Lorsque j’ai appris à développer sous Symfony, il y a un point qui m’a fait tout de suite extrêmement peur, de par sa complexité au premier abord, c’est la gestion de la connexion des utilisateurs. Mais, avec un peu d’entraînement, tout devient extrêmement simple à mettre en place.

Aujourd’hui, nous allons aborder le sujet en créant un simple espace sécurisé pour un administrateur unique.

Lire la suite de

Il existe beaucoup de Bundle permettant de mettre en place un système de pagination au sein de votre projet Symfony. Le plus connu étant KNP Paginator qui, il est vrai, m’a beaucoup aidé à mes débuts. Mais ils ont tous un énorme défaut : l’optimisation.

En effet, pour créer une pagination sur une requête avec Doctrine, il nous faut une information cruciale : le nombre total de résultats. Ainsi, ils exécutent la requête sur l’intégralité de votre base, comptent le nombre de résultats obtenus, puis « coupent » les résultats pour ne retourner que ceux voulus (voir, pour certains, effectuent une seconde requête).

Dans les faits, ça fonctionne, mais dès que vous essayez de paginer une liste de plus d’un millier de résultat, votre serveur commence alors à prendre très cher, rallongeant beaucoup le temps de chargement pour vos visiteurs.

Pourtant, Doctrine, intégré à Symfony, a mis en place, depuis Janvier 2012, la méthode Paginator qui permet d’optimiser très simplement un sytème de pagination.

Pour les besoins d’un de mes projets professionnels, j’ai eu l’occasion d’automatiser la chose avec un nouveau Bundle, que je vous mets à disposition : Tiloweb Pagination Bundle (très original).

Lire la suite de

Il peut arriver, dans certains de vos projets Symfony, que vous deviez appeler une fonction spécifique dans toutes vos actions d’un controller en particulier. Mais voila, vous êtes également dépendant de vos services, qui ne sont disponibles qu’à l’intérieur de vos actions.

L’astuce consiste ici à surcharger chacune des actions de vos controllers automatiquement, pour leur demander d’exécuter le même code avant même de s’exécuter elle-même. Vous bénéficiez ainsi des mêmes dépendances que vos actions ainsi que du même environnement.

Lire la suite de

Il peut arriver certains cas où vous avez tout intérêt à définir des variables spécifiques à votre environnement de développement ou de production tout en gardant exactement le même code pour votre application (dans le cas de l’utilisation de git par exemple, ou simplement si vous travaillez en local avant la mise en production). Plus concrètement, vous pouvez vouloir changer les informations de connexion à votre base de donnée en fonction de votre environnement sans que ça impact votre code.

La solution la plus commune reste alors à déterminer dans votre code dans quel environnement vous vous trouvez :

if($_SERVER['HTTP_HOST'] == 'localhost') {
    // Environnement de développement
} else {
    // Environnement de production
}

Mais très honnêtement, cela peut apporter son lot de complications. A savoir, devoir modifier et redéployer son application à chaque changement pour le moindre environnement par exemple, ou ça devient vite ingérable si vous en utilisez plusieurs.

Une solution bien plus simple existe alors. Pour cela, il suffit de déclarer vos variables directement à l’intérieur même de votre environnement et simplement de les récupérer de manière transparente dans votre application. Pour cela, il suffit d’utiliser en PHP la fonction getenv($var) pour récupérer la variable $var que vous aurez déclaré dans votre votre vhost apache ou votre htaccess à l’aide de la commande SetEnv $var value

Exemple

Pour illustrer cette méthode, nous allons imaginer une application déployée sur 2 environnements différents. La première plateforme est celle de développement répondant à l’URL http://dev.application.com et devra se connecter sur le serveur de base de donnée de développement 123.456.789.0. La seconde plateforme est celle de production répondant à l’URL http://www.application.com et devra se connecter sur le serveur de base de donnée de production 123.456.789.1.

Vhost Apache :

