SlideShare uma empresa Scribd logo
1 de 149
Baixar para ler offline
Zend Framework 2
               Fare con



                                           ciò che facevo con ZF1




Zend Framework Day – Milano – 01/02/2013
@maraspin



2
http://www.mvassociati.it/




3
http://friuli.grusp.org/




4
brutto_esempio.php
<?php
echo '<html><body>';
$caldaia=$_GET['caldaia'];
$mysqli = new mysqli("localhost", "user", "pwd", "mva");
$query = "SELECT * FROM cespiti WHERE id =".$caldaia;
$result = $mysqli->query($query);
while ($row = $result->fetch_assoc()) {
?><div><?php echo $row["nome, temperatura"]); ?></div>
<?php } ?>
<?php
$result->free();
$mysqli->close();
echo '</html></body>';
?>
IL “FENOMENO”
AGGIORNAMENTO
9
LA SEGRETARIA
UFF. TECNICO
PRODUZIONE
ACCOUNT
Com’è strutturata l’azienda?




14
Che in un’applicazione…




15
MVC




16
Flusso MVC




17
Routing




18
Interazione con il modello




19
Il layer di presentazione




20
Risultato all’utente




21
Cosa ci manca?




22
Vorremmo una situazione così




23
Disaccoppiamento




24
I MODULI
Permettono questo




26
27
Come installare ZF2?




28
THE SKELETON APP
Cloning


     git clone git://github.com/zendframework/ZendSkeletonApplication.git




30
31
composer.json
{
    "name": "zendframework/skeleton-application",
    "description": "Skeleton Application for ZF2",
    "license": "BSD-3-Clause",
    "keywords": [
    "framework",
    "zf2"
    ],
    "homepage": "http://framework.zend.com/",
    "require": {
           "php": ">=5.3.3",
           "zendframework/zendframework": "2.*"
    }
}
composer.json
{
    "name": "zendframework/skeleton-application",
    "description": "Skeleton Application for ZF2",
    "license": "BSD-3-Clause",
    "keywords": [
    "framework",
    "zf2"
    ],
    "homepage": "http://framework.zend.com/",
    "require": {
           "php": ">=5.3.3",
           "zendframework/zendframework": "2.*"
    }
}
Installazione


 cd ZendSkeletonApplication
 php composer.phar install




34
Installazione


 cd ZendSkeletonApplication
 php composer.phar install
 > Installing zendframework/zendframework (dev-master)




35
Come impostare il progetto?




36
Struttura delle Cartelle




37
Struttura delle Cartelle

                          Configurazione Applicazione




38
Struttura delle Cartelle

                          Misc (cache, uploads, …)




39
Struttura delle Cartelle


                            Moduli




40
Struttura delle Cartelle


                            Moduli




41
Namespace   Module.php   Modulo




42
Struttura delle Cartelle


                          Modulo Application




43
Struttura delle Cartelle


                         Parte pubblica




44
DOCUMENT ROOT
DOCUMENT ROOT
Come funziona il bootstrap?




48
index.php
<?php
/**
 * This makes our life easier when dealing with paths. Everything is
 * relative to the application root now.
 */
chdir(dirname(__DIR__));


// Setup autoloading
require 'init_autoloader.php';


// Run the application!
ZendMvcApplication::init(require 'config/application.config.php')->run();
Configurazione


             config/
     application.config.php




50
config/application.config.php
<?php
return array(
     'modules' => array(
           'Application',
      ),


[...]


);


                            Elenco dei moduli attivati
Configurazione




52
Module.config.php
<?php [...]


return array(
      'router' => array('routes' => array([…]),
      ),
      'service_manager' => array(
           'factories' => array(
               'translator' => ZendI18nTranslatorTranslatorServiceFactory',
           ),),
      [...]
      'controllers' => array(
           'invokables' => array(
     'ApplicationControllerIndex‘=>'ApplicationControllerIndexController'
           ),),
      'view_manager' => array(
      [...]
      ),
);
Configurazione




54
Module.php
<?php [...]
class Module implements
    AutoloaderProviderInterface,
    ConfigProviderInterface,
    ServiceProviderInterface {
    public function getAutoloaderConfig() {[...]}


    public function getConfig($env = null) {
        return include __DIR__ . '/config/module.config.php';
    }


    public function getControllerPluginConfig() {[...]}


    public function getViewHelperConfig() {[...]}


    public function getServiceConfig() {[...]}
}
Configurazione




56
Configurazione




57
BOOTSTRAP
ROUTING
Dall’url al codice
return array( […]
    'routes'=> array(
              […]
                    'route' => '/sostituiscilampadina',
                    'defaults' => array(
                        'controller' => 'ApplicationControllerElettricista',
                        'action'    => ‘sostlampadina',
                    )
              […]
    ),
    'controllers' => array(
         'invokables' => array(
    'AppControllerElettricista' => 'AppControllerElettricistaController',
         ),
     ),
)
Dall’url al codice
return array( […]
    'routes'=> array(
              […]
                    'route' => '/sostituiscilampadina',
                    'defaults' => array(
                        'controller' => 'ApplicationControllerElettricista',
                        'action'    => ‘sostlampadina',
                    )
              […]
    ),
    'controllers' => array(
         'invokables' => array(
    'AppControllerElettricista' => 'AppControllerElettricistaController',
         ),
     ),
)
Dall’url al codice
return array( […]
    'routes'=> array(
              […]
                    'route' => '/sostituiscilampadina',
                    'defaults' => array(
                        'controller' => 'ApplicationControllerElettricista',
                        'action'    => ‘sostlampadina',
                    )
              […]
    ),
    'controllers' => array(
         'invokables' => array(
    'AppControllerElettricista' => 'AppControllerElettricistaController',
         ),
     ),
)
CONVENTION


VS

CONFIGURATION
Come sono fatti i controller?




64
Controller Semplice in ZF2
<?php


namespace ApplicationController;


use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;


class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        $timestamp = time();


        return new ViewModel(array(
              'timestamp' => $timestamp
        ));
    }
}
Action
<?php


namespace ApplicationController;


use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;


