Un environnement de développement PHP avec Vim

Dans cet article, on va mettre en place un environnement de développement pour le web assez léger et complet avec que des bonnes choses libres dedans.
1/ L’édition
On va utiliser vim. Dans un premier temps, on l’installe donc.
Chez moi: emerge -uD vim
On active la numérotation des lignes et les replis en ajoutant ceci à votre ~/.vimrc :

:set number
:set foldmethod=marker

La seconde ligne permet d’activer le replis dans les fichiers. Pour ceci, vous devez ajouter en commentaire au début de votre fichier, l’entrée:

vim: foldmarker MARKER_DEBUT,MARKER_FIN

Remplacez MARKER_DEBUT et MARKER_FIN par ce que vous souhaitez (du genre ‘{{{‘ et ‘}}}’). Il vous suffit après de délimiter vos blocs avec ces deux marqueurs. Un petit z-o pour ouvrir le bloc et z-c pour le fermer.

Puis phpdoc:
Le greffon PDV (PhpDocumentor for Vim) permet d’ajouter rapidement des commentaires et tags phpdoc dans vos scripts.
Une fois celui-ci installé, il vous faudra modifier votre fichier ~/.vimrc en lui ajoutant les lignes suivantes:

source ~/.vim/plugin/php-doc.vim
imap <C-o> <ESC>:set paste<CR>:call PhpDoc()<CR>:set nopaste<CR>

Après ceci, un petit CTRL+o en mode édition ajoutera un bloc commentaire avec des infos à compléter.

Puis l’auto-complétion des commandes:
Téléchargez le greffon ici puis on met fichier dans ~/.vim/plugin/
Téléchargez le second greffon ici puis on met fichier dans ~/.vim/autoload/
Récupérez aussi le fichier contenant la liste des commandes php ici et on le place dans ~/.vim/syntax/
Toujours dans le ~/.vimrc on ajoute:

set complete=.,w,b,u,t,i,k~/.vim/syntax/php.api
autocmd FileType php set omnifunc=phpcomplete#CompletePHP
source ~/.vim/plugin/word_complete.vim
call DoWordComplete()

On va enfin modifier la configuration de ~/.vim/plugin/word_complete.vim pour mettre l’auto-complétion avec une chaîne d’au moins 3 caractères:

" ==================== file word_complete.vimrc ====================
" User Configuration file for word_complete.vim .
" To use this, uncomment and change the defaults. 

" Do not complete words shorter than this length:
let g:WC_min_len = 3
" Use this key to accept the offered completion:
let g:WC_accept_key = "<Tab>"
" ==================== end: word_complete.vimrc ====================

La seconde ligne surlignée vous permet de changer la touche d’acceptation de la complétion.

Puis la coloration syntaxique:
Ajoutez dans votre ~/.vimrc ceci:

syntax on
filetype on

La seconde ligne active la détection des types de fichiers.
Vous pouvez mettre à jour la coloration syntaxique avec la version php 5.3 via ce lien. Dans l’archive, il y a un script php à exécuter en ligne de commande qui vous permettra de mettre à jours vous-même le-dit fichier.

Enfin la vérification de votre code avec php:
Ici, on va redéfinir la commande makeprg (make programme) de vim pour la faire pointer vers la version cli de php avec l’option -l:

set makeprg=/usr/lib64/php5.4/bin/php\ -l\ %
nmap <F9> :make<ENTER>:copen<ENTER><CTRL>L

Maintenant à chaque fois que vous utiliserez la touche F9, cela déclenchera php -l sur votre fichier en cours d’édition

2/ Le Débogage
Pour le débogage sous PHP on a le choix de le faire à grands coups de var_dump() (qui devient vite pénible) ou d’utiliser une extension de PHP xdebug. Celle-ci s’installe donc sur le serveur et se déclenche automatiquement (selon sa configuration) lorsque le serveur reçoit une requête http avec le paramètre XDEBUG_SESSION_START=1.
* PHP
L’installation se fait de la manière la plus simple avec un petit:

pecl install xdebug

Si vous voulez une installation plus spécifique: installation xdebug
Après vous ajoutez cette ligne à votre php.ini:
zend_extension=”/usr/local/php/modules/xdebug.so”
Et vous devez paramétrer le fichier de configuration de xdebug (chez moi: /etc/php/apache2-php5.4/xdebug.ini). Le miens ressemble à ça:

zend_extension=/usr/lib64/php5.4/lib/extensions/no-debug-zts-20100525/xdebug.so
xdebug.auto_trace="1"
xdebug.trace_output_dir="/dir_Traces"
xdebug.trace_output_name="trace.%c"
xdebug.trace_format="0"
xdebug.trace_options="0"
xdebug.collect_includes="1"
xdebug.collect_params="0"
xdebug.collect_return="0"
xdebug.collect_vars="0"
xdebug.default_enable="0"
xdebug.extended_info="1"
xdebug.manual_url="http://www.php.net"
xdebug.max_nesting_level="100"
xdebug.show_exception_trace="0"
xdebug.show_local_vars="0"
xdebug.show_mem_delta="0"
xdebug.dump.COOKIE="NULL"
xdebug.dump.ENV="NULL"
xdebug.dump.FILES="NULL"
xdebug.dump.GET="NULL"
xdebug.dump.POST="NULL"
xdebug.dump.REQUEST="NULL"
xdebug.dump.SERVER="NULL"
xdebug.dump.SESSION="NULL"
xdebug.dump_globals="1"
xdebug.dump_once="1"
xdebug.dump_undefined="0"
xdebug.profiler_enable="0"
xdebug.profiler_output_dir="/dir_Profiles"
xdebug.profiler_output_name="callgrind.out.%p"
xdebug.profiler_enable_trigger="1"
xdebug.profiler_append="1"
xdebug.profiler_aggregate="0"
xdebug.remote_enable="1"
xdebug.remote_handler="dbgp"
xdebug.remote_host="localhost"
xdebug.remote_mode="req"
xdebug.remote_port="9000"
xdebug.remote_autostart="0"
xdebug.remote_log=""
xdebug.idekey=""
xdebug.var_display_max_data="512"
xdebug.var_display_max_depth="2"
xdebug.var_display_max_children="128"

J’ai surligné les lignes importantes. Évidemment, vous devez adapter les paramètres à votre système (du genre dir_Profiles et dir_Traces).

* vim
Pour utiliser xdebug avec vim, vous devez installer le greffon suivant: dbgp remote debugger.
Pour cela vous copiez les fichiers debugger.py et debugger.vim de l’archive dans votre répertoire: ~/.vim/plugin/
Une fois le greffon installé, il vous suffira d’appuyer sur F5 dans vim et vous aurez 10 secondes pour lancer votre requête http dans votre navigateur.
Pour ce faire, vous avez deux possibilités:
Passer un paramètre à la requête: http://adresse_du_site?XDEBUG_SESSION_START=1 ou
si vous utilisez firefox, celui-ci possède une extension bien pratique dans notre cas: easy xdebug. Celle-ci permet de déclencher le débogage à distance et le profilage de vos scripts via l’appuie sur deux boutons.

Une fois le débogueur lancé, F2 vous amène à l’instruction suivante, F3 vous fait sauter au bloc suivant, F12 vous donne le contenu de la variable sur laquelle se trouve votre curseur et F5 vous amène au point d’arrêt suivant ou à la fin du script.
:Bp permet d’ajouter ou d’ôter des points d’arrêt.

3/ Le profilage
* Qcachegrind
Qcachegrind est une partie du projet KCachegrind que vous trouverez ici.
L’installation se fait très facilement.
Dans un premier temps, vous téléchargez les sources de KCachegrind, décompressez l’archive. Puis vous vous rendez dans le sous-répertoire qcachegrind et vous tapez:

