Debugger un projet Zend MVC à distance avec Netbeans et Xdebug

logo-zend-frameworkContexte

Débugger pas à pas une application Php basée sur Zend Framework, hébergée sur un serveur distant Ubuntu 14.04.
Les sources du projet Netbeans sont donc distantes.

Prérequis

– Activer XDebug sur le serveur

Au cas où il ne serait pas déjà installé

sudo apt-get install php5-xdebug

Par défaut, l’extension n’est pas active. Pour l’activer

sudo php5enmod xdebug

Il faut maintenant activer le debugging à distante en ajoutant la directive remote_enable au fichier /etc/php5/mods-available/xdebug.ini. Il doit ressembler à ça

zend_extension=xdebug.so
xdebug.remote_enable=On

Redémarrer Apache et xdebug devrait apparaitre avec phpinfo()
xdebug
– Créer un tunnel SSH

Afin que Xdebug puisse communiquer correctement avec Netbeans, il faut que le serveur puisse se connecter au client.

Avec Putty, configurer la connexion et ajouter une redirection de port dans la section SSH > Tunnels

putty-xdebug

Netbeans

Menu Tools > Options > Php > Debugging

Décocher « Stop at first line »

netbeans-debug

Ouvrir le projet dans Netbeans, aller dans les propriétés du projet, section Run configuration.
Ouvrir les propriétés avancées
Cocher « Ask every time » de façon à pouvoir debugger n’importe quelle url sans avoir à passer par la page d’accueil.
Ajouter les correspondances de chemins pour que Netbeans fasse la correspondance entre l’arborescence locale et celle distante. Un mapping du repertoire racine de l’application doit suffire.
Pour ceux qui veulent aussi debugger le framework, il suffit de disposer des sources du framework en local et d’ajouter le mapping correspondant (et surement l’ajouter dans l’include path au passage).
netbeans-project

Exécution !

Il ne reste plus qu’à ouvrir le script qu’on veut tester, y placer un point d’arrêt et balancer la sauce par CTRL+F5.

Customiser un flux Atom ou Rss avec Zend_Feed_Writer

logo-zend-frameworkSuite de notre aventure dans la jungle de Zend_Feed_Writer. Maintenant qu’on sait faire un flux standard, nous allons le modifier quelque peu.

Reprenons l’exemple:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Titre</title>
  <link rel="self" type="application/atom+xml" href="/"/>
  <id>Ze Id</id>
  <entry>
    <title>entrée</title>
    <link rel="alternate" type="text/html" href=""/>
  </entry>
</feed>

Pour obtenir la balise link, en vert, nous nous sommes servi de $f->setFeedLink(‘/’,’atom’); Cette fonction a pour effet d’ajouter l’url en paramètre au conteneur ($_data[‘feedLinks’]).

Voilà qui est bien mais comment faire si l’on souhaite changer le type ou l’attribut rel, voire même ajouter un attribut?

Contexte

Lors de l’export atom par exemple, le moteur va lancer le rendu de toutes les balises standards via les méthodes appropriées (voir dans la classe Zend_Feed_Writer_Renderer_Entry_Atom). Ces méthodes vont chercher l’information dans le conteneur de données ($_data) et créer les élements XML qui vont bien.
Pour modifier des balises ou des attributs, Zend_Feed_Writer fait alors appel à des extensions. Il y a les extensions pour le conteneur et celles pour le rendu.
Le rendu des extensions est demandé une fois que le rendu standard est terminé.

Il existe un certains nombre d’extensions disponibles dans le framework pour les specifications les plus connues : Content, DublinCore, Itunes, Slash, Threading et WellFormedWeb.

Imaginons que nous souhaitons créer une extension pour ajouter le support des spécifications Open Publication Distribution System. Il est dit dans cette spec que l’attribut type du tag <link rel=self> doit être

application/atom+xml;profile=opds-catalog;kind=navigation

Nouvelle extension

Sous le répertoire library du projet, créer l’arborescence et un fichier Opds/Feed/Writer/Extension/Opds/Renderer/Feed.php

Créer la classe de cette façon

<?php
/**
 * @see Zend_Feed_Writer_Extension_RendererAbstract
 */
require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';

class Opds_Feed_Writer_Extension_Opds_Renderer_Feed
    extends Zend_Feed_Writer_Extension_RendererAbstract
{
    /**
     * Set to TRUE if a rendering method actually renders something. This
     * is used to prevent premature appending of a XML namespace declaration
     * until an element which requires it is actually appended.
     * @var bool
     */
    protected $_called = false;

    /**
     * Render feed
     * @return void
     */
    public function render()
    {
        if (strtolower($this->getType()) != 'atom') {
            return;
        }
        $this->_setFeedLinks($this->_dom, $this->_base);
        if ($this->_called) {
            $this->_appendNamespaces();
        }
    }

    /**
     * Append namespaces to feed element
     *
     * @return void
     */
    protected function _appendNamespaces()
    {
        $this->getRootElement()->setAttribute('xmlns:opds',
            'http://opds-spec.org/2010/catalog');
    }

    /**
     * Set feed link elements
     *
     * @param  DOMDocument $dom
     * @param  DOMElement $root
     * @return void
     */
    protected function _setFeedLinks(DOMDocument $dom, DOMElement $root)
    {
        $links = $root->getElementsByTagName('link');
        foreach ($links as $link) {
            if ($link->getAttribute('rel') == 'self') {
                $mime  = 'application/atom+xml;profile=opds-catalog;kind=navigation';
                $link->setAttribute('type', $mime);
            }
        }
        $this->_called = true;
    }
}

Le point d’entrée est la méthode render(), c’est elle qui est appelée pour chaque extension.
C’est _setFeedLink qui va ensuite modifier l’attribut « type » de l’élement.
_called permet de savoir si au moins une fonction de l’extension a été appelée et, le cas échéant, ajoute l’espace de nom correspondant à la spécification via _appendNamespaces().

Enregistrement de l’extension

Pour que la méthode render soit appelée automatiquement, il faut enregistrer l’extension.
Dans le contrôleur, ajouter  dans la méthode init() les instructions:

Zend_Feed_Writer::addPrefixPath('Opds_Feed_Writer_Extension', 'Opds/Feed/Writer/Extension');
Zend_Feed_Writer::registerExtension('Opds');

Résultat

Si tout va bien, le résultat devrait être:

<link rel="self" type="application/atom+xml;profile=opds-catalog;kind=navigation" href="/"/>

De la même façon, on peut ajouter des tags non standards en utilisant une extension de conteneur et une extension de rendu.