# Développement
<VirtualHost *:80>
    ServerAdmin admin@application.com
    ServerName dev.application.com
    DocumentRoot /var/www/application/dev/

    SetEnv DBHOST 123.456.789.0
    SetEnv DBUSER application_dev
    SetEnv DBPASS application123
    SetEnv DBNAME application_dev

    <Directory /var/www/application/dev/>
        Options -Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        allow from all
     </Directory>
</VirtualHost>

# Production
<VirtualHost *:80>
    ServerAdmin admin@application.com
    ServerName www.application.com
    DocumentRoot /var/www/application/www/

    SetEnv DBHOST 123.456.789.1
    SetEnv DBUSER application_www
    SetEnv DBPASS application123
    SetEnv DBNAME application_www

    <Directory /var/www/application/www/>
        Options -Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        allow from all
     </Directory>
</VirtualHost>

Application PHP

$db = new PDO('mysql:host='. getenv('DBHOST').';dbname='.getenv('DBNAME'),
               getenv('DBUSER'),
               getenv('DBPASS'));

Et voila votre application communique maintenant avec votre environnement et est prête à être déployée où vous le voulez.

Récemment (très récemment en fait … hier), j’ai subi quelques soucis avec un serveur mit hors-ligne par mon hébergeur sans me prévenir (ouh le méchant OVH). Le soucis le plus important, c’est que je m’en suis rendu compte un peu tard, à savoir, le lendemain (dur dur l’arrivée au bureau ce matin. Je n’ai même pas eu le temps de mettre en place mon intraveineuse de café). Il existe bien entendu beaucoup de systèmes automatique de monitoring sur le web mais quoi de mieux que de réinventer la roue et surtout, de savoir comment celle-ci fonctionne.

Le principe de notre système va donc être de regarder régulièrement, à l’aide d’une tâche CRON, si le serveur de votre site répond correctement et si celui-ci est bien le bon serveur (une guerre existe au sujet de la prononciation du mot « CRON », un camps prône la tâche « crone » et l’autre, la tâche « cron » . Je préfère pour ma part « cron », ça me permet d’insulter tout le monde de « tâche » automatique sans passer pour un … bref).

I/ Créer la base de donnée

La base de donnée n’a rien de compliqué en soit, il suffit de hiérarchiser toutes les données dont nous avons besoins, à savoir :

  • Le titre du site
  • Le nom de domaine du site
  • L’IP du serveur hébergent le site
  • L’indicateur d’état DNS
  • L’indicateur d’état HTTP
  • La date du dernier changement d’état

Soit en SQL :

CREATE TABLE IF NOT EXISTS `monitoring` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(64) NOT NULL,
`domain` varchar(64) NOT NULL,
`ip` varchar(64) NOT NULL,
`dns` tinyint(1) NOT NULL,
`http` tinyint(1) NOT NULL,
`update` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=58 ;

II/ Créer le script

Pour la création de ce script, je vais assumer le fait que vous soyez correctement connecté à votre base de donnée et que vous utilisez la bibliothèque PDO.

Récupéreration des données

Commençons ainsi par créer notre requête de récupération des données :

$sites = $pdo->query('SELECT * FROM monitoring');
foreach($sites->fetchAll() as $site):
    // Traitement du monitoring HTTP

    // Traitement du monitoring DNS
endforeach;

Tester l’accès HTTP

Ensuite, on va tester si l’accès au site est bien possible. Pour cela, il vous suffit de tenter d’ouvrir une connexion PHP entre votre script et votre serveur avec la fonction fopen pointant sur l’IP. Si la connexion s’effectue, la fonction va vous retourner le code brut de votre script, si votre serveur est indisponible, alors votre fonction retournera false.

$sites = $pdo->query('SELECT * FROM monitoring');
foreach($sites->fetchAll() as $site):
    // Traitement du monitoring HTTP
    $ping = (bool) @fopen('http://'.$site['ip'].'/', "r");

    // Traitement du monitoring DNS
endforeach;

En ajoutant un (bool) avant la fonction, on s’assure que celle-ci ne nous renvoit pas le code source du site, mais simplement la valeur true. de la même manière, en ajoutant un @ avant le nom de la fonction, je demande à PHP de ne pas renvoyer d’erreur mais simplement un false si quelque chose ne se passe pas bien (comme le fait que votre serveur ne réponde pas).