qmake
make

Si tout se passe bien vous devriez obtenir un binaire qcachegrind dans le-dit répertoire.
Il suffira ensuite de lancer l’application et d’ouvrir avec les fichier callgrind générés par xdebug (Cf la configuration de xdebug plus haut, ligne 31).

Voici à quoi cela ressemble:
QCacheGrind

4/ Goodies
* pdepend est un petit logiciel qui permet de faire de la métrologie logicielle. Il vous sortira des graphiques exprimant un certain nombre de mesures (comme le nombre total d’appel de méthodes, le nombre de classes ou encore la complexité cyclomatique du code) au format svg.
Pour l’installer il faut passer par PEAR.

pear channel-discover pear.pdepend.org
pear install pdepend/PHP_Depend

Pour générer les graphiques tapez:

pdepend --overview-pyramid=./graphique-pyramide.svg --jdepend-chart=./diagramme-dep.svg ./arborescence-du-code

Ceci vous créera deux images svg.

Voici le type de diagrammes que vous obtiendrez:
Diagramme pyramideDiagramme dépendances

* Dia est un logiciel qui permet de faire des diagrammes et schémas. Il possède notamment une librairie UML permettant de faire tous vos diagrammes de classes, et autres.
Autre intérêt et non des moindres, on peut installer un greffon qui se nomme uml2php5 qui permet d’exporter directement vos schémas de classes sous formes de squelettes php
(et ceci est paramétrable en plus!).
Pour l’installation de dia, reportez-vous à votre distribution.
Voici une image de l’interface:
Interface Dia
Après, on va installer uml2php5: Allez ici et téléchargez le paquet. Les instructions d’installation sont relativement claires.
En rapide, il suffit de décompresser l’archives et de copier 5 fichiers (stylesheet.xml, dia-uml-classes.zx, dia-uml2php5.zx, dia-uml2phpsoap.zx et dia-uml2php5.conf.xsl) dans le répertoire de dia contenant les spécifications des greffons, chez, moi il se trouve ici: /usr/share/dia/xslt
Le fichier de configuration de uml2php5 est: dia-uml2php5.conf.xsl

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <!--
                Parameter       : INDENT_STR
                Values          : 	 [TAB] or SPACE CHAR(s)
                Comment         : if you want you can replace [TAB] with [SPACE] char(s)
        -->
        <xsl:param name="INDENT_STR"><xsl:text>	</xsl:text></xsl:param>
        <!--
                Parameter       : CLOSE_TAG
                Values          : ON / OFF
                Comment         : if you want source code ended or not by '?>'
        -->
        <xsl:param name="CLOSE_TAG">ON</xsl:param>
        <!--
                Parameter       : CLASS_FILE_EXTENSION
                Values          : .class.php / whatever you want
                Comment         : define file extension for classes
        -->
        <xsl:param name="CLASS_FILE_EXTENSION">.class.php</xsl:param>
        <!--
                Parameter       : INTERFACE_FILE_EXTENSION
                Values          : .interface.php / whatever you want
                Comment         : define file extension for interfaces
        -->
        <xsl:param name="INTERFACE_FILE_EXTENSION">.interface.php</xsl:param>
        <!--
                Parameter       : GENERATE_DOC_TAGS
                Values          : ON / OFF
                Comment         : if you want document your source code or not
        -->
        <xsl:param name="GENERATE_DOC_TAGS">ON</xsl:param>
        <!--
                Parameter       : COMPOSITION_IMPLICIT_NAMING
                Values          : ON / OFF
                Comment         : generate or not composition attribute if role is missing
        -->
        <xsl:param name="COMPOSITION_IMPLICIT_NAMING">ON</xsl:param>
        <!--
                Parameter       : AGGREGATION_IMPLICIT_NAMING
                Values          : ON / OFF
                Comment         : generate or not aggregation attribute and method
        -->
        <xsl:param name="AGGREGATION_IMPLICIT_NAMING">ON</xsl:param>
        <!--
                Parameter       : AUTO_EXPAND_INTERFACES
                Values          : ON / OFF
                Comment         : generate interface methods automaticaly
        -->
        <xsl:param name="AUTO_EXPAND_INTERFACES">ON</xsl:param>
        <!--
                Parameter       : _AUTHOR_
                Values          : Name <email>
                Comment         : define the content of @author tag
        -->
        <xsl:param name="_AUTHOR_">Alexandre Keledjian &lt;dervishe@yahoo.fr&gt;</xsl:param>
        <!--
                Parameter       : _COPYRIGHT_
                Values          : Any
                Comment         : define the content of @copyright tag
        -->
        <xsl:param name="_COPYRIGHT_">AFPD</xsl:param>
        <!--
                Parameter       : _LICENSE_
                Values          : URL Name
                Comment         : define the content of @license tag
        -->
        <xsl:param name="_LICENSE_">http://www.gnu.org/licenses</xsl:param>
        <!--
                Parameter       : TRANSLATE_CONSTRUCTOR
                Values          : ON / OFF
                Comment         : translate the name of the constructor to __construct
        -->
        <xsl:param name="TRANSLATE_CONSTRUCTOR">ON</xsl:param>
        <!--
                Parameter       : TRANSLATE_DESTRUCTOR
                Values          : ON / OFF
                Comment         : translate the name of the ~destructor to __destruct
        -->
        <xsl:param name="TRANSLATE_DESTRUCTOR">ON</xsl:param>
        <!--
                Parameter       : _CR
                Values          : Linux : 
 Windows : 

                Comment         : Define cariage return/Line feed
        -->
        <xsl:param name="_CR"><xsl:text>
