Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 13-06-2008 16:32:31

aRKhamTaro
Nouveau membre
Lieu: Rennes
Date d'inscription: 11-06-2008
Messages: 2

[Zend_Layout][1.5] layouts imbriqués

Dans l'atelier Zend_Layout de Developpez.com, Julien Pauli lance l'idée qu'on peut imbriquer des layouts, ce qui m'intéresse fortement.

Après avoir pas mal tourné autour, je ne vois pas du tout comment mettre en place ceci. Il faudrait pouvoir spécifier dynamiquement que la vue utilisée dans une partie d'un layout deviennent un layout elle même.. ou faut il enregistrer plusieurs layouts ?

Est ce que quelqu'un s'est déjà intéressé à la question, et pourrait me mettre sur la voie ..

NiCO

Dernière modification par aRKhamTaro (13-06-2008 16:43:56)

Hors ligne

 

#2 13-06-2008 21:05:09

2mx
Membre
Lieu: Grenoble
Date d'inscription: 06-08-2007
Messages: 125

Re: [Zend_Layout][1.5] layouts imbriqués

Pour cela il faut overloader Zend_Layout, Zend_Layout_Controller_Plugin_Layout et Zend_Layout_Controller_Action_Helper_Layout

L'objectif est d'ajouter une propriété subLayout à Zend_Layout  pour contenir le nom du script à utiliser comme sous template.

Ensuite tu peut utiliser le view helper pour spécifier quelle vue tu veux utiliser comme sous template : $this->layout()->setSubLayout('2column.phtml');


Tu peux t'inspirer de ce que j'ai fait si tu veux :


Code:

require_once 'Zend/Layout.php';

class Mmx_Layout extends Zend_Layout
{
    protected $_subLayout;
    protected $_modulesPath;

    public function setSubLayout($subLayout)
    {
        $this->_subLayout = $subLayout;
    }

    public function getSubLayout()
    {
        return $this->_subLayout;
    }

    public function setModulesPath($modulesPath)
    {
        $this->_modulesPath = $modulesPath;
    }

    public function getModulesPath()
    {
        return $this->_modulesPath;
    }

    /**
     * Static method for initialization with MVC support
     *
     * @param  string|array|Zend_Config $options
     * @return Zend_Layout
     */
    public static function startMvc($options = null)
    {
        if (null === self::$_mvcInstance) {
            self::$_mvcInstance = new self($options, true);
        } else {
            self::$_mvcInstance->setOptions($options);
        }

        return self::$_mvcInstance;
    }

    /** Render layout
     *
     * Sets internal script path as last path on script path stack, assigns
     * layout variables to view, determines layout name using inflector, and
     * renders layout view script.
     *
     * $name will be passed to the inflector as the key 'script'.
     *
     * @param  mixed $name
     * @return mixed
     */
     
    public function render($name = null, $subLayout = null)
    {
        if (null === $name) {
            $name = $this->getLayout();
        }
        if (null === $subLayout) {
            $subLayout = $this->getSubLayout();
        }

        if ($this->inflectorEnabled() && (null !== ($inflector = $this->getInflector())))
        {
            $name = $this->_inflector->filter(array('script' => $name));
            $subLayout = $this->_inflector->filter(array('script' => $subLayout));
        }

        $view = $this->getView();

        if (null !== ($path = $this->getLayoutPath())) {
            $view->addScriptPath($path);
        }
        
        // sublayout is stored in the page
        $content = array();
        $content['subLayoutContent'] = $view->render($subLayout);
        $this->assign($content);

        
        return $view->render($name);
    }


}




class Mmx_Layout_Controller_Action_Helper_Layout  extends Zend_Layout_Controller_Action_Helper_Layout
{
    /**
     * Constructor
     * 
     * @param  Zend_Layout $layout 
     * @return void
     */
    public function __construct(Mmx_Layout $layout = null)
    {
        if (null !== $layout) {
            $this->setLayoutInstance($layout);
        } else {
            $layout = Mmx_Layout::getMvcInstance();
        }
        
        if (null !== $layout) {
            $pluginClass = $layout->getPluginClass();
            $front = $this->getFrontController();
            if ($front->hasPlugin($pluginClass)) {
                $plugin = $front->getPlugin($pluginClass);
                $plugin->setLayoutActionHelper($this);
            }
        }
    }
    
    /**
     * Get layout object
     * 
     * @return Zend_Layout
     */
    public function getLayoutInstance()
    {
        if (null === $this->_layout) {
            require_once 'Mmx/Layout.php';
            if (null === ($this->_layout = Mmx_Layout::getMvcInstance())) {
                $this->_layout = new Mmx_Layout();
            }
        }

        return $this->_layout;
    }
}


class Mmx_View_Helper_Layout
{
    /** @var Mmx_Layout */
    protected $_layout;

    /** Zend_View_Interface */
    public $view;

    /**
     * Set view
     * 
     * @param  Zend_View_Interface $view 
     * @return void
     */
    public function setView(Zend_View_Interface $view)
    {
        $this->view = $view;
    }

    /**
     * Get layout object
     * 
     * @return Mmx_Layout
     */
    public function getLayout()
    {
        if (null === $this->_layout) {
            require_once 'Mmx/Layout.php';           
            $this->_layout = Mmx_Layout::getMvcInstance();
            if (null === $this->_layout) {                         
                // Implicitly creates layout object
                $this->_layout = new Mmx_Layout();
            }
        }

        return $this->_layout;
    }

    /**
     * Set layout object
     * 
     * @param  Mmx_Layout $layout 
     * @return Mmx_Layout_Controller_Action_Helper_Layout
     */
    public function setLayout(Mmx_Layout $layout)
    {
        $this->_layout = $layout;
        return $this;
    }

    /**
     * Return layout object
     *
     * Usage: $this->layout()->setLayout('alternate');
     * 
     * @return Mmx_Layout
     */
    public function layout()
    {
        return $this->getLayout();
    }
}

Dernière modification par 2mx (17-07-2008 12:20:40)

Hors ligne

 

#3 16-06-2008 15:24:47

aRKhamTaro
Nouveau membre
Lieu: Rennes
Date d'inscription: 11-06-2008
Messages: 2

Re: [Zend_Layout][1.5] layouts imbriqués

Ok, je vais aller potasser tout ça tranquillement.

Merci bien !

Hors ligne

 

#4 15-07-2008 22:33:31

Bab
Nouveau membre
Date d'inscription: 28-05-2008
Messages: 8

Re: [Zend_Layout][1.5] layouts imbriqués

Bonjour à tous!

Cette possibilité d'imbriquer des layouts m'intéresse fortement!!
J'ai donc essayer d'adapter le code de 2mx à mon projet, cependant, plusieurs points d'ombres demeurent... :S

Tout d'abord, le subLayout doit-il contenir lui aussi l'instruction:

Code:

echo $this->layout()->content;

Cela me semblerait logique, mais on n'est jamais trop prudent!

Ensuite, l'instruction:

Code:

$this->layout()->setSubLayout('2column.phtml');

doit-elle être placée directement dans la vue correspondant à l'action appelée?

Toutes ces questions car je n'obtient absolument RIEN! hmm
Lorsque je fait un $this->render(); dans mon action, la classe de Layout étendue récupère bien le subLayout via le getter correspondant.
Cependant, mon affichage n'est pas modifié, que je mette ou non l'instruction echo $this->layout()->content; dans mon sublayout.

De plus, l'affichage d'une vue ne déclarant pas de subLayout me génère l'erreur suivante:

Code:

Fatal error: Uncaught exception 'Zend_Filter_Exception' with message 'A replacement identifier : was found inside the inflected target, perhaps a rule was not satisfied with a target source? Unsatisfied inflected target: :script.phtml' in D:\Dev\Vivalur\application\lib\Zend\Filter\Inflector.php:455 Stack trace: #0 D:\Dev\Vivalur\application\lib\Viv\Layout.php(30): Zend_Filter_Inflector->filter(Array) #1 D:\Dev\Vivalur\application\lib\Zend\Layout\Controller\Plugin\Layout.php(142): Viv_Layout->render() #2 D:\Dev\Vivalur\application\lib\Zend\Controller\Plugin\Broker.php(337): Zend_Layout_Controller_Plugin_Layout->postDispatch(Object(Viv_Controller_Request_Http)) #3 D:\Dev\Vivalur\application\lib\Zend\Controller\Front.php(925): Zend_Controller_Plugin_Broker->postDispatch(Object(Viv_Controller_Request_Http)) #4 D:\Dev\Vivalur\application\lib\Viv\Controller\Front.php(73): Zend_Controller_Front->dispatch(Object(Viv_Controller_Request_Http), NULL) #5 D:\Dev\Vivalur\html\index.php(22): Viv_Controller_Front->dispatch() #6 {main} in D:\Dev\Vivalur\application\lib\Zend\Filter\Inflector.php on line 455

Bref, autant dire que je rame un peu (voire beaucoup).

Merci d'avance pour votre aide! smile

Dernière modification par Bab (15-07-2008 22:34:28)

Hors ligne

 

#5 17-07-2008 12:26:33

2mx
Membre
Lieu: Grenoble
Date d'inscription: 06-08-2007
Messages: 125

Re: [Zend_Layout][1.5] layouts imbriqués

Petit correctif sur le code que j'ai donnée ci-dessus :
J'ai supprimer Mmx_Layout_Controller_Plugin_Layout car je ne m'en sert plus et j'avais oublier Mmx_View_Helper_Layout

Sinon le principe de fonctionnement :

Mmx_Layout surclasse Zend_Layout afin de pouvoir gérer les layouts imbriqués.

Comme Zend_Layout est un singleton il faut aussi :

    * surclasser la classe Zend_Layout_Controller_Action_Helper_Layout afin qu'il utilise Mmx_Layout et non Zend_Layout
    * Remplacer Zend_View_Helper_Layout par Mmx_View_Helper_Layout pour les mêmes raisons

Fonctionnement de Zend_Layout

@see http://julien-pauli.developpez.com/tuto … nd-layout/

En Appelant la methode Zend_Layout::startMvc($config) dans le bootstrap, elle crée une instance de Zend_Layout, puis elle enregistre un plugin de FrontController, ainsi qu'un action helper.

Le plugin est enregistré avec un numéro de pile de manière à ce qu'il soit l'avant dernier à intervenir, en postdispatch bien entendu, le dernier étant errorHandler.

Le Plugin effectue les actions suivantes (en postdispatch) :

    * 1) récupère le contenu de l'action (via le 'default' segment du Response Object)
    * 2) puis l'assigne au layout via Zend_Layout::assign() sur la clé 'content'
    * 3) appel la méthode Zend_Layout::render() qui elle va insérer le contenu de l'action dans le template
    * 4) puis réinject le tout dans la Reponse

Layouts Imbriqués

Pour pouvoir effectuer le layout imbriqué (3 step view ?) il faut donc surclasser Zend_Layout::render() :

    * le contenu de l'action est stocké dans dans la variable de layout 'content' par le plugin
    * on appelle Zend_View::render() avec la sous template et on affecte le résulta à la variable de layout 'subLayoutContent'
    * on appelle à nouveau Zend_View::render() avec la template et le résulta est renvoyé au plugin qui le réaffecte à la Réponse.

On a donc dans le sous template

Code:

$this->layout()->content

et dans la template

Code:

$this->layout()->subLayoutContent

Dans le bootstrap on doit avoir :

Code:

// Layout Manager
$confLayout = array_merge($viewConfig->layout->toArray(), array('layoutPath'=> $layoutPath, 'modulesPath'=> $modulesPath, 'view' => $view, 'helperClass' => 'Mmx_Layout_Controller_Action_Helper_Layout', 'mvcSuccessfulActionOnly' => true));
require 'Mmx/Layout.php';
Mmx_Layout::startMvc($confLayout);

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages