Getting Started with Zend Framework 2

Agenda

  • Framework Overview
  • Benefits of using Framework
  • Getting Started
    • Installation (Skeleton App)
    • File/Code Structure
    • Modules
    • Controllers, Views, Routing
    • Database and Models
    • Filters
    • Service Manager
      • Factory based instantiation
    • Session Container
  • Dependency Injection

What is a Framework?

“A Framework is a universal, reusable software platform to develop software applications, products and solutions. In other words, we can say it is some kind of library, a piece of software, which provide web developers with code base and consistent standardized ways of creating web applications”.

Benefits of using Framework

  1. Code and File Organization
  2. Enforcing of Good Coding Standards
  3. Utilities and Libraries
  4. Less Code & Faster Development
  5. Community Support
  6. Security
  7. Modular, use what you need, ignore what you don’t

  8. Strong use of OOP and Design Patterns for Consistency

Getting Started

Modules

A module is a software component or part of a program that contains one or more routines. One or more independently developed modules make up a program. An enterprise-level software application may contain several different modules, and each module serves unique and separate business operations.

Creating a Module

// SAMPLE Module.php file
namespace Album;

use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
    }

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

}

1. Create directory for the module

2. create sub directories(src, config, view)

3. create Module.php under src/ directory

4. create config/module.config.php

5. Register module to application.config.php

6. Update composer.json, add module to autoload

7. run composer dump-autoload

Creating a Controller

namespace Album\Controller;
class AlbumController extends AbstractActionController
{
    public function __construct()
    {
    }
}

1. Create controller under src/Controller/AlbumController.php directory

2. Controller class should extend AbstractActionController

 

 

 

3. Create a Factory for the controller under src/ServiceFactory/Controller/ (AlbumControllerFactory.php)

<?php

namespace Album\ServiceFactory\Controller;

use Psr\Container\ContainerInterface;

class AlbumControllerFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $container = $container->getServiceLocator(); // remove if zf3
        // $AlbumTable = $container->get(AlbumTable::class); // sample call for getting services from service manager
      
        return new AlbumController();
    }
}

Creating a Controller

'controllers' => array(
    'factories' => array(
        AlbumController::class => AlbumControllerFactory::class
    )
),

4. Register controller in config/module.config.php

 

Routing

'router' => [
    'routes' => [
        'album' => [
            'type'    => Segment::class,
            'options' => [
                'route' => '/album[/:action[/:id]]',
                'constraints' => [
                    'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                    'id'     => '[0-9]+',
                ],
                'defaults' => [
                    'controller' => Controller\AlbumController::class,
                    'action'     => 'index',
                ],
            ],
        ],
        'home' => [
            'type' => Literal::class,
            'options' => [
                'route'    => '/',
                'defaults' => [
                    'controller' => IndexController::class,
                    'action'     => 'index',
                ]
            ]
        ]
    ],
],

Route configuration is placed inside module.config.php file

Sample Segment and Literal Route Configuration

Models and Tables

namespace Album\Model;

class Album
{
    public $id;
    public $artist;
    public $title;

    public function exchangeArray(array $data)
    {
        $this->id     = !empty($data['id']) ? $data['id'] : null;
        $this->artist = !empty($data['artist']) ? $data['artist'] : null;
        $this->title  = !empty($data['title']) ? $data['title'] : null;
    }
}

Models and Table classes are placed under src/Model directory.

 

Sample Model:

Models and Tables

namespace Album\Model;

use Zend\Db\TableGateway\TableGateway;

class AlbumTable
{
    private $tableGateway;

    public function __construct(TableGateway $tableGateway)
    {
        $this->tableGateway = $tableGateway;
    }
}

Sample Table class

Models and Tables

namespace Album\ServiceFactory\Model;

use Album\Model\Album;
use Album\Model\AlbumTable;
use Psr\Container\ContainerInterface;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;

class AlbumTableFactory
{
    public function __invoke(ContainerInterface $container)
    {
        // Creation for table gateway instance
        $dbAdapter = $container->get('test');
        $resultSetPrototype = new ResultSet();
        $resultSetPrototype->setArrayObjectPrototype(new Album());

        // create TableGateway instance
        $tableGateway = new TableGateway(
            'album',
            $dbAdapter,
            null,
            $resultSetPrototype
        );

        // Create AlbumTable instance
        return new AlbumTable($tableGateway);
    }
}