Tester le paramétrage DNS

Nous allons maintenant tester le paramétrage des DNS. Cette étape est assez important en fonction de votre configuration. En effet, nous allons vérifier que le serveur correspondant au nom de domaine est bien le bon. En effet, il existe de nombreux cas ou votre nom de domaine pourrait pointer vers un serveur, certe, fonctionnel, mais ne vous appartenant pas pour autant. (Cela m’arrive malheureusement régulièrement avec des clients qui pensent bien faire en modifiant eux-même leur nom de domaine et qui en fait, plombe totalement leur site internet sans même vous prévenir … Pour après vous en blâmer).

Pour cela, il existe une fonction toute faite ! gethostbyname qui prend comme paramètre le nom de domaine recherché et vous renvoi l’IP vers lequel celui-ci redirige. Il suffit alors de vérifier si l’IP répondu correspond bien à notre IP.

$sites = $pdo->query('SELECT * FROM monitoring');
foreach($sites->fetchAll() as $site):
    // Traitement du monitoring HTTP
    $http = (bool) @fopen('http://'.$site['ip'].'/', "r");

    // Traitement du monitoring DNS
    $dns = gethostbyname($site['domain']) == $site['ip'];
endforeach;

Vérification du monitoring

Il reste tout de même une dernière étape avant d’alerter quiconque en cas de problème. Car effectivement, si dès que vous détectez un soucis dans votre monitoring vous envoyez en e-mail, alors dites-vous que tant que votre problème n’est pas réglé, vous allez harcelé par votre propre serveur. Pour cela, il ne faut donc pas oublier de vérifier que l’état actuel des DNS ou du HTTP est différent du précédant état de votre site.

$sites = $pdo->query('SELECT * FROM monitoring');
foreach($sites->fetchAll() as $site):
    // Traitement du monitoring HTTP
    $http = (bool) @fopen('http://'.$site['ip'].'/', "r");

    // Traitement du monitoring DNS
    $dns = gethostbyname($site['domain']) == $site['ip'];

    if($dns != $site['dns'] || $http != $site['http']):
        // On met à jour le site dans la base de donnée
        $pdo->query('UPDATE monitoring SET http = '.$site['http'].', dns = '.$site['dns'].', time = '.time().' WHERE id = '.$site['id']);

        // On n'alerte qu'à cette condition
    endif;
endforeach;

Alerte

Pour les alertes, je vous laissez gérer comme vous le souhaitez. Vous pouvez vous envoyer un mail, un SMS, une notification push … Tout ce qui compte, c’est que vous ayez toutes les informations nécessaire pour traiter le problème le plus rapidement possible. Ainsi, avec ce script, vous saurez :

  • Depuis combien de temps l’alerte est en place (ou depuis combien de temps le site est en ligne)
  • Qu’est-ce qui empêche vos utilisateurs d’accéder à votre site :
    • Votre serveur ne répond plus ?
    • Vos DNS sont mal configurés ?

III/ Paramétrer la tâche CRON

Il vous manque maintenant le plus important, la mise en production de votre script. Ici, nous allons demander à votre serveur (ce sera un debian 6.0 pour ma part) de lancer votre tâche CRON toutes les 3 minutes. Vous pouvez faire varier cette intervale mais plus elle augmente, moins vous serez réactif, plus elle diminue, plus vos serveurs vont travailler.

Nous supposerons que le chemin d’accès à mon script de monitoring soit à l’adresse suivante : /var/www/monitoring/cron.php et que vous avez les droits d’administration de votre serveur (un petit sudo et hop !)

Nous allons éditer le cron général de votre serveur. Pour se faire, connectez vous à votre terminal puis tapez la commande suivante :

$ crontab -e

Votre fichier CRON va s’ouvrir avec votre éditeur de texte préféré. Il vous suffira alors d’ajouter la ligne suivante :

