Welcome to Abdul Malik Ikhsan's Blog

Zend Framework 2 : Disable Layout in specific Module

Posted in Tutorial PHP, Zend Framework 2 by samsonasik on December 2, 2012

Based on definition of module in Zend Framework 2 : “all related code and assets that solve a specific problem”, sometime, for example, we need a module that provide Ajax only, and no need a layout in all actions. So, we can do a trick to reduce code redundancy in every controller/actions.

namespace YourModule;

use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
	$sharedEvents        = $e->getApplication()->getEventManager()->getSharedManager();
	$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
	    $result = $e->getResult();
	    if ($result instanceof \Zend\View\Model\ViewModel) {
		$result->setTerminal($e->getRequest()->isXmlHttpRequest());
                //if you want no matter request is, the layout is disabled, you can
                //set true : $result->setTerminal(true);
	    }
        });
    }
}

How about all module ? attach into Zend\Mvc\Controller\AbstractActionController

namespace YourModule;

use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
	$sharedEvents        = $e->getApplication()->getEventManager()->getSharedManager();
        $sharedEvents->attach('Zend\Mvc\Controller\AbstractActionController','dispatch', 
             function($e) {
                $result = $e->getResult();
                if ($result instanceof \Zend\View\Model\ViewModel) {
                    $result->setTerminal($e->getRequest()->isXmlHttpRequest());
                   //if you want no matter request is, the layout is disabled, you can
                   //set true : $result->setTerminal(true);
                }
        });
    }
}

Remember, you should return ViewModel() in every action in your module.

33 Responses