Create a Factory for AlbumTable class under src/ServiceFactory/Model directory

Models and Tables

'service_manager' => array(
    'factories' => array(
        AlbumTable::class => AlbumTableFactory::class,
        'Album\Storage\AlbumSessionContainer' => AlbumSessionContainerFactory::class,
    ),
    'invokables' => array(
        AlbumFilter::class => AlbumFilter::class,
    )
),

Register AlbumTable in module.config.php service manager factories

Models and Tables

return array(
    'service_manager' => array(
        'abstract_factories' => array(
            'Zend\Db\Adapter\AdapterAbstractServiceFactory',
        ),
    ),
    'db' => array(
        'adapters' => array(
            'test' => array(
                'driver' => 'Pdo_Mysql',
                'driver_options' => array(
                    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
                )
            ),
        ),
    ),
);

Add Database Adapters by updating global.php config file

Add Database Connection Configuration in local.php config file

return array(
    'db' => array(
        'adapters' => array(
            'test' => array(
                'dsn' => 'mysql:dbname=test;host=mysql-57',
                'username' => 'root',
                'password' => 'root'
            ),
        ),
    ),
);

Models and Tables

public function selectWithJoin()
{
    $select = $this->tableGateway->getSql()->select();
    $select->columns(array("artist"));
    $select->join(
        array("a" => "artists"),
        "a.artist_id = album.artist_id",  array("*"),"LEFT"
    );
    
    // query to fetch specific column
    $resultSet = $this->tableGateway->selectWith($select)->getDataSource();
    
    // this will return columns that are not specified in the query,
    // but values are null
    $resultSet = $this->tableGateway->selectWith($select);
    
    foreach ($resultSet as $row) {
        \Zend\Debug\Debug::dump($row);
        exit;
    }
    // dump sql query
    /// echo $this->tableGateway->getSql()->getSqlStringForSqlObject($select);

}

Sample select with joins

Input Filters

namespace Album\Filter;

use Zend\InputFilter\InputFilter;
use Zend\Validator\NotEmpty;

class AlbumFilter extends InputFilter
{
    public function __construct()
    {
        $this->add(array(
            'name'     => 'artist',
            'required' => true,
            'filters'  => array(
                array('name' => 'StripTags'),
                array(
                    'name' => 'StringTrim',
                ),
            ),
            'validators' => array(
                array(
                    'name'    => 'StringLength',
                    'options' => array(
                        'min'     => 1,
                        'max'     => 35,
                        'messages' => array(
                            'stringLengthTooShort' => 'Artist is too short.',
                            'stringLengthTooLong' => 'Artist is too long.'
                        ),
                    ),
                ),
            ),
        ));
}

Create Filters under src/Filter directory.

Then register in service manager as invokables if there are no dependencies, otherwise create Factory for your filter class then register in service manager factories

Session Manager

public function onBootstrap(MvcEvent $e)
{
    .... Some codes here .... 

    /**
     * This method will handle the setting of session sharing configurations
     * and also starting the session manager.
     */

    $sm = $e->getApplication()->getServiceManager();
    $config = $sm->get('Configuration');
    $sessionConfig = new SessionConfig();
    $sessionConfig->setOptions($config['session_config']);
    $sessionManager = new SessionManager($sessionConfig);
    $sessionManager->start();
}

Configure and Start Session Manager

1. Edit Application/src/Module.php and update onBootstrap method

2. Add session configuration in local.php

'session_config' => array(
        'remember_me_seconds' => 2419200,
        'use_cookies' => true,
        'cookie_domain' => '.zftraining.com',
//        'php_save_handler' => 'memcache',
//        'save_path' => 'tcp://memcached-session:11211',
    ),

Factory Design Pattern

Dependency Injection

Dependency injection (Di) is a design pattern which purpose is to reduce the coupling between software components.

Service Manager

  • Allow to programmatically configure dependencies.
  • Use to easily apply Inversion Of Control.
  • Creates and stores instances of your objects: an instance manager.

Getting Started with

By pgamilde

Getting Started with

  • 770