</xsl:text></xsl:param>
        <!--
                Parameter       : AUTO_SETTERS_GETTERS
                Values          : ON/OFF (default: OFF)
                Comment         : allows generation of setters/getters for private data
        -->
        <xsl:param name="AUTO_SETTERS_GETTERS"><xsl:text>ON</xsl:text></xsl:param>
        <!--
                Parameter       : SOAP_SERVER_URL
                Values          : Any (default: URL/)
                Comment         : SOAP server url (ie: xxxx.yyyy.zzz/ )
        -->
        <xsl:param name="SOAP_SERVER_URL"><xsl:text>URL/</xsl:text></xsl:param>
</xsl:stylesheet>

Voici ce que ça donne:
Le schéma de dia:

Et son export en php:

<?php
/**
 *
 * Code skeleton generated by dia-uml2php5 plugin
 * written by KDO kdo@zpmag.com
 * @author     Alexandre Keledjian <dervishe@yahoo.fr>
 * @copyright  AFPD
 */
class Utilisateur {
        /**
         *
         * @var int
         * @access private
         */
        private  $id;
        /**
         *
         * @var int
         * @access private
         */
        private  $id_personne;
        /**
         *
         * @var string
         * @access private
         */
        private  $login;
        /**
         *
         * @var string
         * @access private
         */
        private  $nom;
        /**
         *
         * @var string
         * @access private
         */
        private  $prenom;
        /**
         *
         * @var string
         * @access private
         */
        private  $photo;
        /**
         *
         * @var array
         * @access private
         */
        private  $roles = array();
        /**
         *
         * @var string
         * @access private
         */
        private  $dn;
        /**
         *
         * @var string
         * @access private
         */
        private  $courriel_adm;
        const USR = 'U';
        const SAR = 'SAR';
        const ADM = 'A';
        const SA = 'SA';
        /**
         * @access public
         * @param string $login
         */
        public final  function __construct($login = null) {

        }
        /**
         * @access public
         * @return bool
         */
        public final  function isSuperAdmin() {

        }
        /**
         * renvoie: 1 U1 > U2, -1 U1 < U2 et 0 sinon
         * @access public
         * @param Utilisateur $user1
         * @param Utilisateur $user2
         * @param int $region
         * @return int
         */
        public final  function compare(Utilisateur $user1, Utilisateur $user2, $region) {
        }

        // setters / getters

        public function set_id($value) {
                $this->id = $value;
        }
        public function get_id() {
                return $this->id;
        }
        public function set_id_personne($value) {
                $this->id_personne = $value;
        }
        public function get_id_personne() {
                return $this->id_personne;
        }
        public function set_login($value) {
                $this->login = $value;
        }
        public function get_login() {
                return $this->login;
        }
        public function set_nom($value) {
                $this->nom = $value;
        }
        public function get_nom() {
                return $this->nom;
        }
        public function set_prenom($value) {
                $this->prenom = $value;
        }
        public function get_prenom() {
                return $this->prenom;
        }
        public function set_photo($value) {
                $this->photo = $value;
        }
        public function get_photo() {
                return $this->photo;
        }
        public function set_roles($value) {
                $this->roles = $value;
        }
        public function get_roles() {
                return $this->roles;
        }
        public function set_dn($value) {
                $this->dn = $value;
        }
        public function get_dn() {
                return $this->dn;
        }
        public function set_courriel_adm($value) {
                $this->courriel_adm = $value;
        }
        public function get_courriel_adm() {
                return $this->courriel_adm;
        }
}
?>

* better-snipmate-snippet est un greffon vim (évolution du greffon snipmate) qui permet plein de choses comme la création automatique de bloc de codes ou leur édition plus rapide. Une petite vidéo qui montre les possibilités du greffon initial: ici
Pour l’installer, son auteur préconise l’utilisation du greffon pathogen.
On le télécharge ici. Vous le copiez dans ~/.vim/plugin
Il ne vous reste plus qu’à créer le répertoire ~/.vim/bundle et à rajouter en début de ~/.vimrc la ligne:

call pathogen#infect()

Après il ne vous restera qu’à ajouter les greffons dans un répertoire situé dans ~/.vim/bundle.
Donc pour installer better-snipmate-snippet on va mettre ses sources via git dans ~/.vim/bundle :

cd ~/.vim/bundle
git clone git://github.com/bartekd/better-snipmate-snippets.git

* MySQL-Workbench Si vous voulez de belles images de vos bases de données et / ou les manipuler graphiquement, vous pouvez utiliser MySQL WorkBench, téléchargeable ici.
La version “MySQL Workbench Community Edition” est sous license GPL.
Une petite image de l’interface jolie:
MySQL Workbench

Pour finir, voici à quoi ressemble mon ~/.vimrc:

call pathogen#infect()
:set number
:set fileformat=unix
:set encoding=utf-8
syntax on
filetype on

:set foldmethod=marker
source ~/.vim/plugin/php-doc.vim
imap <C-o> <ESC>:set paste<CR>:call PhpDoc()<CR>:set nopaste<CR>

set complete=.,w,b,u,t,i,k~/.vim/syntax/php.api
autocmd FileType php set omnifunc=phpcomplete#CompletePHP

source ~/.vim/plugin/word_complete.vim
call DoWordComplete()

set makeprg=/usr/lib64/php5.4/bin/php\ -l\ %
nmap <F9> :make<ENTER>:copen<ENTER><CTRL>L

Voilà, on arrive au bout du chemin. Si ça ne vous paraît pas clair, incomplet, voire inexact, n’hésitez pas à faire des remarques, je mettrai à jour au fur et à mesure.

Edit:
(28/09/2012)
* Rajout de la partie coloration syntaxique php 5.3
* Rajout de l’auto-complétion
* Check de syntax avec le client php

Be Sociable, Share!

5 comments to Un environnement de développement PHP avec Vim

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>