SlideShare a Scribd company logo
Error Reporting
in Zend Framework 2

Zend Framework Day – Turin, Italy – 07/02/2014
STEVE MARASPIN
@maraspin
http://www.mvlabs.it/
http://friuli.grusp.org/

5
WHY WORRY?
WE SCREW UP
WE ALL SCREW UP
Application Failures
Application Failures
User Mistakes
INCREASED SUPPORT COST
ABANDONMENT
THE BOTTOM LINE
User Input = Mistake Source
Validation Handling
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
Validation Handling
Improved Error Message
+70% CONVERSIONS
21
Creating A Form in ZF2
<?php
namespace ApplicationForm;
use ZendFormForm;
class ContactForm extends Form
{
public function __construct() {
parent::__construct();
// ...
}
//...
}
Creating A Form in ZF2
<?php
namespace ApplicationForm;
use ZendFormForm;
class ContactForm extends Form
{
public function __construct() {
parent::__construct();
// ...
}
//...
}
Adding Form Fields
public function init() {
$this->setName('contact');
$this->setAttribute('method', 'post');
[…]..
$this->add(array('name' => 'email',
'type' => 'text',
'options' => array(
'label' => 'Name',
),
);
$this->add(array('name' => 'message',
'type' => 'textarea',
'options' => array(
'label' => 'Message',
),
);
//. […]..
}
Adding Form Fields
public function init() {
$this->setName('contact');
$this->setAttribute('method', 'post');
[…]..
$this->add(array('name' => 'email',
'type' => 'text',
'options' => array(
'label' => 'Name',
),
);
$this->add(array('name' => 'message',
'type' => 'textarea',
'options' => array(
'label' => 'Message',
),
);
//. […]..
}
VALIDATION
Form Validation: InputFilter
Validation: inputFilter
<?php
namespace ApplicationForm;
[…]
class ContactFilter extends InputFilter

{
public function __construct() {

// filters go here
}

}
Validation: inputFilter
<?php
namespace ApplicationForm;
[…]
class ContactFilter extends InputFilter

{
public function __construct() {

// filters go here
}

}
Required Field Validation
$this->add(array(
'name' => 'email',
'required' => true,
'filters' => array(
array(
'name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'EmailAddress',
)
)
));
Required Field Validation
$this->add(array(
'name' => 'email',
'required' => true,
'filters' => array(
array(
'name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'EmailAddress',
)
)
));
InputFilter Usage
<?php
namespace ApplicationController;

[…]
class IndexController extends AbstractActionController
{

public function contactAction()
{
$form = new Contact();
$filter = new ContactFilter();

$form->setInputFilter($filter);
return new ViewModel(array(
'form' => $form );

}
}
InputFilter Usage
<?php
namespace ApplicationController;

[…]
class IndexController extends AbstractActionController
{

public function contactAction()
{
$form = new Contact();
$filter = new ContactFilter();

$form->setInputFilter($filter);
return new ViewModel(array(
'form' => $form );

}
}
Standard Error Message
Improved Error Message
Error Message Customization
$this->add(array(
'name' => 'email',

'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
),
'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'
),
),
),
array('name' => 'EmailAddress'),

)
));
Error Message Customization
$this->add(array(
'name' => 'email',

'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
),
'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'
),
),
),
array('name' => 'EmailAddress'),

)
));
More than we need…
Check Chain
$this->add(array(
'name' => 'email',

'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
),
'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'),
) ));
Ok, good…
…but, what if?
Words to Avoid

http://uxmovement.com/forms/how-to-make-your-form-error-messages-more-reassuring/
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
Improved message
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.',
)));
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.',
)));
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.',
)));
Translated Error Messages
Default Message Translation
public function onBootstrap(MvcEvent $e)
{
$translator = $e->getApplication()
->getServiceManager()->get('translator');

$translator->addTranslationFile(
'phpArray', __DIR__ .
'/../../vendor/zendframework/zendframework/'.
'resources/languages/it/Zend_Validate.php',
'default',
'it_IT'
);
AbstractValidator::setDefaultTranslator($translator);
}
Custom Message Translation
$this->add(array(
'name' => 'email',
'required' => true,
'validators' => array(
array('name' =>'NotEmpty',
'options' => array(
'translator' => $translator,
'message' => $translator->translate(
'Make sure your e-mail address contains the @
symbol and a valid domain name.'
)),
'break_chain_on_failure' => true,
),
)));
Form Factory
$translator = $I_services->get('translator');
$I_form = new Contact();
$I_filter = new ContactFilter($translator);
$I_form->setInputFilter($I_filter);
return $I_form;
Translated Error Message
http://patterntap.com/pattern/funny-and-helpful-404-error-page-mintcom
56
Error Display Configuration
Skeleton Applicaton
Configuration
Hiding Exception Traces
'view_manager' => array(

'display_not_found_reason' => false,
'display_exceptions' => false,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index'=> __DIR__ .
'/../view/application/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
Hiding Exception Traces
'view_manager' => array(

'display_not_found_reason' => false,
'display_exceptions' => false,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index'=> __DIR__ .
'/../view/application/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
Custom Error Pages
'view_manager' => array(

'display_not_found_reason' => false,
'display_exceptions' => false,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index'=> __DIR__ .
'/../view/application/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
How about PHP Errors?
class IndexController extends AbstractActionController
{
public function indexAction()
{

1/0;
return new ViewModel();
}
}
How about PHP Errors?
class IndexController extends AbstractActionController
{
public function indexAction()
{

1/0;
return new ViewModel();
}
}
Early error detection principle
What can we do?
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);
}
What happens now?
class IndexController extends AbstractActionController
{
public function indexAction()
{

1/0;
return new ViewModel();
}
}
Now… what if?
class IndexController extends AbstractActionController
{
public function indexAction()
{
$doesNotExist->doSomething();
return new ViewModel();
}
}
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
FATAL ERRORS
Fatal Error Handling
public function onBootstrap(MvcEvent $I_e) {
[…]
$am_config = $I_application->getConfig();
$am_environmentConf = $am_config['mvlabs_environment'];
// Fatal Error Recovery
if (array_key_exists('recover_from_fatal', $am_environmentConf) &&
$am_environmentConf['recover_from_fatal']) {
$s_redirectUrl = $am_environmentConf['redirect_url'];
}
$s_callback = null;
if (array_key_exists('fatal_errors_callback', $am_environmentConf)) {
$s_callback = $am_environmentConf['fatal_errors_callback'];
}
register_shutdown_function(array('ApplicationModule',
'handleFatalPhpErrors'),
$s_redirectUrl,
$s_callback);
}
Fatal Error Handling
/**
* Redirects user to nice page after fatal has occurred
*/
public static function handleFatalPhpErrors($s_redirectUrl,
$s_callback = null) {
if (php_sapi_name() != 'cli' && @is_Array($e = @get_last())) {
if (null != $s_callback) {
// This is the most stuff we can get.
// New context outside of framework scope
$m_code = isset($e['type']) ? $e['type'] : 0;
$s_msg = isset($e['message']) ? $e['message']:'';
$s_file = isset($e['file']) ? $e['file'] : '';
$i_line = isset($e['line']) ? $e['line'] : '';
$s_callback($s_msg, $s_file, $i_line);
}
header("location: ". $s_redirectUrl);
}
return false;
}
Fatal Error Handling
'mvlabs_environment' => array(
'exceptions_from_errors' => true,
'recover_from_fatal' => true,
'fatal_errors_callback' => function($s_msg, $s_file, $s_line) {
return false;
},
'redirect_url' => '/error',

'php_settings' => array(
'error_reporting' => E_ALL,
'display_errors' => 'Off',
'display_startup_errors' => 'Off',
),
),
PHP Settings Conf
'mvlabs_environment' => array(
'exceptions_from_errors' => true,
'recover_from_fatal' => true,
'fatal_errors_callback' => function($s_msg, $s_file, $s_line) {
return false;
},
'redirect_url' => '/error',

'php_settings' => array(
'error_reporting' => E_ALL,
'display_errors' => 'Off',
'display_startup_errors' => 'Off',
),
),
PHP Settings
public function onBootstrap(MvcEvent $I_e) {
[…]
foreach($am_phpSettings as $key => $value) {
ini_set($key, $value);
}
}
NICE PAGE!
CUSTOMER SUPPORT TEAM REACTION
http://www.flickr.com/photos/18548283@N00/8030280738
ENVIRONMENT
DEPENDANT
CONFIGURATION
During Deployment
Local/Global Configuration Files
During Deployment
Runtime
Index.php
// Application wide configuration
$am_conf = $am_originalConf = require 'config/application.config.php';

// Environment specific configuration
$s_environmentConfFile = 'config/application.'.$s_env.'.config.php';
if (file_exists($s_environmentConfFile) &&
is_readable($s_environmentConfFile)) {
// Specific environment configuration merge
$am_environmentConf = require $s_environmentConfFile;
$am_conf = ZendStdlibArrayUtils::merge($am_originalConf,
$am_environmentConf
);
}

// Additional Specific configuration files are also taken into account
$am_conf["module_listener_options"]["config_glob_paths"][] =
'config/autoload/{,*.}' . $s_env . '.php';
ZendMvcApplication::init($am_conf)->run();
application.config.php
'modules' => array(
'Application',
),
Application.dev.config.php
'modules' => array(
'Application',
'ZendDeveloperTools',
),
Enabling Environment Confs
// Application nominal environment
$am_conf = $am_originalConf = require 'config/application.config.php';

// Environment specific configuration
$s_environmentConfFile = 'config/application.'.$s_env.'.config.php';
// Do we have a specific configuration file?
if (file_exists($s_environmentConfFile) &&
is_readable($s_environmentConfFile)) {
// Specific environment configuration merge
$am_environmentConf = require $s_environmentConfFile;
$am_conf = ZendStdlibArrayUtils::merge($am_originalConf,
$am_environmentConf );
}

// Additional Specific configuration files are also taken into account
$am_conf["module_listener_options"]["config_glob_paths"][] =
'config/autoload/{,*.}' . $s_env . '.php';
ZendMvcApplication::init($am_conf)->run();
Env Dependant Conf Files
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!');
}
Apache Config File
<VirtualHost *:80>
DocumentRoot /srv/apps/zfday/public
ServerName www.dev.zfday.it
SetEnv APPLICATION_ENV "dev"
<Directory /srv/apps/zfday/public>
AllowOverride FileInfo
</Directory>
</VirtualHost>
LOGGING

http://www.flickr.com/photos/otterlove/8154505388/
Why Log?

Troubleshooting
• Stats Generation
• Compliance
•

95
Zend Log
$logger = new ZendLogLogger;
$writer = new ZendLogWriterStream('/var/log/app.log');
$logger->addWriter($writer);
$logger->info('Informational message');
$logger->log(ZendLogLogger::EMERG, 'Emergency message');
Zend Log
$logger = new ZendLogLogger;
$writer = new ZendLogWriterStream('/var/log/app.log');
$logger->addWriter($writer);
$logger->info('Informational message');
$logger->log(ZendLogLogger::EMERG, 'Emergency message');
ZendLogLogger::registerErrorHandler($logger);
ZendLogLogger::registerExceptionHandler($logger);
Writers

98
Writers

99
Logrotate
/var/log/app.log {
missingok
rotate 7
daily
notifempty
copytruncate
compress
endscript
}
100
Writers

101
Writers

102
Writers

103
Zend Log Ecosystem

104
Filter Example
$logger = new ZendLogLogger;
$writer1 = new ZendLogWriterStream('/var/log/app.log');
$logger->addWriter($writer1);
$writer2 = new ZendLogWriterStream('/var/log/err.log');
$logger->addWriter($writer2);
$filter = new ZendLogFilterPriority(Logger::CRIT);
$writer2->addFilter($filter);
$logger->info('Informational message');
$logger->log(ZendLogLogger::CRIT, 'Emergency message');
Monolog
use MonologLogger;
use MonologHandlerStreamHandler;
$log = new Logger('name');
$log->pushHandler(new StreamHandler('/var/log/app.log',
Logger::WARNING));
$log->addWarning('Foo');
$log->addError('Bar');
Monolog Components

107
How to log?
class IndexController {

public function helloAction() {
return new ViewModel('msg' =>"Hello!");

}
}
Traditional Invokation
Logging Within Controller
class GreetingsController {
public function helloAction() {
$I_logger = new Logger();
$I_logger->log("We just said Hello!");
return new ViewModel('msg' =>"Hello!");
}
}
Single Responsability Violation
class GreetingsController {
public function helloAction() {
$I_logger = new Logger();
$I_logger->log("We just said Hello!");
return new ViewModel('msg' =>"Hello!");
}
}
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!");
}
}
CROSS CUTTING CONCERNS
What can we do?
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());
);
}
}
Triggering An Event
class GreetingsController {

public function helloAction() {
$this->eventManager
->trigger('wesaidHello',
$this,
array('greeting' => 'Hello!')
);
return new ViewModel('msg' => "Hello!");
}
}
Traditional Invokation
Event Manager
OBSERVER
http://www.flickr.com/photos/lstcaress/502606063/
Event Manager
Handling Framework Errors
class Module {
public function onBootstrap(MvcEvent $e) {
$eventManager = $e->getApplication()
->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);

$logger = $sm->get('logger');
$eventManager->attach(MvcEvent::EVENT_RENDER_ERROR,
function(MvcEvent $e) use ($logger) {
$logger->info('An exception has Happened ' .
$e->getResult()->exception->getMessage());
}, -200);
);
}
}
Event Manager
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
2 min intro
https://xkcd.com/208/
Starting Things Up
input { stdin { } }
output { stdout { codec => rubydebug } }
Starting Things Up
input { stdin { } }
output { stdout { codec => rubydebug } }
java -jar logstash-1.3.3-flatjar.jar agent -f sample.conf
Integrated Elasticsearch
input {

file { path => ["/opt/logstash/example.log"] }
}
output {
stdout { codec => rubydebug }
elasticsearch { embedded => true }
}
java -jar logstash-1.3.3-flatjar.jar agent -f elastic.conf
Integrated Web Interface
input {

file { path => ["/opt/logstash/example.log"] }
}
output {
stdout { codec => rubydebug }
elasticsearch { embedded => true }
}
java -jar logstash.jar agent -f elastic.conf --web
Kibana
Thank you for your attention

Stefano Maraspin
@maraspin
@maraspin
Stefano Maraspin
@maraspin

More Related Content

What's hot

Php Security By Mugdha And Anish
Php Security By Mugdha And AnishPhp Security By Mugdha And Anish
Php Security By Mugdha And Anish
OSSCube
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
Gordon Forsythe
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and you
markstory
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
Michelangelo van Dam
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
Marcello Duarte
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
Michelangelo van Dam
 
Concern of Web Application Security
Concern of Web Application SecurityConcern of Web Application Security
Concern of Web Application Security
Mahmud Ahsan
 
Dealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsDealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsClinton Dreisbach
 
PHP Security
PHP SecurityPHP Security
PHP Security
Mindfire Solutions
 
Proposed PHP function: is_literal()
Proposed PHP function: is_literal()Proposed PHP function: is_literal()
Proposed PHP function: is_literal()
Craig Francis
 
SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!
Taras Oleksyn
 
Seam Glassfish Slidecast
Seam Glassfish SlidecastSeam Glassfish Slidecast
Seam Glassfish Slidecast
Eduardo Pelegri-Llopart
 
Building web APIs in PHP with Zend Expressive
Building web APIs in PHP with Zend ExpressiveBuilding web APIs in PHP with Zend Expressive
Building web APIs in PHP with Zend Expressive
Zend by Rogue Wave Software
 
Open Source Search: An Analysis
Open Source Search: An AnalysisOpen Source Search: An Analysis
Open Source Search: An Analysis
Justin Finkelstein
 
Php Security3895
Php Security3895Php Security3895
Php Security3895Aung Khant
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
Michelangelo van Dam
 
Jquery presentation
Jquery presentationJquery presentation
Jquery presentationguest5d87aa6
 

What's hot (19)

Php Security By Mugdha And Anish
Php Security By Mugdha And AnishPhp Security By Mugdha And Anish
Php Security By Mugdha And Anish
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and you
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Php Security
Php SecurityPhp Security
Php Security
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Concern of Web Application Security
Concern of Web Application SecurityConcern of Web Application Security
Concern of Web Application Security
 
Dealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsDealing with Legacy PHP Applications
Dealing with Legacy PHP Applications
 
PHP Security
PHP SecurityPHP Security
PHP Security
 
Extend sdk
Extend sdkExtend sdk
Extend sdk
 
Proposed PHP function: is_literal()
Proposed PHP function: is_literal()Proposed PHP function: is_literal()
Proposed PHP function: is_literal()
 
SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!
 
Seam Glassfish Slidecast
Seam Glassfish SlidecastSeam Glassfish Slidecast
Seam Glassfish Slidecast
 
Building web APIs in PHP with Zend Expressive
Building web APIs in PHP with Zend ExpressiveBuilding web APIs in PHP with Zend Expressive
Building web APIs in PHP with Zend Expressive
 
Open Source Search: An Analysis
Open Source Search: An AnalysisOpen Source Search: An Analysis
Open Source Search: An Analysis
 
Php Security3895
Php Security3895Php Security3895
Php Security3895
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Jquery presentation
Jquery presentationJquery presentation
Jquery presentation
 

Viewers also liked

ZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of itZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of it
Steve Maraspin
 
Zend Framework 2 - PHPUnit
Zend Framework 2 - PHPUnitZend Framework 2 - PHPUnit
Zend Framework 2 - PHPUnit
Tarun Kumar Singhal
 
Moduli su Zend Framework 2: come sfruttarli
Moduli su Zend Framework 2: come sfruttarliModuli su Zend Framework 2: come sfruttarli
Moduli su Zend Framework 2: come sfruttarli
Stefano Valle
 
Elegant Ways of Handling PHP Errors and Exceptions
Elegant Ways of Handling PHP Errors and ExceptionsElegant Ways of Handling PHP Errors and Exceptions
Elegant Ways of Handling PHP Errors and Exceptions
ZendCon
 
Asset management with Zend Framework 2
Asset management with Zend Framework 2Asset management with Zend Framework 2
Asset management with Zend Framework 2
Stefano Valle
 
Instant ACLs with Zend Framework 2
Instant ACLs with Zend Framework 2Instant ACLs with Zend Framework 2
Instant ACLs with Zend Framework 2
Stefano Valle
 
Unit testing PHP apps with PHPUnit
Unit testing PHP apps with PHPUnitUnit testing PHP apps with PHPUnit
Unit testing PHP apps with PHPUnit
Michelangelo van Dam
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service Manager
Chris Tankersley
 
Zend Framework 2 : Dependency Injection
Zend Framework 2 : Dependency InjectionZend Framework 2 : Dependency Injection
Zend Framework 2 : Dependency Injection
Abdul Malik Ikhsan
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentation
Thanh Robi
 
Meet a parallel, asynchronous PHP world
Meet a parallel, asynchronous PHP worldMeet a parallel, asynchronous PHP world
Meet a parallel, asynchronous PHP world
Steve Maraspin
 
Clean Unit Test Patterns
Clean Unit Test PatternsClean Unit Test Patterns
Clean Unit Test Patterns
Frank Appel
 
Understanding Unit Testing
Understanding Unit TestingUnderstanding Unit Testing
Understanding Unit Testing
ikhwanhayat
 
Introduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitIntroduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnit
Michelangelo van Dam
 
Unit Testing Concepts and Best Practices
Unit Testing Concepts and Best PracticesUnit Testing Concepts and Best Practices
Unit Testing Concepts and Best Practices
Derek Smith
 
Zend Framework Workshop Parte2
Zend Framework Workshop Parte2Zend Framework Workshop Parte2
Zend Framework Workshop Parte2massimiliano.wosz
 
GAME ON! Integrating Games and Simulations in the Classroom
GAME ON! Integrating Games and Simulations in the Classroom GAME ON! Integrating Games and Simulations in the Classroom
GAME ON! Integrating Games and Simulations in the Classroom
Brian Housand
 

Viewers also liked (17)

ZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of itZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of it
 
Zend Framework 2 - PHPUnit
Zend Framework 2 - PHPUnitZend Framework 2 - PHPUnit
Zend Framework 2 - PHPUnit
 
Moduli su Zend Framework 2: come sfruttarli
Moduli su Zend Framework 2: come sfruttarliModuli su Zend Framework 2: come sfruttarli
Moduli su Zend Framework 2: come sfruttarli
 
Elegant Ways of Handling PHP Errors and Exceptions
Elegant Ways of Handling PHP Errors and ExceptionsElegant Ways of Handling PHP Errors and Exceptions
Elegant Ways of Handling PHP Errors and Exceptions
 
Asset management with Zend Framework 2
Asset management with Zend Framework 2Asset management with Zend Framework 2
Asset management with Zend Framework 2
 
Instant ACLs with Zend Framework 2
Instant ACLs with Zend Framework 2Instant ACLs with Zend Framework 2
Instant ACLs with Zend Framework 2
 
Unit testing PHP apps with PHPUnit
Unit testing PHP apps with PHPUnitUnit testing PHP apps with PHPUnit
Unit testing PHP apps with PHPUnit
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service Manager
 
Zend Framework 2 : Dependency Injection
Zend Framework 2 : Dependency InjectionZend Framework 2 : Dependency Injection
Zend Framework 2 : Dependency Injection
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentation
 
Meet a parallel, asynchronous PHP world
Meet a parallel, asynchronous PHP worldMeet a parallel, asynchronous PHP world
Meet a parallel, asynchronous PHP world
 
Clean Unit Test Patterns
Clean Unit Test PatternsClean Unit Test Patterns
Clean Unit Test Patterns
 
Understanding Unit Testing
Understanding Unit TestingUnderstanding Unit Testing
Understanding Unit Testing
 
Introduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitIntroduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnit
 
Unit Testing Concepts and Best Practices
Unit Testing Concepts and Best PracticesUnit Testing Concepts and Best Practices
Unit Testing Concepts and Best Practices
 
Zend Framework Workshop Parte2
Zend Framework Workshop Parte2Zend Framework Workshop Parte2
Zend Framework Workshop Parte2
 
GAME ON! Integrating Games and Simulations in the Classroom
GAME ON! Integrating Games and Simulations in the Classroom GAME ON! Integrating Games and Simulations in the Classroom
GAME ON! Integrating Games and Simulations in the Classroom
 

Similar to Error Reporting in ZF2: form messages, custom error pages, logging

Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
Michelangelo van Dam
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
Shinya Ohyanagi
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
Bernhard Schussek
 
CakePHP workshop
CakePHP workshopCakePHP workshop
CakePHP workshop
Walther Lalk
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
Marcus Ramberg
 
Data::FormValidator Simplified
Data::FormValidator SimplifiedData::FormValidator Simplified
Data::FormValidator Simplified
Fred Moyer
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::ManagerJay Shirley
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
Michelangelo van Dam
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
Michelangelo van Dam
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
Jorn Oomen
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application framework
Dustin Filippini
 
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate ModuleDigital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Erich Beyrent
 
HTML::FormFu talk for Sydney PM
HTML::FormFu talk for Sydney PMHTML::FormFu talk for Sydney PM
HTML::FormFu talk for Sydney PM
Dean Hamstead
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Michelangelo van Dam
 
Moodle Quick Forms
Moodle Quick FormsMoodle Quick Forms
Moodle Quick Forms
Jalpa Bhavsar
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
Michelangelo van Dam
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
Michelangelo van Dam
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
Michelangelo van Dam
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
Nate Abele
 

Similar to Error Reporting in ZF2: form messages, custom error pages, logging (20)

Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
 
CakePHP workshop
CakePHP workshopCakePHP workshop
CakePHP workshop
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Data::FormValidator Simplified
Data::FormValidator SimplifiedData::FormValidator Simplified
Data::FormValidator Simplified
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application framework
 
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate ModuleDigital Mayflower - Data Pilgrimage with the Drupal Migrate Module
Digital Mayflower - Data Pilgrimage with the Drupal Migrate Module
 
HTML::FormFu talk for Sydney PM
HTML::FormFu talk for Sydney PMHTML::FormFu talk for Sydney PM
HTML::FormFu talk for Sydney PM
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 
Moodle Quick Forms
Moodle Quick FormsMoodle Quick Forms
Moodle Quick Forms
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
The new form framework
The new form frameworkThe new form framework
The new form framework
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 

More from Steve Maraspin

Architetture a Microservizi (con Kubernetes)
Architetture a Microservizi (con Kubernetes)Architetture a Microservizi (con Kubernetes)
Architetture a Microservizi (con Kubernetes)
Steve Maraspin
 
How Agile changed Software Development
How Agile changed Software DevelopmentHow Agile changed Software Development
How Agile changed Software Development
Steve Maraspin
 
Principi di Interaction Design
Principi di Interaction DesignPrincipi di Interaction Design
Principi di Interaction Design
Steve Maraspin
 
Customer Journey Mapping Workshop
Customer Journey Mapping WorkshopCustomer Journey Mapping Workshop
Customer Journey Mapping Workshop
Steve Maraspin
 
A (really) Quick Introduction to Event Storming
A (really) Quick Introduction to Event StormingA (really) Quick Introduction to Event Storming
A (really) Quick Introduction to Event Storming
Steve Maraspin
 
Don't Make Me Think - There's no need (2014)
Don't Make Me Think - There's no need (2014)Don't Make Me Think - There's no need (2014)
Don't Make Me Think - There's no need (2014)
Steve Maraspin
 
The Metaphor Fallacy (in Digital Product Development)
The Metaphor Fallacy (in Digital Product Development)The Metaphor Fallacy (in Digital Product Development)
The Metaphor Fallacy (in Digital Product Development)
Steve Maraspin
 
Lean UX: Sviluppo Software Agile e Incentrato sull'Utente
Lean UX: Sviluppo Software Agile e Incentrato sull'UtenteLean UX: Sviluppo Software Agile e Incentrato sull'Utente
Lean UX: Sviluppo Software Agile e Incentrato sull'Utente
Steve Maraspin
 
La filosofia Lean nello sviluppo di prodotti digitali
La filosofia Lean nello sviluppo di prodotti digitaliLa filosofia Lean nello sviluppo di prodotti digitali
La filosofia Lean nello sviluppo di prodotti digitali
Steve Maraspin
 
Outcome not Output: A Story of Lean UX Adoption
Outcome not Output: A Story of Lean UX AdoptionOutcome not Output: A Story of Lean UX Adoption
Outcome not Output: A Story of Lean UX Adoption
Steve Maraspin
 
Don't Make me Think - There's no Need
Don't Make me Think - There's no NeedDon't Make me Think - There's no Need
Don't Make me Think - There's no Need
Steve Maraspin
 
Fare con Zend Framework 2 ciò che facevo con ZF1
Fare con Zend Framework 2 ciò che facevo con ZF1Fare con Zend Framework 2 ciò che facevo con ZF1
Fare con Zend Framework 2 ciò che facevo con ZF1
Steve Maraspin
 
NoSQL Data Stores: Introduzione alle Basi di Dati Non Relazionali
NoSQL Data Stores: Introduzione alle Basi di Dati Non RelazionaliNoSQL Data Stores: Introduzione alle Basi di Dati Non Relazionali
NoSQL Data Stores: Introduzione alle Basi di Dati Non Relazionali
Steve Maraspin
 
Polyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDB
Polyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDBPolyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDB
Polyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDB
Steve Maraspin
 
NoSQL, No Worries: Vecchi Problemi, Nuove Soluzioni
NoSQL, No Worries: Vecchi Problemi, Nuove SoluzioniNoSQL, No Worries: Vecchi Problemi, Nuove Soluzioni
NoSQL, No Worries: Vecchi Problemi, Nuove Soluzioni
Steve Maraspin
 
Permettere al cliente di apprezzare l'approccio agile
Permettere al cliente di apprezzare l'approccio agilePermettere al cliente di apprezzare l'approccio agile
Permettere al cliente di apprezzare l'approccio agile
Steve Maraspin
 
Let customers appreciate the agile workflow
Let customers appreciate the agile workflowLet customers appreciate the agile workflow
Let customers appreciate the agile workflow
Steve Maraspin
 
Esempio di architettura distribuita basata su PHP, CouchDB e Mobile
Esempio di architettura distribuita basata su PHP, CouchDB e MobileEsempio di architettura distribuita basata su PHP, CouchDB e Mobile
Esempio di architettura distribuita basata su PHP, CouchDB e Mobile
Steve Maraspin
 
Striving towards better PHP code
Striving towards better PHP codeStriving towards better PHP code
Striving towards better PHP code
Steve Maraspin
 

More from Steve Maraspin (19)

Architetture a Microservizi (con Kubernetes)
Architetture a Microservizi (con Kubernetes)Architetture a Microservizi (con Kubernetes)
Architetture a Microservizi (con Kubernetes)
 
How Agile changed Software Development
How Agile changed Software DevelopmentHow Agile changed Software Development
How Agile changed Software Development
 
Principi di Interaction Design
Principi di Interaction DesignPrincipi di Interaction Design
Principi di Interaction Design
 
Customer Journey Mapping Workshop
Customer Journey Mapping WorkshopCustomer Journey Mapping Workshop
Customer Journey Mapping Workshop
 
A (really) Quick Introduction to Event Storming
A (really) Quick Introduction to Event StormingA (really) Quick Introduction to Event Storming
A (really) Quick Introduction to Event Storming
 
Don't Make Me Think - There's no need (2014)
Don't Make Me Think - There's no need (2014)Don't Make Me Think - There's no need (2014)
Don't Make Me Think - There's no need (2014)
 
The Metaphor Fallacy (in Digital Product Development)
The Metaphor Fallacy (in Digital Product Development)The Metaphor Fallacy (in Digital Product Development)
The Metaphor Fallacy (in Digital Product Development)
 
Lean UX: Sviluppo Software Agile e Incentrato sull'Utente
Lean UX: Sviluppo Software Agile e Incentrato sull'UtenteLean UX: Sviluppo Software Agile e Incentrato sull'Utente
Lean UX: Sviluppo Software Agile e Incentrato sull'Utente
 
La filosofia Lean nello sviluppo di prodotti digitali
La filosofia Lean nello sviluppo di prodotti digitaliLa filosofia Lean nello sviluppo di prodotti digitali
La filosofia Lean nello sviluppo di prodotti digitali
 
Outcome not Output: A Story of Lean UX Adoption
Outcome not Output: A Story of Lean UX AdoptionOutcome not Output: A Story of Lean UX Adoption
Outcome not Output: A Story of Lean UX Adoption
 
Don't Make me Think - There's no Need
Don't Make me Think - There's no NeedDon't Make me Think - There's no Need
Don't Make me Think - There's no Need
 
Fare con Zend Framework 2 ciò che facevo con ZF1
Fare con Zend Framework 2 ciò che facevo con ZF1Fare con Zend Framework 2 ciò che facevo con ZF1
Fare con Zend Framework 2 ciò che facevo con ZF1
 
NoSQL Data Stores: Introduzione alle Basi di Dati Non Relazionali
NoSQL Data Stores: Introduzione alle Basi di Dati Non RelazionaliNoSQL Data Stores: Introduzione alle Basi di Dati Non Relazionali
NoSQL Data Stores: Introduzione alle Basi di Dati Non Relazionali
 
Polyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDB
Polyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDBPolyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDB
Polyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDB
 
NoSQL, No Worries: Vecchi Problemi, Nuove Soluzioni
NoSQL, No Worries: Vecchi Problemi, Nuove SoluzioniNoSQL, No Worries: Vecchi Problemi, Nuove Soluzioni
NoSQL, No Worries: Vecchi Problemi, Nuove Soluzioni
 
Permettere al cliente di apprezzare l'approccio agile
Permettere al cliente di apprezzare l'approccio agilePermettere al cliente di apprezzare l'approccio agile
Permettere al cliente di apprezzare l'approccio agile
 
Let customers appreciate the agile workflow
Let customers appreciate the agile workflowLet customers appreciate the agile workflow
Let customers appreciate the agile workflow
 
Esempio di architettura distribuita basata su PHP, CouchDB e Mobile
Esempio di architettura distribuita basata su PHP, CouchDB e MobileEsempio di architettura distribuita basata su PHP, CouchDB e Mobile
Esempio di architettura distribuita basata su PHP, CouchDB e Mobile
 
Striving towards better PHP code
Striving towards better PHP codeStriving towards better PHP code
Striving towards better PHP code
 

Recently uploaded

Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 

Recently uploaded (20)

Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 

Error Reporting in ZF2: form messages, custom error pages, logging

  • 1. Error Reporting in Zend Framework 2 Zend Framework Day – Turin, Italy – 07/02/2014
  • 11.
  • 15. User Input = Mistake Source
  • 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
  • 21. 21
  • 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(); // ... } //... }
  • 24. Adding Form Fields public function init() { $this->setName('contact'); $this->setAttribute('method', 'post'); […].. $this->add(array('name' => 'email', 'type' => 'text', 'options' => array( 'label' => 'Name', ), ); $this->add(array('name' => 'message', 'type' => 'textarea', 'options' => array( 'label' => 'Message', ), ); //. […].. }
  • 25. Adding Form Fields public function init() { $this->setName('contact'); $this->setAttribute('method', 'post'); […].. $this->add(array('name' => 'email', 'type' => 'text', 'options' => array( 'label' => 'Name', ), ); $this->add(array('name' => 'message', 'type' => 'textarea', 'options' => array( 'label' => 'Message', ), ); //. […].. }
  • 28. Validation: inputFilter <?php namespace ApplicationForm; […] class ContactFilter extends InputFilter { public function __construct() { // filters go here } }
  • 29. Validation: inputFilter <?php namespace ApplicationForm; […] class ContactFilter extends InputFilter { public function __construct() { // filters go here } }
  • 30. Required Field Validation $this->add(array( 'name' => 'email', 'required' => true, 'filters' => array( array( 'name' => 'StringTrim'), ), 'validators' => array( array( 'name' => 'EmailAddress', ) ) ));
  • 31. Required Field Validation $this->add(array( 'name' => 'email', 'required' => true, 'filters' => array( array( 'name' => 'StringTrim'), ), 'validators' => array( array( 'name' => 'EmailAddress', ) ) ));
  • 32. InputFilter Usage <?php namespace ApplicationController; […] class IndexController extends AbstractActionController { public function contactAction() { $form = new Contact(); $filter = new ContactFilter(); $form->setInputFilter($filter); return new ViewModel(array( 'form' => $form ); } }
  • 33. InputFilter Usage <?php namespace ApplicationController; […] class IndexController extends AbstractActionController { public function contactAction() { $form = new Contact(); $filter = new ContactFilter(); $form->setInputFilter($filter); return new ViewModel(array( 'form' => $form ); } }
  • 36. Error Message Customization $this->add(array( 'name' => 'email', 'required' => true, 'filters' => array( array('name' => 'StringTrim'), ), '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' ), ), ), array('name' => 'EmailAddress'), ) ));
  • 37. Error Message Customization $this->add(array( 'name' => 'email', 'required' => true, 'filters' => array( array('name' => 'StringTrim'), ), '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' ), ), ), array('name' => 'EmailAddress'), ) ));
  • 38. More than we need…
  • 39. Check Chain $this->add(array( 'name' => 'email', 'required' => true, 'filters' => array( array('name' => 'StringTrim'), ), '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'), ) ));
  • 42.
  • 43.
  • 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.', )));
  • 51. Default Message Translation public function onBootstrap(MvcEvent $e) { $translator = $e->getApplication() ->getServiceManager()->get('translator'); $translator->addTranslationFile( 'phpArray', __DIR__ . '/../../vendor/zendframework/zendframework/'. 'resources/languages/it/Zend_Validate.php', 'default', 'it_IT' ); AbstractValidator::setDefaultTranslator($translator); }
  • 52. Custom Message Translation $this->add(array( 'name' => 'email', 'required' => true, 'validators' => array( array('name' =>'NotEmpty', 'options' => array( 'translator' => $translator, 'message' => $translator->translate( 'Make sure your e-mail address contains the @ symbol and a valid domain name.' )), 'break_chain_on_failure' => true, ), )));
  • 53. Form Factory $translator = $I_services->get('translator'); $I_form = new Contact(); $I_filter = new ContactFilter($translator); $I_form->setInputFilter($I_filter); return $I_form;
  • 56. 56
  • 57.
  • 58. Error Display Configuration Skeleton Applicaton Configuration
  • 59. Hiding Exception Traces 'view_manager' => array( 'display_not_found_reason' => false, 'display_exceptions' => false, 'doctype' => 'HTML5', 'not_found_template' => 'error/404', 'exception_template' => 'error/index', 'template_map' => array( 'layout/layout' => __DIR__ . '/../view/layout/layout.phtml', 'application/index/index'=> __DIR__ . '/../view/application/index/index.phtml', 'error/404' => __DIR__ . '/../view/error/404.phtml', 'error/index' => __DIR__ . '/../view/error/index.phtml', ), 'template_path_stack' => array( __DIR__ . '/../view', ), ),
  • 60. Hiding Exception Traces 'view_manager' => array( 'display_not_found_reason' => false, 'display_exceptions' => false, 'doctype' => 'HTML5', 'not_found_template' => 'error/404', 'exception_template' => 'error/index', 'template_map' => array( 'layout/layout' => __DIR__ . '/../view/layout/layout.phtml', 'application/index/index'=> __DIR__ . '/../view/application/index/index.phtml', 'error/404' => __DIR__ . '/../view/error/404.phtml', 'error/index' => __DIR__ . '/../view/error/index.phtml', ), 'template_path_stack' => array( __DIR__ . '/../view', ), ),
  • 61.
  • 62. Custom Error Pages 'view_manager' => array( 'display_not_found_reason' => false, 'display_exceptions' => false, 'doctype' => 'HTML5', 'not_found_template' => 'error/404', 'exception_template' => 'error/index', 'template_map' => array( 'layout/layout' => __DIR__ . '/../view/layout/layout.phtml', 'application/index/index'=> __DIR__ . '/../view/application/index/index.phtml', 'error/404' => __DIR__ . '/../view/error/404.phtml', 'error/index' => __DIR__ . '/../view/error/index.phtml', ), 'template_path_stack' => array( __DIR__ . '/../view', ), ),
  • 63.
  • 64. How about PHP Errors? class IndexController extends AbstractActionController { public function indexAction() { 1/0; return new ViewModel(); } }
  • 65. How about PHP Errors? class IndexController extends AbstractActionController { public function indexAction() { 1/0; return new ViewModel(); } }
  • 66.
  • 68. What can we do?
  • 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
  • 75. Fatal Error Handling public function onBootstrap(MvcEvent $I_e) { […] $am_config = $I_application->getConfig(); $am_environmentConf = $am_config['mvlabs_environment']; // Fatal Error Recovery if (array_key_exists('recover_from_fatal', $am_environmentConf) && $am_environmentConf['recover_from_fatal']) { $s_redirectUrl = $am_environmentConf['redirect_url']; } $s_callback = null; if (array_key_exists('fatal_errors_callback', $am_environmentConf)) { $s_callback = $am_environmentConf['fatal_errors_callback']; } register_shutdown_function(array('ApplicationModule', 'handleFatalPhpErrors'), $s_redirectUrl, $s_callback); }
  • 76. Fatal Error Handling /** * Redirects user to nice page after fatal has occurred */ public static function handleFatalPhpErrors($s_redirectUrl, $s_callback = null) { if (php_sapi_name() != 'cli' && @is_Array($e = @get_last())) { if (null != $s_callback) { // This is the most stuff we can get. // New context outside of framework scope $m_code = isset($e['type']) ? $e['type'] : 0; $s_msg = isset($e['message']) ? $e['message']:''; $s_file = isset($e['file']) ? $e['file'] : ''; $i_line = isset($e['line']) ? $e['line'] : ''; $s_callback($s_msg, $s_file, $i_line); } header("location: ". $s_redirectUrl); } return false; }
  • 77. Fatal Error Handling 'mvlabs_environment' => array( 'exceptions_from_errors' => true, 'recover_from_fatal' => true, 'fatal_errors_callback' => function($s_msg, $s_file, $s_line) { return false; }, 'redirect_url' => '/error', 'php_settings' => array( 'error_reporting' => E_ALL, 'display_errors' => 'Off', 'display_startup_errors' => 'Off', ), ),
  • 78. PHP Settings Conf 'mvlabs_environment' => array( 'exceptions_from_errors' => true, 'recover_from_fatal' => true, 'fatal_errors_callback' => function($s_msg, $s_file, $s_line) { return false; }, 'redirect_url' => '/error', 'php_settings' => array( 'error_reporting' => E_ALL, 'display_errors' => 'Off', 'display_startup_errors' => 'Off', ), ),
  • 79. PHP Settings public function onBootstrap(MvcEvent $I_e) { […] foreach($am_phpSettings as $key => $value) { ini_set($key, $value); } }
  • 81. CUSTOMER SUPPORT TEAM REACTION http://www.flickr.com/photos/18548283@N00/8030280738
  • 82.
  • 87. Index.php // Application wide configuration $am_conf = $am_originalConf = require 'config/application.config.php'; // Environment specific configuration $s_environmentConfFile = 'config/application.'.$s_env.'.config.php'; if (file_exists($s_environmentConfFile) && is_readable($s_environmentConfFile)) { // Specific environment configuration merge $am_environmentConf = require $s_environmentConfFile; $am_conf = ZendStdlibArrayUtils::merge($am_originalConf, $am_environmentConf ); } // Additional Specific configuration files are also taken into account $am_conf["module_listener_options"]["config_glob_paths"][] = 'config/autoload/{,*.}' . $s_env . '.php'; ZendMvcApplication::init($am_conf)->run();
  • 90. Enabling Environment Confs // Application nominal environment $am_conf = $am_originalConf = require 'config/application.config.php'; // Environment specific configuration $s_environmentConfFile = 'config/application.'.$s_env.'.config.php'; // Do we have a specific configuration file? if (file_exists($s_environmentConfFile) && is_readable($s_environmentConfFile)) { // Specific environment configuration merge $am_environmentConf = require $s_environmentConfFile; $am_conf = ZendStdlibArrayUtils::merge($am_originalConf, $am_environmentConf ); } // Additional Specific configuration files are also taken into account $am_conf["module_listener_options"]["config_glob_paths"][] = 'config/autoload/{,*.}' . $s_env . '.php'; ZendMvcApplication::init($am_conf)->run();
  • 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!'); }
  • 93. Apache Config File <VirtualHost *:80> DocumentRoot /srv/apps/zfday/public ServerName www.dev.zfday.it SetEnv APPLICATION_ENV "dev" <Directory /srv/apps/zfday/public> AllowOverride FileInfo </Directory> </VirtualHost>
  • 95. Why Log? Troubleshooting • Stats Generation • Compliance • 95
  • 96. Zend Log $logger = new ZendLogLogger; $writer = new ZendLogWriterStream('/var/log/app.log'); $logger->addWriter($writer); $logger->info('Informational message'); $logger->log(ZendLogLogger::EMERG, 'Emergency message');
  • 97. Zend Log $logger = new ZendLogLogger; $writer = new ZendLogWriterStream('/var/log/app.log'); $logger->addWriter($writer); $logger->info('Informational message'); $logger->log(ZendLogLogger::EMERG, 'Emergency message'); ZendLogLogger::registerErrorHandler($logger); ZendLogLogger::registerExceptionHandler($logger);
  • 105. Filter Example $logger = new ZendLogLogger; $writer1 = new ZendLogWriterStream('/var/log/app.log'); $logger->addWriter($writer1); $writer2 = new ZendLogWriterStream('/var/log/err.log'); $logger->addWriter($writer2); $filter = new ZendLogFilterPriority(Logger::CRIT); $writer2->addFilter($filter); $logger->info('Informational message'); $logger->log(ZendLogLogger::CRIT, 'Emergency message');
  • 106. Monolog use MonologLogger; use MonologHandlerStreamHandler; $log = new Logger('name'); $log->pushHandler(new StreamHandler('/var/log/app.log', Logger::WARNING)); $log->addWarning('Foo'); $log->addError('Bar');
  • 108. How to log? class IndexController { public function helloAction() { return new ViewModel('msg' =>"Hello!"); } }
  • 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!"); } }
  • 114. What can we do?
  • 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!"); } }
  • 121. Handling Framework Errors class Module { public function onBootstrap(MvcEvent $e) { $eventManager = $e->getApplication() ->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager); $logger = $sm->get('logger'); $eventManager->attach(MvcEvent::EVENT_RENDER_ERROR, function(MvcEvent $e) use ($logger) { $logger->info('An exception has Happened ' . $e->getResult()->exception->getMessage()); }, -200); ); } }
  • 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
  • 124.
  • 125.
  • 126.
  • 129. Starting Things Up input { stdin { } } output { stdout { codec => rubydebug } }
  • 130. Starting Things Up input { stdin { } } output { stdout { codec => rubydebug } } java -jar logstash-1.3.3-flatjar.jar agent -f sample.conf
  • 131. Integrated Elasticsearch input { file { path => ["/opt/logstash/example.log"] } } output { stdout { codec => rubydebug } elasticsearch { embedded => true } } java -jar logstash-1.3.3-flatjar.jar agent -f elastic.conf
  • 132. Integrated Web Interface input { file { path => ["/opt/logstash/example.log"] } } output { stdout { codec => rubydebug } elasticsearch { embedded => true } } java -jar logstash.jar agent -f elastic.conf --web
  • 133. Kibana
  • 134. Thank you for your attention Stefano Maraspin @maraspin