class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        $timestamp = time();


        return new ViewModel(array(
              'timestamp' => $timestamp
        ));
    }
}
Come interagisco con il model?




67
Controller ZF1
[…]


class IdraulicoController extends Zend_Controller_Action {


public function installaCaldaia () {


      $operatore = new Operatore();
      $esito = $operatore->installaCaldaia();


      $this->view->esito =$esito;
}
Scendiamo nel dettaglio
[…]


class IdraulicoController extends Zend_Controller_Action {


public function installaCaldaia () {


      $operatore = new Operatore();
      $esito = $operatore->installaCaldaia();


      $this->view->esito =$esito;


}
Com’è fatto questo oggetto?
[…]
Class Operatore {
        public function __constructor () {
                    $this->caldaia = new Caldaia();
        }


        public function getCaldaia() {
            return $this->caldaia;
        }


        public function installaCaldaia() {
            // Fai qualcosa con $this->caldaia
        }


}
Dipendenza. Siamo vincolati!
[…]
Class Operatore {
        public function __constructor () {
                    $this->caldaia = new Caldaia();
        }


        public function getCaldaia() {
            return $this->caldaia;
        }


        public function installaCaldaia() {
            // Fai qualcosa con $this->caldaia
        }


}
“IL PRINCIPIO DEL GARZONE”
Siamo vincolati
[…]
Class Operatore {
        public function __constructor (Caldaia $caldaia) {
                    $this->caldaia = $caldaia;
        }


        public function getCaldaia() {
            return $this->caldaia;
        }


        public function installaCaldaia() {
            // Fai qualcosa con $this->caldaia
        }


}
Siamo vincolati
[…]
Class Operatore {
        public function __constructor (Caldaia $caldaia) {
                    $this->caldaia = $caldaia;
        }


        public function getCaldaia() {
            return $this->caldaia;
        }


        public function installaCaldaia() {
            // Fai qualcosa con $this->caldaia
        }


}
Test operatore
[…]
class     OperatoreTest extends TestCase {

      function testInstallaCaldaia() {
         $caldaia = mockCaldaia();
          $operatore = new Operatore($caldaia);
          $esito = $operatore->installaCaldaia();
          $this->assertTrue($esito);
      }
}
Da…




76
A…




77
INVERSIONE DI CONTROLLO
Factory operatore
[…]
class OperatoreFactory {

