Errors frustrate users. No matter if it's their fault or applications', risks that they'll lose interest in our product is high. In this presentation, given at the Italian ZFDay 2014, I discuss about these issues and provide some hints for improving error reporting and handling.
17. User Privacy Concerns
• Over 40% of online shoppers are very
concerned over the use of personal
information
• Public opinion polls have revealed a
general desire among Internet users to
protect their privacy
Online Privacy: A Growing Threat. - Business Week, March 20, 2000, 96. Internet Privacy in ECommerce:
Framework, Review, and Opportunities for Future Research - Proceedings of the 41st Hawaii
International Conference on System Sciences - 2008
22. Creating A Form in ZF2
<?php
namespace ApplicationForm;
use ZendFormForm;
class ContactForm extends Form
{
public function __construct() {
parent::__construct();
// ...
}
//...
}
23. Creating A Form in ZF2
<?php
namespace ApplicationForm;
use ZendFormForm;
class ContactForm extends Form
{
public function __construct() {
parent::__construct();
// ...
}
//...
}
45. A few tips:
•
•
•
45
Provide the user with a solution to the
problem
Do not use technical jargon, use
terminology that your audience
understands
Avoid uppercase text and exclamation
points
47. Condensing N messages into 1
$this->add(array(
'name' => 'email',
'required' => true,
'validators' => array(
array('name' =>'NotEmpty',
'options' => array(
'messages' => array(
NotEmpty::IS_EMPTY => 'We need an '.
'e-mail address to be able to get back to you'
)),
'break_chain_on_failure' => true,
),
array('name' => 'EmailAddress',
'options' => array(
'message' => 'E-Mail address does not seem to be valid.
Please make sure it contains the @ symbol
and a valid domain name.',
)));
48. Condensing N messages into 1
$this->add(array(
'name' => 'email',
'required' => true,
'validators' => array(
array('name' =>'NotEmpty',
'options' => array(
'messages' => array(
NotEmpty::IS_EMPTY => 'We need an '.
'e-mail address to be able to get back to you'
)),
'break_chain_on_failure' => true,
),
array('name' => 'EmailAddress',
'options' => array(
'message' => 'E-Mail address does not seem to be valid.
Please make sure it contains the @ symbol
and a valid domain name.',
)));
49. Messages VS message
$this->add(array(
'name' => 'email',
'required' => true,
'validators' => array(
array('name' =>'NotEmpty',
'options' => array(
'messages' => array(
NotEmpty::IS_EMPTY => 'We need an '.
'e-mail address to be able to get back to you'
)),
'break_chain_on_failure' => true,
),
array('name' => 'EmailAddress',
'options' => array(
'message' => 'E-Mail address does not seem to be valid.
Please make sure it contains the @ symbol
and a valid domain name.',
)));
69. Handling PHP Errors
public function onBootstrap(MvcEvent $I_e) {
[…]
set_error_handler(array('ApplicationModule','handlePhpErrors'));
}
public static function handlePhpErrors($i_type,
$s_message,
$s_file,
$i_line) {
if (!($i_type & error_reporting())) { return };
throw new Exception("Error: " . $s_message . " in file " . $s_file
. " at line " . $i_line);
}
70. What happens now?
class IndexController extends AbstractActionController
{
public function indexAction()
{
1/0;
return new ViewModel();
}
}
71.
72. Now… what if?
class IndexController extends AbstractActionController
{
public function indexAction()
{
$doesNotExist->doSomething();
return new ViewModel();
}
}
73. Fatal error: Call to a member function doSomething() on a non-object in
/srv/apps/zfday/module/Application/src/Application/Controller/IndexController.php
on line 20
92. index.php Check
// What environment are we in?
$s_env = getenv('APPLICATION_ENV');
if (empty($s_env)) {
throw new Exception('Environment not set.'.
' Cannot continue. Too risky!');
}
110. Logging Within Controller
class GreetingsController {
public function helloAction() {
$I_logger = new Logger();
$I_logger->log("We just said Hello!");
return new ViewModel('msg' =>"Hello!");
}
}
111. Single Responsability Violation
class GreetingsController {
public function helloAction() {
$I_logger = new Logger();
$I_logger->log("We just said Hello!");
return new ViewModel('msg' =>"Hello!");
}
}
112. Fat Controllers
class GreetingsController {
public function helloAction() {
$I_logger = new Logger();
$I_logger->log("We just said Hello!");
$I_mailer = new Mailer();
$I_mailer->mail($s_msg);
$I_queue = new Queue();
$I_queue->add($s_msg);
return new ViewModel('msg' =>"Hello!");
}
}
115. Handling Events
class Module {
public function onBootstrap(MvcEvent $e) {
$eventManager = $e->getApplication()
->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$logger = $sm->get('logger');
$eventManager->attach('wesaidHello',
function(MvcEvent $event) use
($logger) {
$logger->log($event->getMessage());
);
}
}
116. Triggering An Event
class GreetingsController {
public function helloAction() {
$this->eventManager
->trigger('wesaidHello',
$this,
array('greeting' => 'Hello!')
);
return new ViewModel('msg' => "Hello!");
}
}
123. Stuff to take home
1.
2.
3.
123
When reporting errors, make sure to be
nice with users
Different error reporting strategies could
be useful for different environments
The event manager reduces coupling and
provides flexibility