mercredi 28 mai 2014

Service avec accès au container sans code

Les services de Symfony2 peuvent accéder au Container. La méthode la plus classique pour déclarer un service ayant accès à ce container est :
# Resources/config/services.yml services: foo: class: Foo\Bar\Service arguments: [ @service_container ]
Et dans votre classe Foo\Bar\Service, vous devez gérer une propriété protected (souvent $container), qui sera remplie dans le __construct :
<?php namespace Foo\Bar; use Symfony\Component\DependencyInjection\ContainerInterface; class Service { protected $container; public function __construct(ContainerInterface $container) { $this->container = $container; } }

Mais vous pouvez également vous simplifier le code du service, en étendant la classe ContainerAware et en utilisant les appels de méthode à l'instaciation de votre service.
ContainerAware ajoute une méthode setContainer et une propriété protected $container.
# Resources/config/services.yml services: foo: class: Foo\BarBundle\Service\MyService calls: - [ setContainer, [ @service_container ] ]
# Resources/config/services.xml <services> <service id="foo" class="Foo\BarBundle\Service\MyService"> <call method="setContainer"> <argument type="service" id="service_container" /> </call> </service> </services>
<?php namespace Foo\BarBundle\Service; use Symfony\Component\DependencyInjection\ContainerAware; class Service extends ContainerAware { }

Supprimer la validation HTML5 dans un formulaire Symfony2

Symfony2 permet de créer des formulaires sécurisés, via FormType.

Dans la méthode buildForm() de votre FormType, vous définissez les champs qui seront affichés dans votre formulaire, dont le bouton submit. Pour indiquer à votre formulaire de ne pas passer l'étape de validation HTML5 (par le navigateur donc), vous devez ajouter l'attribut formnovalidate à ce submit :
$builder->add('save', 'submit', array('label' => 'Enregistrer', 'attr' => array('formnovalidate' => 'formnovalidate')));
Une autre méthode consiste à ajouter l'attribut novalidate lors de la génération de l'HTML de la balise form :
{{ form_start(form, { attr: { novalidate: 'novalidate' } }) }}

mardi 27 mai 2014

DateTime comme clef primaire dans Symfony2 / Doctrine

Symfony2, qui utilise Doctrine, ne permet pas de base de définir un champ de type DateTime comme un identifiant d'entité.

Le problème ne vient ni de Symfony2, ni de Doctrine (quoi que). L'UnitOfWork de Doctrine essaye de convertir en string tous les champs identifiants d'une entité, mais la classe DateTime de PHP ne contient pas la méthode magique __toString().

A cause de ça, si vous définissez un champ de type DateTime en identifiant pour votre entité, vous allez avoir une erreur "Cannot convert DateTime to string".

Le bundle DoctrineBundle vous permet, entre autre, d'ajouter un type de champ PrimaryDateTime. Ce type de champ fonctionne exactement comme DateTime (il l'étend en interne),tout en ajoutant la méthode __toString() qui permet à l'UnitOfWork de fonctionner.

Ajouter un champ de type Base64 à Symfony2 / Doctrine

Symfony2, qui utilise Doctrine, offre par défaut la majorité des types de champ dont on a besoin.

Cependant, le bundle DoctrineBundle permet d'ajouter des types de champ intéressants, dont base64.

Ce type de champ sauvegardera la version Base64 de la valeur de votre champ, et décodera cette valeur lors de la lecture de la base de données.

lundi 26 mai 2014

VHost Apache 2.4 pour Symfony2

Des différences notables, qui cassent la rétro-compatibilité, ont été instaurées dans Apache 2.4. Donc un VirtualHost Apache 2.2 n'est pas compatible avec un VirtualHost Apache 2.4.

Voilà un exemple basique de VirtualHost pour Apache 2.4 et Symfony2 :
<VirtualHost *:80> ServerName sf2.loc ServerAdmin webmaster@localhost DocumentRoot /foo/bar/sf2/web <Directory /foo/bar/sf2/web> AllowOverride All Require all granted Options -Indexes </Directory> ErrorLog ${APACHE_LOG_DIR}/sf2-error.log CustomLog ${APACHE_LOG_DIR}/sf2-access.log combined </VirtualHost>

dimanche 25 mai 2014

Normes de dev Symfony2 dans NetBeans

NetBeans, éditeur PHP (mais aussi C/C++, Java, etc) gratuit, permet de formater automatiquement le code quand on sauvegarde (CTRL + S).

Pour configurer le formatage à la sauvegarde, il faut aller dans Tools / Options / Editor / On Save, choisir PHP pour Laguage et All Lines pour Reformat et Remove Trailing Whitespace From.

Par défaut, un projet NetBeans utilisera les codes de formatages indiqués au niveau de l'éditeur (dans Tools / Options / Editor / Formatting). Mais on peut lui indiquer des codes de formatages spécifiques par projet, en faisant un click droit sur le projet, puis Properties / Formatting.

Cette configuration par projet sera sauvegardée dans nbprojet/project.properties. Voici celle qui vous permettra de respecter les normes de développement Symfony2 :
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=true auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=4 auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=4 auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8 auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80 auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-line-wrap=none auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.blankLinesAfterClass=0 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.blankLinesAfterField=0 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.blankLinesAfterOpenPHPTag=0 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.blankLinesBeforeField=0 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.classDeclBracePlacement=NEW_LINE auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.continuationIndentSize=4 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.expand-tabs=false auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.indent-shift-width=4 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.methodDeclBracePlacement=NEW_LINE auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.spaces-per-tab=4 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.tab-size=4 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.text-limit-width=120 auxiliary.org-netbeans-modules-editor-indent.text.x-php5.CodeStyle.project.text-line-wrap=none

Symfony 2.4.5

Symfony 2.4.5 vient d'être packagé, avec une trentaine de bugs corrigés.

Si vous utilisez Symfony 2.4.4, il est conseillé de passer sur la 2.4.5, la rétro compatibilité étant totale.

vendredi 23 mai 2014

Activer le Configuration Storage de phpMyAdmin

phpMyAdmin a énormément d'options cachées, que l'on doit soit connaître soit se faire dévoiler par un collègue.

Le Configuration Storage ajoute de très grosses fonctionnalités dans phpMyAdmin, et s'installe facilement. Il permet par exemple d'ajouter un onglet Concepteur, qui génère un MCD de votre base de données.

1) Importer les tables nécessaires pour le Configuration Storage
mysql -u%USER% -p%PASSWORD < examples/create_tables.sql mysql -u%USER -p%PASSWORD% < examples/upgrade_tables_mysql_4_1_2+.sql
2) Activer le Configuration Storage
Vous devez décommenter toutes les lignes après le commentaire "phpMyAdmin configuration storage settings." (sauf auth_swekey_config, à vous voir pour celle là) dans le fichier config.inc.php :
/* * phpMyAdmin configuration storage settings. */ /* User used to manipulate with storage */ $cfg['Servers'][$i]['controlhost'] = 'localhost'; $cfg['Servers'][$i]['controlport'] = ''; $cfg['Servers'][$i]['controluser'] = '%USER%'; $cfg['Servers'][$i]['controlpass'] = '%PASSWORD'; /* Storage database and tables */ $cfg['Servers'][$i]['pmadb'] = 'phpmyadmin'; $cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark'; $cfg['Servers'][$i]['relation'] = 'pma__relation'; $cfg['Servers'][$i]['table_info'] = 'pma__table_info'; $cfg['Servers'][$i]['table_coords'] = 'pma__table_coords'; $cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages'; $cfg['Servers'][$i]['column_info'] = 'pma__column_info'; $cfg['Servers'][$i]['history'] = 'pma__history'; $cfg['Servers'][$i]['table_uiprefs'] = 'pma__table_uiprefs'; $cfg['Servers'][$i]['tracking'] = 'pma__tracking'; $cfg['Servers'][$i]['designer_coords'] = 'pma__designer_coords'; $cfg['Servers'][$i]['userconfig'] = 'pma__userconfig'; $cfg['Servers'][$i]['recent'] = 'pma__recent'; $cfg['Servers'][$i]['favorite'] = 'pma__favorite'; $cfg['Servers'][$i]['users'] = 'pma__users'; $cfg['Servers'][$i]['usergroups'] = 'pma__usergroups'; $cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding'; $cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches'; /* Contrib / Swekey authentication */ // $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
3) Pensez à vous déconnecter / reconnecter sur phpMyAdmin

Cacher les tables système dans phpMyAdmin

phpMyAdmin, outil très puissant pour gérer vos bases de données MySQL via une interface graphique Web, a énormément de configrations possibles.

Tout se passe généralement dans config.inc.php (fichier de configuration qui surcharge config.sample.inc.php).

Vous pouvez cacher certaines bases de données. Voici un exemple pour cacher celles de MySQL (et de phpMyAdmin quand on installe le Configuration Storage) :
$cfg['Servers'][$i]['hide_db'] = '^(information_schema|performance_schema|mysql|phpmyadmin)$';

jeudi 22 mai 2014

PHP Tour Lyon 2014

L'AFUP organise un apéro PHP à Lyon, les 23 et 24 juin 2014.

Les thèmes suivants seront notamment abordés :

  • mouvement DevOps
  • méthodologies agiles
  • tests du code
  • méthodologie de modélisation

Avec Gérald Croës (mon ancien architecte technique chez Alptis Assurances) en conférencier pour les méthodologies de modélisation.

mardi 20 mai 2014

PHP5, Symfony2, Twig et internationalisation

L'extension PHP Intl permet de faciliter l'internationalisation de votre code.

Pour pouvoir l'utiliser dans Symfony2, et plus précisément dans Twig, vous devez installer l'extension php5-intl :
sudo apt-get install php5-intl && sudo service apache2 restart
Et activer le service Twig_Extensions_Extension_Intl (par exemple dans app/config/config.yml) :
services: twig.extension.intl: class: Twig_Extensions_Extension_Intl tags: - { name: twig.extension }
Ensuite, vous pouvez utiliser le filtre localizeddate :
{{ mydate|localizeddate('long') }} => '20 mai 2014 15:03:39'

jeudi 15 mai 2014

Valeur d'une variable Twig en clef de tableau

Twig, moteur de template notamment intégré dans Symfony2, permet de simplifier la création de templates.

Cependant, il peut arriver qu'on ait des besoins particuliers, comme avoir la valeur d'une variable comme clef d'un tableau. Il suffit alors d'entourer notre variable de parenthèses, pour que Twig comprenne qu'il doit mettre la valeur de la variable et non pas le texte :
{% set myKey = 'foo' %} {% set myArray = { (myKey): 'bar' } %}

mercredi 14 mai 2014

PS1 en couleur avec séparateur

En bash, PS1 représente le code qui sera exécuté avant de vous donner la main pour écrire une commande.