      public static function create ($nome) {
         $caldaia = new Caldaia();
          $operatore = new Operatore($caldaia);
          return $operatore;
      }
}
Controller ZF1
[…]
class IdraulicoController extends Zend_Controller_Action {


public function installaCaldaia () {


      $I_operatore = OperatoreFactory::create();
      $esito = $I_operatore->installaCaldaia();


      $this->view->esito =$esito;
}
ZF2 - Il Service Manager
[…]
class IdraulicoController extends AbstractActionController {


public function installaCaldaia () {


      $operatore = $this->serviceLocator->get(‘operatore’);
      $esito = $I_operatore->installaCaldaia();


      return new ViewModel(‘operatore’ => $operatore,
                           ‘esito’ => $esito);
}
Riconsideriamo la configurazione
return array(
     ...
     'controllers' => array(
       ‘factories' => array(
           'AppControllerIdraulico' =>
                         'AppControllerIdraulicoControllerFactory',
       ),),
    ‘service_manager’ =>
       ‘factories' => array(
           ‘operatore' => ‘MVAServicesOperatoreFactory',
       ),
     ‘invokables' => array(
           ‘caldaia' => ‘MVAServicesCaldaia',
       ),
     ‘aliases' => array(
           ‘attrezzi.martelloPneumatico' => ‘attrezzi.martello',
       ),
)
Factories
return array(
     ...
     'controllers' => array(
       ‘factories' => array(
           'AppControllerIdraulico' =>
                         'AppControllerIdraulicoControllerFactory',
       ),),
    ‘service_manager’ =>
       ‘factories' => array(
           ‘operatore' => ‘MVAServicesOperatoreFactory',
       ),
     ‘invokables' => array(
           ‘caldaia' => ‘MVAServicesCaldaia',
       ),
     ‘aliases' => array(
           ‘attrezzi.martelloPneumatico' => ‘attrezzi.martello',
       ),
)
Invokables
return array(
     ...
     'controllers' => array(
       ‘factories' => array(
           'AppControllerIdraulico' =>
                         'AppControllerIdraulicoControllerFactory',
       ),),
    ‘service_manager’ =>
       ‘factories' => array(
           ‘operatore' => ‘MVAServicesOperatoreFactory',
       ),
     ‘invokables' => array(
           ‘caldaia' => ‘MVAServicesCaldaia',
       ),
     ‘aliases' => array(
           ‘attrezzi.martelloPneumatico' => ‘attrezzi.martello',
       ),
)
LAZY REGISTRY, ON STEROIDS
Service Locator
SE FATTO CON REGISTRY
Service Locator
Service Locator
Uso di Alias
return array(
     ...
     'controllers' => array(
       ‘factories' => array(
           'AppControllerIdraulico' =>
                         'AppControllerIdraulicoControllerFactory',
       ),
),
    ‘service_manager’ =>
       ‘invokables' => array(
       ‘attrezzi.martello' => 'AppServicesMartello',
       ‘attrezzi.martelloPneumatico‘ => 'AppServicesMartelloPneumatico',
       ),
)
Uso di Alias
return array(
     ...
     'controllers' => array(
       ‘factories' => array(
           'AppControllerIdraulico' =>
                         'AppControllerIdraulicoControllerFactory',
       ),
),
    ‘service_manager’ =>
     […]
    ‘invokables' => array(
           ‘attrezzi.martello' => 'AppServicesMartello',
       ‘attrezzi.supermartello' => 'AppServicesMartello',
       ),
     ‘aliases' => array(
           ‘attrezzi.martelloPneumatico' => ‘attrezzi.supermartello',
       ),
)
I diversi service managers
Diagramma service managers
Peering
Uso del Service Locator?
[…]
class Termostato implements ServiceLocatorAwareInterface {
    […]
    public function getTemperatura() {
        $sm = $this->getServiceLocator();
        $sensore = $sm->get(‘AziendaModelTermoSensore');
        return $sensore->getTemperatura();
    }


  public function setServiceLocator(ServiceLocatorInterface
$serviceLocator) {
    $this->serviceLocator = $serviceLocator; }


    public function getServiceLocator() {
        return $this->serviceLocator; }
}
Abuso del Service Locator
[…]
class Termostato implements ServiceLocatorAwareInterface {
    […]
    public function getTemperatura() {
        $sm = $this->getServiceLocator();
        $sensore = $sm->get(‘AziendaModelTermoSensore');
        return $sensore->getTemperatura();
    }


  public function setServiceLocator(ServiceLocatorInterface
$serviceLocator) {
    $this->serviceLocator = $serviceLocator; }


    public function getServiceLocator() {
        return $this->serviceLocator; }
}
ATTENZIONE!
Abuso del Service Locator
[…]
class Termostato implements ServiceLocatorAwareInterface {
    […]
    public function getTemperatura() {
        $sm = $this->getServiceLocator();
        $sensore = $sm->get(‘AziendaModelTermoSensore');
        return $sensore->getTemperatura();
    }


  public function setServiceLocator(ServiceLocatorInterface
$serviceLocator) {
    $this->serviceLocator = $serviceLocator; }


    public function getServiceLocator() {
        return $this->serviceLocator; }
}
Factory per il Controller
[…]


Class IdraulicoControllerFactory implements
FactoryInterface {


      public static function
          createService(ServiceLocatorInterface $services) {
          $sm = $services->getServiceLocator();
          $operatore = $sm->get(‘Operatore');
          return new IdraulicoController($operatore);
      }


      […]
}
?>
DEPENDENCY INJECTION




http://ocramius.github.com/blog/zend-framework-2-controllers-and-dependency-injection-with-zend-di/
E per le funzioni di supporto?




101
Scambio di messaggi
class IdraulicoController {

    public function installaCaldaiaAction() {


    $operatore = $this->serviceLocator->get(‘operatore’);
    $esito = $I_operatore->installaCaldaia();


    $I_logger = new Logger();
    $I_logger->log(‘Installazione Caldaia’);


    return new ViewModel(‘operatore’ => $operatore,
                         ‘esito’ => $esito);

    }
}
Mi trovo nel posto giusto?
class IdraulicoController {

    public function installaCaldaiaAction() {


    $operatore = $this->serviceLocator->get(‘operatore’);
    $esito = $I_operatore->installaCaldaia();


    $I_logger = new Logger();
    $I_logger->log(‘Installazione Caldaia’);


    return new ViewModel(‘operatore’ => $operatore,
                         ‘esito’ => $esito);

    }
}
Messaggio Diretto
CROSS CUTTING CONCERNS
Problema di estendibilità
$s_msg = ‘Installazione Caldaia’;

$I_logger = new Logger();
$I_logger->log($s_msg);

$I_mailer = new Mailer();
$I_mailer->mail($s_msg);

[…]
Event Manager
Class Segretaria {
       public function onFinitoIntervento() {
              /* Occupati della Fatturazione */
       }
}
Event Manager
Class IdraulicoFactory {

    createService(ServiceLocatorInterface $serviceLocator) {
    $idraulico = new Idraulico ();
    $idraulico ->setEventManager(
                  $serviceLocator->get('eventManager')
                 );
     $segretaria = $serviceLocator->get(‘segretaria');
     $idraulico->getEventManager()->attach(
                   ‘finitointervento',
                    array($segretaria, ‘onFinitoIntervento')
     );
     return $idraulico;
    }
}
Event Manager
//nella classe che scatena l’evento...
class Idraulico {

      public function installaCaldaia () {

       /* Codice Installazione Caldaia */

       $this->eventManager
             ->trigger(‘finitointervento‘,
                       $this,
                       array(‘azione’ => ‘Tutto OK!’)
                       );
      }
}
Event Manager
OBSERVER
Event Manager
Come interagisco con il DB?




113
ZENDDB
115
Come uso controller plugin?




116
Esempio con controller plugin
<?php


namespace ApplicationController;


use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;


class IndexController extends AbstractActionController
{
    public function redirectAction()
    {
        $this->redirect()->toUrl(‘http://www.zfday.it’);
    }
}
Come recupero parametri?




118
Factory per il Controller
[…]
use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;


class IndexController extends AbstractActionController
{
      public function scriviNomeAction()
      {
          $nome = $this->getEvent()
                 ->getRouteMatch()->getParam('slug');
          return (‘nome’ => $nome);
      }
}
E se ho funzionalità ripetute?




120
init()
<?php
class IdraulicoController extends Zend_Controller_Action {


    public function init () {
        $this->view->azienda = $this->getParam(‘azienda’);
    }
}
Ma non ho ancora l’EM!
[…]
use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;


class IndexController extends AbstractActionController
{
      public function __construct()
      {
          $this->azienda = $this->getEvent()
                 ->getRouteMatch()->getParam(‘azienda');
      }
}
Sulla Dependency Injection…
[…]
// Sul costruttore
public function __construct($dipendenza) {
      $this->dipendenza = $dipendenza;
}


// Con setters
Public function __construct() {
}


Public function setDipendenza() {
      $this->dipendenza = $dipendenza;
}
Agisco sul setter
[…]
use ZendMvcControllerAbstractActionController;
use ZendViewModelViewModel;


class IdraulicoController extends AbstractActionController
{
     public function setEventManager(EventManagerInterface $events) {
         parent::setEventManager($events);
         $controller = $this;
         $events->attach('dispatch', function ($e) use ($controller) {
              $this->name = $controller->params()->fromRoute(‘azienda',
                                                                                  ‘Sconosciuta');
         }


    }}




    Vedasi anche il post di M. W. O’Phinney: http://www.mwop.net/blog/2012-07-30-the-new-init.html
Come funzionano le viste?




125
Il layer di presentazione
View
//view index/index.phtml
<div class="row">


     <!-- Including header partial -->
     <?php echo $this->partial('partials/header.phtml', array()); ?>


     <!-- Stampiamo la data -->
     <h1>Actual time is: <?php echo $this->timestamp;?></h1>


</div>
View con helper
//usando il view helper printData
//view index/index.phtml
<div class="row">
<!-- Including header partial -->
     <?php echo $this->partial('partials/header.phtml', array()); ?>


    <!-- Stampiamo la data -->
     <h1>Actual time is:
         <?php echo $this->printData($this->timestamp);?>
     </h1>
</div>
Helper
//Creando un viewHelper per formattare la data
// Va registrato tra gli invokables del SM dei ViewHelpers
<?php
namespace ApplicationViewHelper;


class PrintData extends ZendViewHelperAbstractHelper   {


    public function __invoke($timestamp) {


        $date = new DateTime();
        $date->setTimestamp($timestamp);
        $result =   $date->format('d-m-Y H:i');
        return $result;


    }
}
Come funzionano le form?




130
Creando una form
//Creiamo il file ContactForm dentro nostro modulo Application/src/Form
<?php
namespace ApplicationForm;


use ZendFormElement;
use ZendFormForm;


class ContactForm extends Form
{


    public function __construct()
    {
        parent::__construct();
        // …
    }
    //...
}
Form: aggiungiamo i campi
public function init() {
        $this->setName('contact');
        $this->add(array(
            'name' => ‘emailMittente',
            'type' => 'ZendFormElementText',
            'options' => array(
                 'label' => 'From:',
            ),
        )
        $this->add(array(
                 'name' => 'Send',
                 'type' => 'ZendFormElementSubmit',
                 'attributes' => array(
                        'value' => 'Send',
                 ),); //...
    }
}
La Form




      Form
Gli InputFilter
Validation: inputFilter
//creiamo l'imput filter contactFilter.php dentro Application/src/Form
<?php
namespace ApplicationForm;


use ZendInputFilterInputFilter;
use ZendValidatorHostname as HostnameValidator;


class ContactFilter extends InputFilter
{
    public function __construct()
    {
         //aggiungiamo i filtri
    }


}
InputFilter: filter & validation
//Esempio filtering(trim) + email validation with custom message
        $this->add(array(
              'name'        => ‘emailMittente',
              'required' => true,
              'filters'     => array(
                   array('name' => 'StringTrim'),
              ),
              'validators' => array(
                   array(
                       'name' => 'EmailAddress',
                       'options' => array(
                            'messages' => array(
                                ZendValidatorEmailAddress::INVALID =>
                                'L'indirizzo email inserito non è valido.'),
                       )
                   )
              )
        ));
Controller: Usando la form
namespace ApplicationController;
use ZendMvcControllerAbstractActionController;
use ApplicationFormContact;
use ApplicationFormContactFilter;
class IndexController extends AbstractActionController
{
    public function contactAction()
    {
        $form     = new Contact();
        $filter   = new ContactFilter();
        $form->setInputFilter($filter);


        return new ViewModel(array(
             'form' => $form
        );
    }
}
View: Usando la form
<?php
$form = $this->form;
$form->setAttribute('action', $this->url('contact'));
$form->prepare();
echo $this->form()->openTag($form); ?>
<dl class="contact_form">
    <dt><?php echo $this->formLabel($form->get('from')); ?></dt>
    <dd><?php
        echo $this->formInput($form->get('from'));
        echo $this->formElementErrors($form->get('from'));
    ?></dd>
    <!-- ... -->
</dl>
<?php echo $this->form()->closeTag($form) ?>;
Una form più filtri
Come posso proseguire?




140
Per Approfondire




141
Per Approfondire




142
Sporcati le mani:
      https://packages.zendframework.com/docs/latest/manual/en/user-guide/overview.html




143
Segui i migliori eventi




                   http://www.phpday.it




144
In sintesi
      1.   Maggior enfasi sul riuso. Tenere a mente
           che ci sono i Moduli
      2.   Su ZF2 si segue maggiormente un
           approccio orientato alla configurazione
           piuttosto che convenzione
      3.   Lo strumento cerca di favorire il
           disaccoppiamento (EventManager) e
           l’inversione di controllo
           (ServiceManager, DI)

145
Grazie per l’attenzione




Stefano Maraspin
@maraspin
s.maraspin@mvassociati.it
DOMANDE?
Photo Credits
      •   http://www.flickr.com/photos/cclark395/7671665642/
      •   http://www.flickr.com/photos/thompsonrivers/8072087088/
      •   http://www.flickr.com/photos/ter-burg/5807937726/
      •   http://www.flickr.com/photos/cimmyt/7798631622/
      •   http://www.flickr.com/photos/reckless_sniper/6568298617/
      •   http://www.flickr.com/photos/fil/144232588/
      •   http://www.flickr.com/photos/ponchopenguin/3262049873/
      •   http://www.flickr.com/photos/hugosimmelink/1791812548/
      •   http://www.flickr.com/photos/calsidyrose/4925267732/
      •   http://www.flickr.com/photos/29233640@N07/8412347937/
      •   http://www.flickr.com/photos/stungeye/2774997317/
      •   http://www.flickr.com/photos/urbanwoodswalker/4375401057/
      •   http://www.flickr.com/photos/adelaide_archivist/3262863212/
      •   http://www.flickr.com/photos/syslfrog/172945973/
      •   http://www.flickr.com/photos/tognum/6279595321/
      •   http://www.flickr.com/photos/dominichargreaves/2825624738/
      •   http://www.flickr.com/photos/lstcaress/502606063/
      •   http://www.flickr.com/photos/a-g/2128462119/
      •   http://www.flickr.com/photos/see-through-the-eye-of-g/4087838437/



148
Stefano Maraspin
@maraspin
s.maraspin@mvassociati.it

Mais conteúdo relacionado

Semelhante a Fare con Zend Framework 2 ciò che facevo con ZF1

Zend Framework Workshop Parte2
Zend Framework Workshop Parte2Zend Framework Workshop Parte2
Zend Framework Workshop Parte2
massimiliano.wosz
 
Dominare il codice legacy
Dominare il codice legacyDominare il codice legacy
Dominare il codice legacy
Tommaso Torti
 

Semelhante a Fare con Zend Framework 2 ciò che facevo con ZF1 (20)

Come portare il profiler di symfony2 in drupal8
Come portare il profiler di symfony2 in drupal8Come portare il profiler di symfony2 in drupal8
Come portare il profiler di symfony2 in drupal8
 
Come Drupal costruisce le tue pagine
Come Drupal costruisce le tue pagineCome Drupal costruisce le tue pagine
Come Drupal costruisce le tue pagine
 
SaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
SaaS con Symfony2 un caso *molto* concreto di applicazione multitenantSaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
SaaS con Symfony2 un caso *molto* concreto di applicazione multitenant
 
SaaS con Symfony2
SaaS con Symfony2SaaS con Symfony2
SaaS con Symfony2
 
MVC2: non solo tecnologia
MVC2: non solo tecnologiaMVC2: non solo tecnologia
MVC2: non solo tecnologia
 
Java lezione 10
Java lezione 10Java lezione 10
Java lezione 10
 
Zend Framework Workshop Parte2
Zend Framework Workshop Parte2Zend Framework Workshop Parte2
Zend Framework Workshop Parte2
 
Zendframework Parte2
Zendframework    Parte2Zendframework    Parte2
Zendframework Parte2
 
Yagwto
YagwtoYagwto
Yagwto
 
Dominare il codice legacy
Dominare il codice legacyDominare il codice legacy
Dominare il codice legacy
 
Non Conventional Android Programming (Italiano)
Non Conventional Android Programming (Italiano)Non Conventional Android Programming (Italiano)
Non Conventional Android Programming (Italiano)
 
Applicazioni native in java
Applicazioni native in javaApplicazioni native in java
Applicazioni native in java
 
eZ publish - Extension
eZ publish - ExtensioneZ publish - Extension
eZ publish - Extension
 
Simple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computingSimple Cloud API: accesso semplificato al cloud computing
Simple Cloud API: accesso semplificato al cloud computing
 
Sviluppo web dall'antichità all'avanguardia e ritorno
Sviluppo web  dall'antichità all'avanguardia e ritornoSviluppo web  dall'antichità all'avanguardia e ritorno
Sviluppo web dall'antichità all'avanguardia e ritorno
 
ReactJS for beginners
ReactJS for beginnersReactJS for beginners
ReactJS for beginners
 
Drupal diventa un CMF e WordPress che fa? Slide WordCamp Milano 2019
Drupal diventa un CMF e WordPress che fa? Slide WordCamp Milano 2019Drupal diventa un CMF e WordPress che fa? Slide WordCamp Milano 2019
Drupal diventa un CMF e WordPress che fa? Slide WordCamp Milano 2019
 
Il testing con zend framework
Il testing con zend frameworkIl testing con zend framework
Il testing con zend framework
 
Il testing con zend framework
Il testing con zend frameworkIl testing con zend framework
Il testing con zend framework
 
(My) Best Practices in Symfony
(My) Best Practices in Symfony(My) Best Practices in Symfony
(My) Best Practices in Symfony
 

Mais de Steve Maraspin

Mais de Steve Maraspin (20)

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
 
Meet a parallel, asynchronous PHP world
Meet a parallel, asynchronous PHP worldMeet a parallel, asynchronous PHP world
Meet a parallel, asynchronous PHP world
 
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
 
Error Reporting in ZF2: form messages, custom error pages, logging
Error Reporting in ZF2: form messages, custom error pages, loggingError Reporting in ZF2: form messages, custom error pages, logging
Error Reporting in ZF2: form messages, custom error pages, logging
 
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
 
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
 
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
 

Fare con Zend Framework 2 ciò che facevo con ZF1

  • 1. Zend Framework 2 Fare con ciò che facevo con ZF1 Zend Framework Day – Milano – 01/02/2013
  • 5.
  • 6. brutto_esempio.php <?php echo '<html><body>'; $caldaia=$_GET['caldaia']; $mysqli = new mysqli("localhost", "user", "pwd", "mva"); $query = "SELECT * FROM cespiti WHERE id =".$caldaia; $result = $mysqli->query($query); while ($row = $result->fetch_assoc()) { ?><div><?php echo $row["nome, temperatura"]); ?></div> <?php } ?> <?php $result->free(); $mysqli->close(); echo '</html></body>'; ?>
  • 9. 9
  • 19. Interazione con il modello 19
  • 20. Il layer di presentazione 20
  • 27. 27
  • 30. Cloning git clone git://github.com/zendframework/ZendSkeletonApplication.git 30
  • 31. 31
  • 32. composer.json { "name": "zendframework/skeleton-application", "description": "Skeleton Application for ZF2", "license": "BSD-3-Clause", "keywords": [ "framework", "zf2" ], "homepage": "http://framework.zend.com/", "require": { "php": ">=5.3.3", "zendframework/zendframework": "2.*" } }
  • 33. composer.json { "name": "zendframework/skeleton-application", "description": "Skeleton Application for ZF2", "license": "BSD-3-Clause", "keywords": [ "framework", "zf2" ], "homepage": "http://framework.zend.com/", "require": { "php": ">=5.3.3", "zendframework/zendframework": "2.*" } }
  • 34. Installazione cd ZendSkeletonApplication php composer.phar install 34
  • 35. Installazione cd ZendSkeletonApplication php composer.phar install > Installing zendframework/zendframework (dev-master) 35
  • 36. Come impostare il progetto? 36
  • 38. Struttura delle Cartelle Configurazione Applicazione 38
  • 39. Struttura delle Cartelle Misc (cache, uploads, …) 39
  • 42. Namespace Module.php Modulo 42
  • 43. Struttura delle Cartelle Modulo Application 43
  • 44. Struttura delle Cartelle Parte pubblica 44
  • 47.
  • 48. Come funziona il bootstrap? 48
  • 49. index.php <?php /** * This makes our life easier when dealing with paths. Everything is * relative to the application root now. */ chdir(dirname(__DIR__)); // Setup autoloading require 'init_autoloader.php'; // Run the application! ZendMvcApplication::init(require 'config/application.config.php')->run();
  • 50. Configurazione config/ application.config.php 50
  • 51. config/application.config.php <?php return array( 'modules' => array( 'Application', ), [...] ); Elenco dei moduli attivati
  • 53. Module.config.php <?php [...] return array( 'router' => array('routes' => array([…]), ), 'service_manager' => array( 'factories' => array( 'translator' => ZendI18nTranslatorTranslatorServiceFactory', ),), [...] 'controllers' => array( 'invokables' => array( 'ApplicationControllerIndex‘=>'ApplicationControllerIndexController' ),), 'view_manager' => array( [...] ), );
  • 55. Module.php <?php [...] class Module implements AutoloaderProviderInterface, ConfigProviderInterface, ServiceProviderInterface { public function getAutoloaderConfig() {[...]} public function getConfig($env = null) { return include __DIR__ . '/config/module.config.php'; } public function getControllerPluginConfig() {[...]} public function getViewHelperConfig() {[...]} public function getServiceConfig() {[...]} }
  • 60. Dall’url al codice return array( […] 'routes'=> array( […] 'route' => '/sostituiscilampadina', 'defaults' => array( 'controller' => 'ApplicationControllerElettricista', 'action' => ‘sostlampadina', ) […] ), 'controllers' => array( 'invokables' => array( 'AppControllerElettricista' => 'AppControllerElettricistaController', ), ), )
  • 61. Dall’url al codice return array( […] 'routes'=> array( […] 'route' => '/sostituiscilampadina', 'defaults' => array( 'controller' => 'ApplicationControllerElettricista', 'action' => ‘sostlampadina', ) […] ), 'controllers' => array( 'invokables' => array( 'AppControllerElettricista' => 'AppControllerElettricistaController', ), ), )
  • 62. Dall’url al codice return array( […] 'routes'=> array( […] 'route' => '/sostituiscilampadina', 'defaults' => array( 'controller' => 'ApplicationControllerElettricista', 'action' => ‘sostlampadina', ) […] ), 'controllers' => array( 'invokables' => array( 'AppControllerElettricista' => 'AppControllerElettricistaController', ), ), )
  • 64. Come sono fatti i controller? 64
  • 65. Controller Semplice in ZF2 <?php namespace ApplicationController; use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; class IndexController extends AbstractActionController { public function indexAction() { $timestamp = time(); return new ViewModel(array( 'timestamp' => $timestamp )); } }
  • 66. Action <?php namespace ApplicationController; use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; class IndexController extends AbstractActionController { public function indexAction() { $timestamp = time(); return new ViewModel(array( 'timestamp' => $timestamp )); } }
  • 67. Come interagisco con il model? 67
  • 68. Controller ZF1 […] class IdraulicoController extends Zend_Controller_Action { public function installaCaldaia () { $operatore = new Operatore(); $esito = $operatore->installaCaldaia(); $this->view->esito =$esito; }
  • 69. Scendiamo nel dettaglio […] class IdraulicoController extends Zend_Controller_Action { public function installaCaldaia () { $operatore = new Operatore(); $esito = $operatore->installaCaldaia(); $this->view->esito =$esito; }
  • 70. Com’è fatto questo oggetto? […] Class Operatore { public function __constructor () { $this->caldaia = new Caldaia(); } public function getCaldaia() { return $this->caldaia; } public function installaCaldaia() { // Fai qualcosa con $this->caldaia } }
  • 71. Dipendenza. Siamo vincolati! […] Class Operatore { public function __constructor () { $this->caldaia = new Caldaia(); } public function getCaldaia() { return $this->caldaia; } public function installaCaldaia() { // Fai qualcosa con $this->caldaia } }
  • 72. “IL PRINCIPIO DEL GARZONE”
  • 73. Siamo vincolati […] Class Operatore { public function __constructor (Caldaia $caldaia) { $this->caldaia = $caldaia; } public function getCaldaia() { return $this->caldaia; } public function installaCaldaia() { // Fai qualcosa con $this->caldaia } }
  • 74. Siamo vincolati […] Class Operatore { public function __constructor (Caldaia $caldaia) { $this->caldaia = $caldaia; } public function getCaldaia() { return $this->caldaia; } public function installaCaldaia() { // Fai qualcosa con $this->caldaia } }
  • 75. Test operatore […] class OperatoreTest extends TestCase { function testInstallaCaldaia() { $caldaia = mockCaldaia(); $operatore = new Operatore($caldaia); $esito = $operatore->installaCaldaia(); $this->assertTrue($esito); } }
  • 79. Factory operatore […] class OperatoreFactory { public static function create ($nome) { $caldaia = new Caldaia(); $operatore = new Operatore($caldaia); return $operatore; } }
  • 80. Controller ZF1 […] class IdraulicoController extends Zend_Controller_Action { public function installaCaldaia () { $I_operatore = OperatoreFactory::create(); $esito = $I_operatore->installaCaldaia(); $this->view->esito =$esito; }
  • 81. ZF2 - Il Service Manager […] class IdraulicoController extends AbstractActionController { public function installaCaldaia () { $operatore = $this->serviceLocator->get(‘operatore’); $esito = $I_operatore->installaCaldaia(); return new ViewModel(‘operatore’ => $operatore, ‘esito’ => $esito); }
  • 82. Riconsideriamo la configurazione return array( ... 'controllers' => array( ‘factories' => array( 'AppControllerIdraulico' => 'AppControllerIdraulicoControllerFactory', ),), ‘service_manager’ => ‘factories' => array( ‘operatore' => ‘MVAServicesOperatoreFactory', ), ‘invokables' => array( ‘caldaia' => ‘MVAServicesCaldaia', ), ‘aliases' => array( ‘attrezzi.martelloPneumatico' => ‘attrezzi.martello', ), )
  • 83. Factories return array( ... 'controllers' => array( ‘factories' => array( 'AppControllerIdraulico' => 'AppControllerIdraulicoControllerFactory', ),), ‘service_manager’ => ‘factories' => array( ‘operatore' => ‘MVAServicesOperatoreFactory', ), ‘invokables' => array( ‘caldaia' => ‘MVAServicesCaldaia', ), ‘aliases' => array( ‘attrezzi.martelloPneumatico' => ‘attrezzi.martello', ), )
  • 84. Invokables return array( ... 'controllers' => array( ‘factories' => array( 'AppControllerIdraulico' => 'AppControllerIdraulicoControllerFactory', ),), ‘service_manager’ => ‘factories' => array( ‘operatore' => ‘MVAServicesOperatoreFactory', ), ‘invokables' => array( ‘caldaia' => ‘MVAServicesCaldaia', ), ‘aliases' => array( ‘attrezzi.martelloPneumatico' => ‘attrezzi.martello', ), )
  • 85. LAZY REGISTRY, ON STEROIDS
  • 87. SE FATTO CON REGISTRY
  • 90. Uso di Alias return array( ... 'controllers' => array( ‘factories' => array( 'AppControllerIdraulico' => 'AppControllerIdraulicoControllerFactory', ), ), ‘service_manager’ => ‘invokables' => array( ‘attrezzi.martello' => 'AppServicesMartello', ‘attrezzi.martelloPneumatico‘ => 'AppServicesMartelloPneumatico', ), )
  • 91. Uso di Alias return array( ... 'controllers' => array( ‘factories' => array( 'AppControllerIdraulico' => 'AppControllerIdraulicoControllerFactory', ), ), ‘service_manager’ => […] ‘invokables' => array( ‘attrezzi.martello' => 'AppServicesMartello', ‘attrezzi.supermartello' => 'AppServicesMartello', ), ‘aliases' => array( ‘attrezzi.martelloPneumatico' => ‘attrezzi.supermartello', ), )
  • 92. I diversi service managers
  • 95. Uso del Service Locator? […] class Termostato implements ServiceLocatorAwareInterface { […] public function getTemperatura() { $sm = $this->getServiceLocator(); $sensore = $sm->get(‘AziendaModelTermoSensore'); return $sensore->getTemperatura(); } public function setServiceLocator(ServiceLocatorInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; } public function getServiceLocator() { return $this->serviceLocator; } }
  • 96. Abuso del Service Locator […] class Termostato implements ServiceLocatorAwareInterface { […] public function getTemperatura() { $sm = $this->getServiceLocator(); $sensore = $sm->get(‘AziendaModelTermoSensore'); return $sensore->getTemperatura(); } public function setServiceLocator(ServiceLocatorInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; } public function getServiceLocator() { return $this->serviceLocator; } }
  • 98. Abuso del Service Locator […] class Termostato implements ServiceLocatorAwareInterface { […] public function getTemperatura() { $sm = $this->getServiceLocator(); $sensore = $sm->get(‘AziendaModelTermoSensore'); return $sensore->getTemperatura(); } public function setServiceLocator(ServiceLocatorInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; } public function getServiceLocator() { return $this->serviceLocator; } }
  • 99. Factory per il Controller […] Class IdraulicoControllerFactory implements FactoryInterface { public static function createService(ServiceLocatorInterface $services) { $sm = $services->getServiceLocator(); $operatore = $sm->get(‘Operatore'); return new IdraulicoController($operatore); } […] } ?>
  • 101. E per le funzioni di supporto? 101
  • 102. Scambio di messaggi class IdraulicoController { public function installaCaldaiaAction() { $operatore = $this->serviceLocator->get(‘operatore’); $esito = $I_operatore->installaCaldaia(); $I_logger = new Logger(); $I_logger->log(‘Installazione Caldaia’); return new ViewModel(‘operatore’ => $operatore, ‘esito’ => $esito); } }
  • 103. Mi trovo nel posto giusto? class IdraulicoController { public function installaCaldaiaAction() { $operatore = $this->serviceLocator->get(‘operatore’); $esito = $I_operatore->installaCaldaia(); $I_logger = new Logger(); $I_logger->log(‘Installazione Caldaia’); return new ViewModel(‘operatore’ => $operatore, ‘esito’ => $esito); } }
  • 106. Problema di estendibilità $s_msg = ‘Installazione Caldaia’; $I_logger = new Logger(); $I_logger->log($s_msg); $I_mailer = new Mailer(); $I_mailer->mail($s_msg); […]
  • 107. Event Manager Class Segretaria { public function onFinitoIntervento() { /* Occupati della Fatturazione */ } }
  • 108. Event Manager Class IdraulicoFactory { createService(ServiceLocatorInterface $serviceLocator) { $idraulico = new Idraulico (); $idraulico ->setEventManager( $serviceLocator->get('eventManager') ); $segretaria = $serviceLocator->get(‘segretaria'); $idraulico->getEventManager()->attach( ‘finitointervento', array($segretaria, ‘onFinitoIntervento') ); return $idraulico; } }
  • 109. Event Manager //nella classe che scatena l’evento... class Idraulico { public function installaCaldaia () { /* Codice Installazione Caldaia */ $this->eventManager ->trigger(‘finitointervento‘, $this, array(‘azione’ => ‘Tutto OK!’) ); } }
  • 113. Come interagisco con il DB? 113
  • 114. ZENDDB
  • 115. 115
  • 116. Come uso controller plugin? 116
  • 117. Esempio con controller plugin <?php namespace ApplicationController; use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; class IndexController extends AbstractActionController { public function redirectAction() { $this->redirect()->toUrl(‘http://www.zfday.it’); } }
  • 119. Factory per il Controller […] use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; class IndexController extends AbstractActionController { public function scriviNomeAction() { $nome = $this->getEvent() ->getRouteMatch()->getParam('slug'); return (‘nome’ => $nome); } }
  • 120. E se ho funzionalità ripetute? 120
  • 121. init() <?php class IdraulicoController extends Zend_Controller_Action { public function init () { $this->view->azienda = $this->getParam(‘azienda’); } }
  • 122. Ma non ho ancora l’EM! […] use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; class IndexController extends AbstractActionController { public function __construct() { $this->azienda = $this->getEvent() ->getRouteMatch()->getParam(‘azienda'); } }
  • 123. Sulla Dependency Injection… […] // Sul costruttore public function __construct($dipendenza) { $this->dipendenza = $dipendenza; } // Con setters Public function __construct() { } Public function setDipendenza() { $this->dipendenza = $dipendenza; }
  • 124. Agisco sul setter […] use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; class IdraulicoController extends AbstractActionController { public function setEventManager(EventManagerInterface $events) { parent::setEventManager($events); $controller = $this; $events->attach('dispatch', function ($e) use ($controller) { $this->name = $controller->params()->fromRoute(‘azienda', ‘Sconosciuta'); } }} Vedasi anche il post di M. W. O’Phinney: http://www.mwop.net/blog/2012-07-30-the-new-init.html
  • 125. Come funzionano le viste? 125
  • 126. Il layer di presentazione
  • 127. View //view index/index.phtml <div class="row"> <!-- Including header partial --> <?php echo $this->partial('partials/header.phtml', array()); ?> <!-- Stampiamo la data --> <h1>Actual time is: <?php echo $this->timestamp;?></h1> </div>
  • 128. View con helper //usando il view helper printData //view index/index.phtml <div class="row"> <!-- Including header partial --> <?php echo $this->partial('partials/header.phtml', array()); ?> <!-- Stampiamo la data --> <h1>Actual time is: <?php echo $this->printData($this->timestamp);?> </h1> </div>
  • 129. Helper //Creando un viewHelper per formattare la data // Va registrato tra gli invokables del SM dei ViewHelpers <?php namespace ApplicationViewHelper; class PrintData extends ZendViewHelperAbstractHelper { public function __invoke($timestamp) { $date = new DateTime(); $date->setTimestamp($timestamp); $result = $date->format('d-m-Y H:i'); return $result; } }
  • 130. Come funzionano le form? 130
  • 131. Creando una form //Creiamo il file ContactForm dentro nostro modulo Application/src/Form <?php namespace ApplicationForm; use ZendFormElement; use ZendFormForm; class ContactForm extends Form { public function __construct() { parent::__construct(); // … } //... }
  • 132. Form: aggiungiamo i campi public function init() { $this->setName('contact'); $this->add(array( 'name' => ‘emailMittente', 'type' => 'ZendFormElementText', 'options' => array( 'label' => 'From:', ), ) $this->add(array( 'name' => 'Send', 'type' => 'ZendFormElementSubmit', 'attributes' => array( 'value' => 'Send', ),); //... } }
  • 133. La Form Form
  • 135. Validation: inputFilter //creiamo l'imput filter contactFilter.php dentro Application/src/Form <?php namespace ApplicationForm; use ZendInputFilterInputFilter; use ZendValidatorHostname as HostnameValidator; class ContactFilter extends InputFilter { public function __construct() { //aggiungiamo i filtri } }
  • 136. InputFilter: filter & validation //Esempio filtering(trim) + email validation with custom message $this->add(array( 'name' => ‘emailMittente', 'required' => true, 'filters' => array( array('name' => 'StringTrim'), ), 'validators' => array( array( 'name' => 'EmailAddress', 'options' => array( 'messages' => array( ZendValidatorEmailAddress::INVALID => 'L'indirizzo email inserito non è valido.'), ) ) ) ));
  • 137. Controller: Usando la form namespace ApplicationController; use ZendMvcControllerAbstractActionController; use ApplicationFormContact; use ApplicationFormContactFilter; class IndexController extends AbstractActionController { public function contactAction() { $form = new Contact(); $filter = new ContactFilter(); $form->setInputFilter($filter); return new ViewModel(array( 'form' => $form ); } }
  • 138. View: Usando la form <?php $form = $this->form; $form->setAttribute('action', $this->url('contact')); $form->prepare(); echo $this->form()->openTag($form); ?> <dl class="contact_form"> <dt><?php echo $this->formLabel($form->get('from')); ?></dt> <dd><?php echo $this->formInput($form->get('from')); echo $this->formElementErrors($form->get('from')); ?></dd> <!-- ... --> </dl> <?php echo $this->form()->closeTag($form) ?>;
  • 139. Una form più filtri
  • 143. Sporcati le mani: https://packages.zendframework.com/docs/latest/manual/en/user-guide/overview.html 143
  • 144. Segui i migliori eventi http://www.phpday.it 144
  • 145. In sintesi 1. Maggior enfasi sul riuso. Tenere a mente che ci sono i Moduli 2. Su ZF2 si segue maggiormente un approccio orientato alla configurazione piuttosto che convenzione 3. Lo strumento cerca di favorire il disaccoppiamento (EventManager) e l’inversione di controllo (ServiceManager, DI) 145
  • 146. Grazie per l’attenzione Stefano Maraspin @maraspin s.maraspin@mvassociati.it
  • 148. Photo Credits • http://www.flickr.com/photos/cclark395/7671665642/ • http://www.flickr.com/photos/thompsonrivers/8072087088/ • http://www.flickr.com/photos/ter-burg/5807937726/ • http://www.flickr.com/photos/cimmyt/7798631622/ • http://www.flickr.com/photos/reckless_sniper/6568298617/ • http://www.flickr.com/photos/fil/144232588/ • http://www.flickr.com/photos/ponchopenguin/3262049873/ • http://www.flickr.com/photos/hugosimmelink/1791812548/ • http://www.flickr.com/photos/calsidyrose/4925267732/ • http://www.flickr.com/photos/29233640@N07/8412347937/ • http://www.flickr.com/photos/stungeye/2774997317/ • http://www.flickr.com/photos/urbanwoodswalker/4375401057/ • http://www.flickr.com/photos/adelaide_archivist/3262863212/ • http://www.flickr.com/photos/syslfrog/172945973/ • http://www.flickr.com/photos/tognum/6279595321/ • http://www.flickr.com/photos/dominichargreaves/2825624738/ • http://www.flickr.com/photos/lstcaress/502606063/ • http://www.flickr.com/photos/a-g/2128462119/ • http://www.flickr.com/photos/see-through-the-eye-of-g/4087838437/ 148