*/3 * * * * php -f /var/www/monitoring/cron.php

Et voila, votre service de monitoring est en place. C’est plutôt cool, et surtout indispensable de savoir, avant votre client, quand ça va chauffer pour vos oreilles.

Bonjour,

Je ne le souhaite à personne, mais certains d’entre vous vont un jour être confronté à un petit problème : convertir un fichier de configuration excel en PHP. Si les calculs dans ce fichier restent simple, alors ça ne pose pas de soucis, on trouve rapidement les équivalent des fonctions Excels basiques en PHP, comme ARRONDI.INF ou SUM. Mais dès que l’on va un peu plus loin dans les formules excels, là, c’est la catastrophe.

En effet, excel est un logiciel très poussé pour tout ce qui concerne les calculs financiers, et il suffit qu’une des fonctions disponibles dans la librairie financière soit utilisée pour que PHP ne suive plus dans ses fonctions. Il m’est arrivé ce problème aujourd’hui et les réponses sont quasi inexistantes sur google. Après quelques heures de lutte acharnées, de recherche infructueuses et de remémoration de mes cours de terminal S qui remontent bien loins, j’ai réussi à traduire les 3 fonctions les plus utilisées de cette bibliothèque.

Fonction VPM

Cette fonction calcule le remboursement d’un emprunt sur la base de remboursements et d’un taux d’intérêt constants. Retrouvez la documentation de la fonction VPM sous Excel.


function vpm($taux, $npm, $va, $vc = 0, $type = 0){
if(!is_numeric($taux) || !is_numeric($npm) || !is_numeric($va) || !is_numeric($vc) || !is_numeric($type)):
return false;
endif;

if($type > 1|| $type < 0):
return false;
endif;

$tauxAct = pow(1 + $taux, -$npm);

if((1 - $tauxAct) == 0):
return 0;
endif;

$vpm = ( ($va + $vc * $tauxAct) * $taux / (1 - $tauxAct) ) / (1 + $taux * $type);
return -$vpm;
}

Fonction VA

Cette fonction calcule la valeur actuelle d’un investissement. La valeur actuelle correspond à la somme que représente aujourd’hui un ensemble de remboursements futurs. Par exemple, lorsque vous faites un emprunt, le montant de l’emprunt représente la valeur actuelle pour le prêteur. Retrouvez la documentation de la fonction VA sous Excel.


function va($taux, $npm, $vpm, $vc = 0, $type = 0){
if(!is_numeric($taux) || !is_numeric($npm) || !is_numeric($vpm) || !is_numeric($vc) || !is_numeric($type)):
return false;
endif;

if($type > 1|| $type < 0):
return false;
endif;

$tauxAct = pow(1 + $taux, -$npm);

if((1 - $tauxAct) == 0):
return 0;
endif;

$va = $vpm * (1 + $taux * $type) * (1 - $tauxAct) / $taux - $vc * $tauxAct;
return $va;
}

Fonction TAUX

Calcule le taux d’intérêt par période d’un investissement donné. La fonction TAUX est calculée par itération et peut n’avoir aucune solution ou en avoir plusieurs. Retrouvez la documentation de la fonction Taux sous Excel.

function taux($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) {

$rate = $guess;
if (abs($rate) < 20):
$y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
else:
$f = exp($nper * log(1 + $rate));
$y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
endif;
$y0 = $pv + $pmt * $nper + $fv;
$y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;

$i = $x0 = 0.0;
$x1 = $rate;
while ((abs($y0 - $y1) > 0.0000001) &amp;amp;&amp;amp; ($i < 20)):
$rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0);
$x0 = $x1;
$x1 = $rate;

if(abs($rate) < 0.0000001):
$y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
else:
$f = exp($nper * log(1 + $rate));
$y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
endif;

$y0 = $y1;
$y1 = $y;
++$i;
endwhile;

return $rate;
}

Je ne sais pas pour vous, mais je suis à deux doigts de l’indigestion. Mais en tous les cas, j’espère avoir évité à quelqu’un d’entre vous des heures de recherches inutiles.

Bon courage !