De base, il n'y a pas (ou très peu) de couleurs, et pas de fonctionnalités avancées. Pour ajouter de la couleur, la branche du dépot Git si le répertoire courant est un projet Git, etc, ajoutez ceci à la fin de votre ~/.bashrc :

 function parse_git_branch {  
     var=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/' -e 's/(//g' -e 's/)//g')  
     if [[ $var != "" ]] ; then  
         echo -e "\033[33m$(git config core.description)\033[00m [\033[33m$var\033[00m]";  
     fi  
 }  
 PS1='$(for (( i=0; i<$COLUMNS; i++ )); do echo -n '_'; done;)\n[\033[31m\u@\h\033[00m] [\033[32m\w\033[00m] $(parse_git_branch) \n\$ '  

Pour donner un nom à votre projet Git :

 git config core.description NomDeMonProjet  

Résultat :

Définir l'environement Symfony2 dans Composer

Lors d'un composer update, ou composer install (je vous laisse découvrir composer), et dans le cas d'un projet Symfony2, un script est exécuté pour vider le cache.

Ce script est définit dans le composer.json :
{ "scripts": { "post-install-cmd": [ "...\\ScriptHandler::clearCache" ], "post-update-cmd": [ "...\\ScriptHandler::clearCache" ] } }
Seulement voilà, ce script ne prend pas l'environement Symfony2 en paramètre. Du coup, composer l'appelle directement, et ce script appelle la commande "php app/console cache:clear".

Quand on ne passe pas d'environement à la console Symfony2, elle va chercher dans la variable d'environement SYMFONY_ENV, sinon, elle utilise "dev".

Donc pour définir cet environement, sans pour autant définir une variable au niveau système (qui pourrait casser d'autres environements Symfony2 installés sur le même serveur), il suffit d'appeler composer comme ceci :
SYMFONY_ENV=prod composer install --no-dev --optimize-autoloader

Installation de composer

Composer permet de gérer des dépendances dans votre projet, souvent sur GitHub.

L'installation est très facile, il manque cependant ces commandes plus complètes dans la documentation :

Version Linux
 sudo wget https://getcomposer.org/composer.phar /usr/bin/composer && chmod +x /usr/bin/composer  

Version MAC
 sudo curl -sS https://getcomposer.org/composer.phar | sudo php -- --install-dir=/usr/local/bin --filename=composer  

mardi 13 mai 2014

Machines virtuelles pour tester Internet Explorer

Tous les développeurs web sont confrontés au même problème : gérer la compatibilité du code html / css entre les différents navigateurs. Si les différences entre Chrome et Firefox posent très peu de problèmes, c'est bien sûr Internet Explorer le retardataire ... bien qu'à partir de la version 9, on commence à entrevoir des possibilités intéressantes.

Pour tester toutes les versions d'Internet Explorer, sur plusieurs Windows, vous pouvez télécharger des machines virtuelles sur ce site :

Git status sur tous les repositories d'un répertoire

Le gestionnaire de version Git est en train de remplacer SVN (qui a lui-même remplacé CVS et SourceSafe).

Quand on développe un projet avec Composer, on a un répertoire vendor qui contient toutes les dépendances installées via Composer. Parfois on effectue des modifications dans ce vendor, et il peut arriver qu'on exécute composer update alors qu'on a du code modifié à pusher.

C'est là qu'intervient gitstatus.sh, qui permet de scanner tous les repositories d'un répertoire, et d'effectuer un git status sur chacun d'entre eux :


L'installation est très facile :
git clone https://github.com/kujaff/gitscripts.git ~/dev/gitscripts echo "alias gs='~/dev/gitscripts/status.sh'" >> ~/.bashrc source ~/.bashrc

Formater du code pour BlogSpot avec CodeFormatter

Un blog de codeur sans code n'est pas un vrai blog de codeur.

Le code non formatté étant dur à lire, ce blog vous permet d'écrire votre code (n'importe quel language) et de le formatter selon quelques critères :

Correction de maxStrLength dans CgKintBundle

Pour dumper facilement des variables, CgKintBundle met à disposition une fonction PHP et une fonction Twig.

Seulement ce bundle a un bug, sur la gestion de la config maxStrLength. Cette config permet d'indiquer le nombre de caractères maximaux qui seront affichés lors d'un dump d'une variable de type string.
Cette configuration est mal lue, et donc n'est pas prise en compte au final.

Pour corriger ce bug, il faut modifier votre AppKernel :

class AppKernel extends Kernel { protected function initializeContainer() { parent::initializeContainer(); \Kint::$maxStrLength = 1000; } }