How can I make Expressive direct errors into apache's error_log?

When I run across an error in Expressive, I often see a blank screen.

For example I had a recent bug where only the partial header was rendered, nothing further was shown on the screen.
Apache logs did not show anything, neither did Mozilla Firefox’s Developer Tools. Response was HTTP 200 despite an incomplete page loaded.

How can I see the errors?

Thankfully in my case on mydev it was an easily repeatable error, so I found the cause. An invalid method was called on a class inside my template. But had it happened in production, and had it been a non-repeatable error, there would have been no record of it.

How could I expose and display or log such errors in Expressive? Is there a way to disable error catching to where these errors just flow into apache’s error_log file?

For production env, I think another storage for log should be used instead of error_log for easier to read. I created ErrorHeroModule that can be used in both zend-mvc and zend-expressive. It can save any exception/error in DB and optionally send to multi registered emails as notification, disable/enable error, templated error page, etc.

1 Like

As far as i can see, ErrorHandler is intercepting errors and exceptions. It is registered in pipeline config in expressive skeleton application.

Enabling development mode in config should make it print details to browser.

You can attach listener to error handler that will pass exceptions to logger. It then depends on how you configured logger. For example monolog/monolog have ErrorLogHandler that sends messages to error_log()

As xerkus is saying, you can attach an ErrorListener to the standard ErrorHandler. There is an listening-for-errors section in the docs.

During development there is also the Whoops error handler.

Thanks! I will be looking into these. I like the samsonasik’s approach of using the database to record errors.

But as far as error handling, I do have Whoops error handler installed, and for whatever reason it does not trigger.
It does trigger on some errors, but not some others. It did not trigger on this one and I do not have much clue as to why.

Recreating Error

The error I had was me trying to use a parameter in a layout when that parameter was not defined. To recreate:

  • In layout::default use a parameter like echo $this->randomObject->getName()

What I see on screen is partial layout rendered, and nothing else. Layout quits being rendered when it encounters getName() being called on parameter randomObject, as that object was not defined. My Whoops is not triggered. No error is recorded.

I should note that $this->randomObject, despite its random name, is seen as type Zend\View\Renderer\PhpRenderer in the view. Because in my case, I use ZendViewRendererFactory for my TemplateRendererInterface, so I am guessing that view sees it as a TemplateRendererInterface instance and tries to call getName() method on that instance.

But Whoops is not picking it up. So I am concerned about whether the other approaches will. I will give them a try.

Whoops does not catch the error

My Whoops set up is like so:

//development.local.php
return [
    'dependencies' => [
        'factories'  => [
            ErrorResponseGenerator::class       => Container\WhoopsErrorResponseGeneratorFactory::class,
            'Zend\Expressive\Whoops'            => Container\WhoopsFactory::class,
            'Zend\Expressive\WhoopsPageHandler' => Container\WhoopsPageHandlerFactory::class
        ],
    ],    
    'whoops' => [
        'json_exceptions' => [
            'display'    => true,
            'show_trace' => true,
            'ajax_only'  => true,
        ],
    ],
];