1

I have a question about Zend Framework 2.I want to find out how much time take to complete a request and I know that it should be possible using Zend MVCEvent but I don't know how.

Serban Alexandru
  • 165
  • 2
  • 13

3 Answers3

2

a better solution in my mind is to replace a special variable inside your template files like this

{{ renderTime }}

so you are free to controll the text position and don't mess up json response models in your zf application.

let me explain why i don't hook up into the \Zend\View\ViewEvent::EVENT_RENDERER event and replace my variable directly in the Response at the FINISH event.

basically you can't use the other events, because the page is not rendered at any time and all the functions/viewhelper into your template are currently not done and so the time would be less then the real render time.

The \Zend\View\ViewEvent::EVENT_RENDERER_POST Event is not good because - your view is rendered thats true - but the application is not done and maybee all the registered events etc that follow are not executed yet.

if you like my idea than your index.php would look like this

<?php
/**
 * This makes our life easier when dealing with paths. Everything is relative
 * to the application root now.
 */
chdir(dirname(__DIR__));
define('STARTTIME', microtime(true));

// Decline static file requests back to the PHP built-in webserver
if (php_sapi_name() === 'cli-server' && is_file(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH))) {
    return false;
}

// Setup autoloading
require 'init_autoloader.php';

// Run the application!
Zend\Mvc\Application::init(require 'config/application.config.php')->run();

and your module.php onBootstrap method would become this

$e->getApplication()->getEventManager()->attach(\Zend\Mvc\MvcEvent::EVENT_FINISH, function($e){
    /** @var $e \Zend\Mvc\MvcEvent */
    if( $e->getResult() instanceof \Zend\View\Model\ViewModel )
    {
        $renderText = sprintf('page render time - %s seconds', number_format(microtime(true) - STARTTIME, 5));

        /** @var \Zend\Http\PhpEnvironment\Response $response */
        $response = $e->getResponse();
        $response->setContent(
            str_replace('{{ renderTime }}', $renderText, $response->getContent())
        );
    }
}, 100000);

and in your template/layout file set where you wish to inject the rendertime with {{ renderTime }}

<h1>Hello Friends!</h1>
<div>some content</div>
<div class="footer">
    {{ renderTime }}
</div>

that now gives you page render time - 0.67307 seconds

ins0
  • 3,918
  • 1
  • 20
  • 28
  • You say that if I initialize the start time in DISPATCH Event and finish time in FINISH Event is possible that not all the request to be complete?And I see that you initialize the finish time in FINIS Event but the start time direct in bootstrap method so you saying that because my start time is in DISPATCH method and yours in bootstrap direct I loose some request time?I did that way because I understand from Zend documentation that a request begin with trigger DISPATCH Event and Finish when trigger FINISH Event.So could you explain me exactly what is the request flow in your vision?Thanks! – Serban Alexandru Aug 20 '14 at 09:03
  • this is true even when you setup your starttime in the ``onBootstrap`` method you miss some time that zend needs to bootstrap your application/routing etc. your answer is ok but not good because you hijack the ``request`` class to deliver your render time and are out of controll where your rendertime will display on the client (at the bottom - no controll) also you mess up json viewmodels because every time your response is append to the direct client output. i edit my answer – ins0 Aug 20 '14 at 09:09
  • I understand what you say about the position in page but I didn't took that in consideration,my first objective was to determine somehow the request time using MVC Event then I can do some sort of tricks to put the time where I want like the one you did with setContent and maybe there are other posibility but I haven't yet think about them,I just wanted to see how a request flow from the MVC Event side and how to use event->attach to do things in certain moment of the application like before request start and after is complete,that was the purpose of the application,to get used with a request – Serban Alexandru Aug 20 '14 at 09:15
  • Flow and MVC Event because I just started to learn Zend 2 a few days ago and I wanted to have a better undestand of how things are going in back. – Serban Alexandru Aug 20 '14 at 09:16
  • I've add your solution and you are right is a difference in time,mine is 0.014517068862915 seconds and yours 0.07570 seconds .But I would really apreciate if you can tell me a few about what exactly is the order Zend do things in request so I can see where I lose that time.Thanks! – Serban Alexandru Aug 20 '14 at 09:21
  • the best experience is to look in the source code of the ``zf2`` repository (``Zend\Mvc\Application``) and understand where and why events are fired from zend. this is to complex to explain here but the basics are written here http://framework.zend.com/manual/2.1/en/modules/zend.mvc.mvc-event.html#order-of-events – ins0 Aug 20 '14 at 09:22
  • Thanks,is seem that the time loose is between index.php and DISPATCH EVENT,I will try to look in Application and hope I can see the flow of things even if the code there is a little to complex for me now. – Serban Alexandru Aug 20 '14 at 09:27
  • yeah for the first time zf2 seems so ``DAFUQ`` but after some time you hit the mark ;) – ins0 Aug 20 '14 at 09:30
0

This don't exactly answer your question but I think you could do such a thing using the REQUEST_TIME that you can get from the request server. Something like this :

 $startTime = $mvcEvent->getRequest()->getServer()->get('REQUEST_TIME');

And then at the end of the request :

 $endTime = microtime(true);

I'm not sure but I think this module ZendDeveloperTools permits to show the execution time.

blackbishop
  • 30,945
  • 11
  • 55
  • 76
  • Thanks for your answer,is not really what I want,I come with this aproch too firt: $eventManager->attach(MvcEvent::EVENT_FINISH,function($e){ $p=$e->getParams(); echo 'Time:'.(microtime(TRUE)-$p['request']>getServer('REQUEST_TIME')).' seconds'; }); – Serban Alexandru Aug 19 '14 at 15:02
  • But is not good enough because I don't want to depend on the apache server,I need something that could work on any server.Now I try to do something like get microtime(true) in MvcEvent::EVENT_DISPATCH and in MvcEvent::EVENT_FINISH and make difference,but I don't know how to receive the microtime value from EVENT_DISPATCH callback I attach. – Serban Alexandru Aug 19 '14 at 15:05
  • @SerbanAlexandru You can add arbitrary values to the event instance. `$mvcEvent->setParam('startTime', $value)` and `$mvcEvent->getParam('startTime')` in a later listener. – AlexP Aug 19 '14 at 15:45
  • I know but the MvcEvent::Event_DISPATCH requires MvcEvent instance when you want to triger it, not an MvcEvent\Event instance,if I understand what you meand to do. – Serban Alexandru Aug 19 '14 at 15:55
  • Aniway I finded another way finally I will put an answer with it – Serban Alexandru Aug 19 '14 at 15:55
0

This is the solution I've came up with,the code is write in Module.php on the Module that I want to display request time on every page:

 public function onBootstrap(MvcEvent $e)
{
    $eventManager        = $e->getApplication()->getEventManager();
    $moduleRouteListener = new ModuleRouteListener();
    $checklistener=new CheckListener();
    $checklistener->attach($eventManager);
    $addyearlistener=new AddyearListener();
    $addyearlistener->attach($eventManager);
    $moduleRouteListener->attach($eventManager);
    //request time
    $eventManager->attach(MvcEvent::EVENT_DISPATCH,function($e){
        $param=new Parameters(array('time' => microtime(TRUE)));
        $e->getApplication()->getRequest()->setPost($param);
        $e->getApplication()->getEventManager()->attach(MvcEvent::EVENT_FINISH, function($e){
           echo 'Time:'. (microtime(TRUE)-$e->getRequest()->getPost('time')).' seconds'; 
        });

    });

}
Serban Alexandru
  • 165
  • 2
  • 13