Posts Tagged ‘zf2’

MVC in ZF2


ZF2 file structure






  ‘modules’ =>array( //list of modules you want to use
  ) ,
  ‘module_listener_options’ =>array( //modules options as autoloading and paths
    ‘config_glob_paths’ => array(


ServiceManager is a Service Locator where you register services and later retrive them by configuration.

Types of services: explicit services, invokables to instatiate, factory returing object, aliases, unknown services, scoped containers, shared or not.


namespace Application;

use ZendMvcModuleRouteListener;
use ZendMvcMvcEvent;

class Module
  public function getConfig(){
    return include __DIR__ . ‘/config/module.config.php’;


return array(
        ‘type’=>’ZendMvcRouterHttpLiteral’, //You can use Segment type
/* … */


namespace ApplicationController;

use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;

class IndexController extends AbstractActionController
  public function indexAction(){
    return ViewModel();

The ViewModel will return view/application/index/index.phtml contents.

Source Zend webinar.

Get started to zf2 and why to switch from zf1

  • ZF1 way: Singletons, registers, soft and hard dependencies
  • ZF2 way: Even-Driven Services flexibility, better secure defaults, contexts of escaping, dependencies injection (inversion of control).

Instead of using hard dependencies and dificult to test code:

public function someAction(){  $front = Zend_Controller_Front::getInstance();  $bootstrap = $front->getParam('bootstrap');  $db = $bootstrap->getResource('db');  $service = new SomeService($db);  $this->view->results = $service->doSomething();}


With ZF2 you can achieve this:

public function setService($service){  $this->service = $service;}public function someAction(){  return array(    'results' => $this->service->doSomething();  ); }

You need to use Dependency Injection when getting the controller:

function ($controllers){  $services = $controllers->getServiceLocator();  $service = $services->get('SomeService');  $controller = new SomeController();  $controller->setService($service);  return $controller;}


  • Easy replacements which means easier to test
  • Code for construcion is located in one place, easy reviewed place.
  • You can do things for separate services more easily



No discovery, you code injections. Explicit writing means less debuging

//Explicit services
array(‘services’, array(
  ‘foo’=>new SomeComponentFoo,
//Instantiable class
array(‘invokables’, array(
//Callable that returns and object
array(‘factories’, array(
    return new SomeComponentFoo(
//Callable that handles multiple services
array(‘abstract_factories’, array(
//Example of abstract factory
class SampleAbstractFactory implements AbstractFactoryInterface {
  public funtion canCreateServiceWithName(
   ServiceLocatorInterface $services, $name, $requestedName
  ) { /* code.. */ }
  public funtion createServiceWithName  /* code.. */

//(un)Share a service
array(‘shared’, array(
  ‘EventManager’=>false, //default is true
//Operations on new instances, for example to automate injections like this
array(‘initializers’, array(
  function($instance, $services) {
    if($instance instanceof EventManagerAwareInterface) {
//Plugin example. $heplers is view helper plugin manager instance
array(‘factories’, array(
  ‘something’=> function($helpers) {
    $services = $helpers->getServiceLocator();
    $model = $services->get(‘SomeModel’);
    $helper = new SomethingHelper($model);
    return $helper;

Event Manager

Listen and react to trigger events in simple way

$events = new EventManager();
$events->attach(‘do’, function($e){
  $event = $e->getName();
  $params= $e->getParams();
  printf(‘Handled event %s with parameters %s, 
  $event, json_enccode($params));
$params=array(‘foo’ => ‘bar’, ‘baz’ => ‘bat’);
$events->trigger(‘do, null, $params);

Listen and react to trigger events to a group of objects or objects that don’t exist yet.

$shared = $events->getSharedEventManager();
$shared =  $services->get(‘SharedEventManager’);

$shared->attach(‘ZendStdlibDispatchableInterface’, ‘dispatch’, $callback, $priority);

Everything is an event

Boostrap listeners run modules, route listeners run modules, dispatch listeners run modules.

Controllers are services

Use ServiceManager to wire default workflow and event listeners.

Plug and play modules

They should do one thing and do it well. They provide services for MVC and wire event listeners.

 Modules are implemented as a namespace with a single Module.php class file.



Module example

Edit module/MyMarkdown/Module.php

namespace  MyMarkdown;

use ZendViewHelperAbstractHelper;

class Module extends AbstractHelper
  public function getViewHelperConfig(){
    return array(‘services’, array(‘markdown’ => $this));
  public function __invoke($string = null){
    require_once ‘php-markdown/markdown.php’;
    return Markdown($string);

Add the MyMarkdown module to application in config/application.config.php

return array(
  ‘modules’ => array(
  /* … */

Test it in view script

<?= $this->markdown($this->someMarkdowntext) ?> 

What you can do if the module you want exist? Use ‘git submodule add’, add module name to your config/application.config.php file and you are done.


Controller example

They are very similar than in ZF1. In ZF2 you return something.

namespace ApplicationController;

use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;

class IndexController extends AbstractActionController
  public function indexAction()
    return new ViewModel();


Key points to remember for using ZF2

  • Know to configure services.
  • Know to wire event listeners.
  • Controllers return informa
    tion as they are now services.
  • Modules inform the MVC of services (controllers!) and wire events.


Secure Zend Framework programing in ZF2


Comments on this webinar:

What are the most common security risks?

OWASP Top 10 Application Security Risks – 2010

A1-Injection Injection flaws, such as SQL, OS, and LDAP injection, occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing unauthorized data.
A2-Cross Site Scripting (XSS) XSS flaws occur whenever an application takes untrusted data and sends it to a web browser without proper validation and escaping. XSS allows attackers to execute scripts in the victim’s browser which can hijack user sessions, deface web sites, or redirect the user to malicious sites.
A3-Broken Authentication and Session Management Application functions related to authentication and session management are often not implemented correctly, allowing attackers to compromise passwords, keys, session tokens, or exploit other implementation flaws to assume other users’ identities.
A4-Insecure Direct Object References A direct object reference occurs when a developer exposes a reference to an internal implementation object, such as a file, directory, or database key. Without an access control check or other protection, attackers can manipulate these references to access unauthorized data.
A5-Cross Site Request Forgery (CSRF) A CSRF attack forces a logged-on victim’s browser to send a forged HTTP request, including the victim’s session cookie and any other automatically included authentication information, to a vulnerable web application. This allows the attacker to force the victim’s browser to generate requests the vulnerable application thinks are legitimate requests from the victim.
A6-Security Misconfiguration Good security requires having a secure configuration defined and deployed for the application, frameworks, application server, web server, database server, and platform. All these settings should be defined, implemented, and maintained as many are not shipped with secure defaults. This includes keeping all software up to date, including all code libraries used by the application.
A7-Insecure Cryptographic Storage Many web applications do not properly protect sensitive data, such as credit cards, SSNs, and authentication credentials, with appropriate encryption or hashing. Attackers may steal or modify such weakly protected data to conduct identity theft, credit card fraud, or other crimes.
A8-Failure to Restrict URL Access Many web applications check URL access rights before rendering protected links and buttons. However, applications need to perform similar access control checks each time these pages are accessed, or attackers will be able to forge URLs to access these hidden pages anyway.
A9-Insufficient Transport Layer Protection Applications frequently fail to authenticate, encrypt, and protect the confidentiality and integrity of sensitive network traffic. When they do, they sometimes support weak algorithms, use expired or invalid certificates, or do not use them correctly.
A10-Unvalidated Redirects and Forwards Web applications frequently redirect and forward users to other pages and websites, and use untrusted data to determine the destination pages. Without proper validation, attackers can redirect victims to phishing or malware sites, or use forwards to access unauthorized pages.


“Filter input, escape output”
Yest, but it’s not enough.

Security tools in ZF2

  • ZendAuthentication
  • ZendPermissions
  • ZendFilter
  • ZendValidator
  • ZendInputFilter
  • ZendEscaper
  • ZendCaptcha
  • ZendCrypt
  • ZendMath



    API for authentication and includes concrete authentication adapters for common use case scenarios:

    • Database table
    • Digest
    • HTTP
    • LDAP
    • Or your custom authentication adapter…

    Example of ZendAuthentication use:

      use ZendAuthenticationAuthenticationService;$auth = new AuthenticationService();$authAdapter = new MyAuthAdapter($username, $password);if(!$result->isValid()){//auth failedvar_dump($result->getMessages());}else{//auth success, $username is stored in the session}


      Proviedes access control list (ACL) for privileges management

      • Resource: An object which access is controlled
      • Role: An object that may request access to a resource.

      Example of ZendPermissions use:

      use ZendPermissionsAclAcl;use ZendPermissionsAclRoleGenericRole as Role;use ZendPermissionsAclResourceGenericResource as Resource;$acl = new Acl();$acl->addRole(new Role('guest'));    ->addRole(new Role('member'));    ->addRole(new Role('admin'));$parents = array('guest', 'member', 'admin');$acl->addRole(new('someUser'), $parents);$acl->addResource(new Resource('someResource'));$acl->deny('guest', 'someResource');$acl->deny('member', 'someResource');echo $acl->isAllowed('someUser', 'someResource')? 'allowed' : 'denied';

      ZendPermissionsRbac adapter in ZF2.1 is a new Role-Based Access Control based in PHP 5.3 SPL RecursiveIterator. It put emphasis on roles and their permissions rather than resource objects:

      • identity: one or more roles
      • role: requests acces to a permission
      • permission is givet to a role.



      Provides a set of commonly needed data filters and a chainging mechanism by which multiple filters may be applied.

      Standard Filter Classes…

      • Alnum
      • Alpha
      • BaseName
      • Boolean
      • Compress/Decompress
      • Digits
      • Dir
      • Encrypt/Decrypt
      • HtmlEntities
      • Int
      • Null
      • NumberFormat
      • PregReplace
      • RealPath
      • StringToLower/ToUpper
      • StringTrim
      • StripNewLines/Tags
      • Callback (custom filter)



      Provides a set of commonly needed validators and a validator chainging mechanism by which multiple validators may be applied.

      It examines its input with respecto to requirements and
      productes a boolean result whether the input successfully validates against the requirements.

      $validator = new ZendValidatorEmailAddress;
      if(!$validator->isValid($email)){//valid email}else{//print reasons email is invalidvar_dump($validator->getMessages());}


      Standard Validator Classes…

      • Alnum
      • Alpha
      • Barcode
      • Between
      • CreditCard
      • Date
      • DbRecordExists and NoRecordExists
      • Digits
      • EmailAddress
      • GreaterThan/LessThan
      • Hex
      • Hostname
      • Iban
      • Identical
      • InArray
      • Ip
      • Isbn
      • NotEmpty
      • PostCode
      • Regex
      • Sitemap
      • Step
      • StringLength
      • Callback (custom filter)



      Can be used to filter and validate generic sets of input data. For instance $_GET, $_POST, CLI, etc

      use ZendInputFilterInputFilter;use ZendInputFilterInput;use ZendValidator;$email = new Input('email');$email->getValidatorChain()  ->addValidator(new ValidatorEmailAddress());$password = new Input('password');$password ->getValidatorChain()  ->addValidator(new ValidatorStringLength(8));$inputFilter = new InputFilter();$inputFilter->add($email)            ->add($password)            ->setData($_POST);if(!$inputFilter->isValid()){//form is valid}else{//print reasons form is invalidvar_dump($inputFilter->getInvalidInput());}




      Always escape the output, multiple formats:

      • escapeHtml()
      • escapeHtmlAttr()
      • escapeJs()
      • escapeUrl()
      • EscapeCss()


      Prevent submision from automated tools (Figlet, AbstractWord, Dumb, Image, ReCaptcha)

      $captcha = new ZendCaptchaFiglet(array( 'name=>'foo', 'wordLen'=>6, 'timeout'=>300,));$id = $captcha->generate();echo $captcha->getFiglet()->render($captcha->getWord());//On subsequent requestif($captcha->isValid($_POST['foo'], $_POST)){  //validated}



      Use cryptography in a convenient way (instead of php built-in functions and extensions crypt, mcrypt, openssl, hash, mhash):

      • ZendCryptPassword
      • ZendCryptKeyDerivation
      • ZendCryptSymmetric
      • ZendCryptPublicKey
      • ZendCryptHash
      • ZendCryptHmac
      • ZendCryptBlockCipher

      Example of how to encrypt sensitive data:

      • ZendCryptBlockCipher symmetric encryption and authenication (HMAC)
      • Simplified API: setKey($key), encrypt($data), decrupt($data) uses Mcrypt adapter (Zend CryptSymmetricMcrypy) for us.
      • Defult values used by BlockCipher:
        • AES (256 bits key)
        • CBC mode + HMAC (SHA-256)
        • PKCS6 padding mode (RFC 5652)
        • PBKDF2 to generate encryption key + auth key for HMAC
        • Random IV for each encryption

      BlockCipher using AES encryption

      use ZendCryptBlockCipher;$cipher = BlockCipher::factory(  'mcrypt',   array('algorithm' => 'aes'));$cipher->setKey('this is the encryption key');$plaintext = 'This is the sensitive message to encrypt';//encoded base64, get binary using setBinaryOutput(true)$encrypted = $cipher->encrypt($plaintext);// You will see three parts: HMAC, IV and ciphertextprintf("encrypted text: %sn", $encrypted); file_put_contents('test.crypt',  $encrypted);


      BlockCipher decryption

      use ZendCryptBlockCipher;$cipher = BlockCipher::factory(  'mcrypt',   array('algorithm' => 'aes'));$cipher->setKey('this is the encryption key');$encrypted = file_get_contents('test.crypt');$plaintext = $cipher->decrypt($encrypted );printf("Dencrypted text: %sn", $plaintext );


      Example of how to store a password:

      Insecure, old school: MD5 password or/and salt random string (In a 4 core CPU you can break md5 8 char passwords in less than 2 hours)

      New way: bcrypt (Blowfish cipher is secure way now)

      bcrypt is secure because is very slow and attacks need huge amount of time to be completed (cost value determine how expensive is bcrypt, by default 14 that is equivalent to 1 second of computation using Core i5 CPU at 3.3Ghz.. Check taht your system use at least 1 second)

      Example of how to encrypt the password with bcrypt:

      use ZendCryptPasswordBcrypt;$bcrypt = new Bcrypt();$start = microtime(true);$hash =$bcrypt->create('password');$end = microtime(true);printf("Hash      : %s, %hash); //string of 60 bytesprintf("Exec. time: %.2fn", $end-$start);


      To check if password the user is valid, you verify them using the hash:

      $is_valid = bcrypt::verify($password, $hash)



      PHP generate pseudo-random values but they are not good for cryptography purposes.

      You can get secure random numbers in PHP if you have openssl PHP extension:


      Zend use most secure available function at the moment, never PHP primitives if $strong=true.

      ZendMathMath:randBytes($lenggth, $strong=false)

      ZendMathMath:rand($min, $max, $strong=false)