Subscribe to comments with RSS.

  1. Michał Zwoliński said, on December 2, 2012 at 8:06 pm

    Hi, xdebug doesn’t stop at callback breakpoint, why?

    Thank you for your tutorials. I will be your subscriber.

    • samsonasik said, on December 2, 2012 at 9:27 pm

      I’m not familiar with xdebug, sorry. You’re welcome

  2. Michał Zwoliński said, on December 2, 2012 at 10:42 pm

    Ok, it was my fault. Everything is all right.
    I have one question. How can I inject to all Controllers a new field without define setters and getters in every Controllers? I want to simply set entityManager (Doctrine2) in my Controllers untill dispatch after Controller instance is create. Can i use automagic method? I don’t wanna use $this->getServiceLocator()->get(’em’) all the time. I don’t wanna extends my Controllers with parent class where is entityManager defined. Maybe an event before Controller is a good place for it? Event driven architecture is great but i don’t know how can i use it.
    Bests.

    • samsonasik said, on December 3, 2012 at 2:39 am

      maybe like this :

      public function onBootstrap(MvcEvent $e)
      {
          $sharedEvents        = $e->getApplication()->getEventManager()->getSharedManager();
          $sm = $e->getApplication()->getServiceManager();
          
          $sharedEvents->attach('Zend\Mvc\Controller\AbstractActionController','dispatch', 
               function($e) use ($sm) {
                  $controller = $e->getTarget();
                  $controller->em = $sm->get('em');
              }, 100
         );
      }
      

      and in Controller :

      class YourController extends \Zend\Mvc\Controller\AbstracActionController
      {
            public $em;
      
           public function indexAction()
           {
               var_dump($this->em);
           }
      }
      
  3. Raphael said, on December 3, 2012 at 5:15 am

    Hey samsonasik!

    Thank you for all the help that you have done on your blog! I am not sure how I will survive learning ZF2 without you as well as the contributors to the framework.

    I am currently following your posts on github as well. much easier for me to find the scripts that I needed to start off with the work I am currently doing.

    But often I get to see some codes that you have not put on Github, so I copy and pasted yours and just referenced the page where I took it from. I hope that’s alright with you?

  4. Michał Zwoliński said, on December 3, 2012 at 5:23 am

    It works what i expected perfectly! Thank you so much! It also works if public $em is not defined in controller.
    How do you think, is there any method to set this service in config arrays?

    • samsonasik said, on December 3, 2012 at 7:04 am

      You’re welcome. I suggest to type public $em, it’s make code more testable and solid. maybe via ‘di’ Zend\Di ( personally, i’m not fan of dic which ‘inject’ class with config array in array in array definition), but i think it will be more complicated.

  5. Mungiu said, on December 7, 2012 at 9:48 pm

    do yolu know where i can find documentation of how to use \Zend\File\Transfer\Transfer? tanks

  6. Mungiu said, on December 9, 2012 at 5:45 am

    Maybe a simple and stupid question.. how can i unescape the label in form? tanks

  7. Mungiu said, on December 9, 2012 at 9:20 pm

    yes i know where the documentation is and i read it but i don’t find how to not escape the label in helper like this echo $this->formRow($form->get(‘title’)) . PHP_EOL;
    if i do like this $name = $form->get(‘special’);
    echo $formLabel->openTag() . $this->formInput($name) . $name->getOption(‘label’);
    echo $this->formElementErrors($name);
    echo $formLabel->closeTag();

    everityng is fine the label aren’t escaped but i ended with a lot of markup and then whats the catch to use zend

    • samsonasik said, on December 9, 2012 at 9:28 pm

      just write your custom formLabel.

      • Mungiu said, on December 9, 2012 at 9:52 pm

        sound a little stupid to not be a flag or something, if you need a little markup in label like a span.. ok tanks. i ended modify zend till find a solution

      • samsonasik said, on December 9, 2012 at 10:31 pm

        custom, don’t modify the core, for ex :

        namespace SanCommons\View\Helper;
        
        use Zend\Form\ElementInterface;
        use Zend\Form\View\Helper\FormLabel as ParentLabel;
        
        class FormLabel extends ParentLabel
        {   
            public function openTag($attributesOrElement = null)
            {
                if ($attributesOrElement instanceof ElementInterface) {
                    return '<label class="control-label" for="'.$attributesOrElement->getName().'">';
                }
            }
        }
        

        Register it in ServiceManager :

         'view_helpers' => array(
                'invokables' => array(
                    'formlabel' => 'SanCommons\View\Helper\FormLabel',
                ),
        ),
        
  8. Mungiu said, on December 10, 2012 at 4:37 am

    this code don’t solve the problem this method is for label tag not what is inside, i see for the most of inputs that helper render something like
    label txt so call that method only in textarea inputs
    Must extend other class i don’t know what class must extend and what method must rewrite

  9. Mungiu said, on December 10, 2012 at 4:40 am

    it’s work with something like echo html_entity_decode($this->formRow($form->get(‘element’))) i write this here maybe someone else need because i see some of people asked on the google and not anybody answered. It’s a little bit stranhe to decode what is encode already alittle bit overhead but when you need it is ok. tanks for the answers.

    • samsonasik said, on December 10, 2012 at 5:40 am

      You should override __invoke function of FormLabel :

      namespace SanCommons\View\Helper;
      
      use Zend\Form\ElementInterface;
      use Zend\Form\View\Helper\FormLabel as ParentLabel;
      
      class FormLabel extends ParentLabel
      {   
          public function __invoke(ElementInterface $element)
          {
              $result = parent::__invoke($element);
              return  html_entity_decode($result);
          }
      }
      
      
  10. Manish Kutaula said, on February 6, 2013 at 1:08 am

    Remember, you should return ViewModel() in every action in your module.
    why is this needed. my action by default accesses my corresponding template file.

  11. samsonasik said, on February 6, 2013 at 2:29 am

    because by ViewModel, you can setTerminal.

  12. Emmanuel said, on February 6, 2013 at 9:07 pm

    Hi Samsonic,

    I wonder if you can help me here… I have a base service file which I am using to try and load the Doctrine 2 service.. I followed your on onBootstrap suggestion on loading Doctrine2 into a controller:

    public function onBootstrap(MvcEvent $e)
    {
    $sharedEvents = $e->getApplication()->getEventManager()->getSharedManager();
    $sm = $e->getApplication()->getServiceManager();

    $sharedEvents->attach(‘Zend\Mvc\Controller\AbstractActionController’,’dispatch’,
    function($e) use ($sm) {
    $controller = $e->getTarget();
    $controller->em = $sm->get(’em’);
    }, 100
    );
    }

    This worked great.. But is there a way I can do this in a service file instead rather than using controller? I have a few files that extend from this service file. Any help would be appreciated. Right now, all I am getting is Fatal error: Call to a member function createQueryBuilder(). Which suggests that my entity variable in my service file is null. This is the code for my service file.

    entityManager = $manager;
    return $this;
    }

    /**
    * @return \Doctrine\ORM\EntityManager
    */
    public function getEntityManager()
    {
    if (null === $this->entityManager) {
    $this->entityManager = $this->getServiceLocator()->get(‘doctrine.entitymanager.orm_default’);
    }
    return $this->entityManager ;
    }

    /**
    * @param ServiceLocatorInterFace $serviceLocator
    */
    public function setServiceLocator(ServiceLocatorInterFace $serviceLocator)
    {
    $this->serviceLocator = $serviceLocator;
    }

    /**
    * @returns ServiceLocatorInterFace
    */
    public function getServiceLocator()
    {
    /*echo “

    ";
            print_r($this->serviceLocator);
            echo "

    “;
    exit;*/

    return $this->serviceLocator;
    }

    }

    The service file that extends the base service looks like this:

    entityManager->createQueryBuilder();

    $query = $qb->select(‘a.id_attendee, a.title, a.name’)
    ->from(‘CPortal\Entity\AttendeesEntity’,’a’)
    ->setFirstResult(0)
    ->setMaxResults(10);
    $attendees = $query->getQuery()->getResult();
    return $attendees;
    }

    }

    Finally my controller looks like so:

    getAttendees($this->em);

    return new ViewModel(
    array(
    ‘attendees’ => $attendees
    )
    );
    }

    }

    Thanks again… I hope I am not asking for too much so any help would be welcome as to where I am going wrong… Superb tutorial btw.

  13. Emmanuel said, on February 6, 2013 at 9:20 pm

    BaseService.php

    <?php
    
    
    namespace My\Service;
    
    use My\ServiceManager\EntityManagerAwareInterface;
    use Doctrine\ORM\EntityManager;
    use Zend\ServiceManager\ServiceManager;
    use Zend\ServiceManager\ServiceLocatorAwareInterface;
    use Zend\ServiceManager\ServiceLocatorInterface;
    
    class BaseService implements ServiceLocatorAwareInterface
    {
        /**
         * @var ServiceManager\ServiceLocatorInterFace
         */
        protected $serviceLocator;
    
        /**
         * @var \Doctrine\ORM\EntityManager
         */
        protected $entityManager;
    
        /**
         * @param \Doctrine\ORM\EntityManager $manager
         * @return $this
         */
        public function setEntityManager(ServiceManager $manager)
        {
            $this->entityManager = $manager;
            return $this;
        }
    
        /**
         * @return \Doctrine\ORM\EntityManager
         */
        public function getEntityManager()
        {
            if (null === $this->entityManager) {
                $this->entityManager = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
            }
            return $this->entityManager ;
        }
    
        /**
         * @param ServiceLocatorInterFace $serviceLocator
         */
        public function setServiceLocator(ServiceLocatorInterFace $serviceLocator)
        {
            $this->serviceLocator = $serviceLocator;
        }
    
        /**
         * @returns ServiceLocatorInterFace
         */
        public function getServiceLocator()
        {
            /*echo "<pre>";
            print_r($this->serviceLocator);
            echo "</pre>";
            exit;*/
    
            return $this->serviceLocator;
        }
    
    }
    

    AttendeesService.php file which extends the BaseService.php file

    <?php
    namespace My\Service;
    
    use My\Service\BaseService;
    use Doctrine\ORM\Mapping as ORM;
    use Doctrine\ORM\Query\Expr\Base;
    
    class AttendeesService extends BaseService
    {
        /**
         * Get all attendees not deleted
         * @return array
         */
        public function getAttendees()
        {
            $qb = $this->entityManager->createQueryBuilder();
    
            $query = $qb->select('a.id_attendee, a.title, a.name')
                ->from('CPortal\Entity\AttendeesEntity','a')
                ->setFirstResult(0)
                ->setMaxResults(10);
            $attendees = $query->getQuery()->getResult();
            return $attendees;
        }
    
    }
    

    AttendeesController.php file where a new instance of the AttendeesService is created.

    <?php
    /**
     * Zend Framework (http://framework.zend.com/)
     *
     * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
     * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
     * @license   http://framework.zend.com/license/new-bsd New BSD License
     */
    
    namespace Cms\Controller;
    
    
    use My\Controller\BaseController;
    use Doctrine\ORM\Query\Expr\Base;
    use Zend\Config\Config;
    use Zend\Log\Logger;
    use My\Service\AttendeesService;
    use Zend\View\Model\ViewModel;
    
    class AttendeesController extends BaseController
    {
    
        public function indexAction()
        {
    
            /*echo "<pre>";
            print_r($this->em);
            echo "</pre>";
            exit;*/
    
            $attendeeService = new AttendeesService();
            $attendees = $attendeeService->getAttendees($this->em);
    
            return new ViewModel(
                array(
                    'attendees' => $attendees
                )
            );
        }
    
    }
    
    

    I hope this helps, as all I get is a Fatal error: Call to a member function createQueryBuilder() in the AttendeesService.php file…

    Thanks

  14. Emmanuel said, on February 6, 2013 at 10:14 pm

    Thanks Samson… Just out of curiosity, was there a reason why I couldn’t call the Doctrine 2 from the service file but in a controller, this could easily be done?

  15. […] also provides no answers. After a bit of cursing my frustration leads me to Google which yields Zend Framework 2 : Disable Layout in specific Module. OK that was a waste of time, but at least it works… except.. the obsessive compulsive part […]

  16. Pradeep Chaudhary said, on August 19, 2014 at 4:01 pm

    Can i disable the layout in a particular page?


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: