CloudParty - Php & Cloud

Sviluppo di API REST con ZF2 & MongoDB

Created by Gianluca Arbezzano / @GianArb

Dependencies

  • DoctrineModule
  • DoctrineMongoODMModule

    {
        "require": {
            "php": ">=5.3.3",
            "zendframework/zendframework": "~2.3.0",
            "doctrine/mongodb-odm": "1.0.0-beta11",
            "doctrine/doctrine-mongo-odm-module": "0.8.1"
        }
    }

Zend Framework

Doctrine

The Doctrine Project is the home to several PHP libraries primarily focused on database storage and object mapping


Support MongoDB and Document Object Mapping (ODM) pattern

Index - Ping!

localhost/


{
"ping": true
}

Status Code: 200


namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\JsonModel;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return new JsonModel(array('ping' => true));
    }
}
                

Crud - this is not all that simple

But

Exist \Zend\Mvc\Controller\AbstractRestfulController

An abstract controller to manage Restulf action

  • Get
  • Get list
  • Put
  • Delete
  • ...

Connection with DATABASE


return array(
    'doctrine' => array(
        'connection' => array(
            'odm_default' => array(
                'server'           => 'localhost',
                'port'             => '27017',
            ),
        ),
    ),
);
                        

Doctrine Configuration


return array(
    'doctrine' => array(
        'connection' => array(),
        'configuration' => array(
            'odm_default' => array(
                'generate_proxies'   => false,
                'proxy_dir'          => 'data/Application/Proxy',
                'proxy_namespace'    => 'Application\Proxy',
                'generate_hydrators' => false,
                'hydrator_dir'       => 'data/Application/Hydrator',
                'hydrator_namespace' => 'Application\Hydrator',
                'default_db'         => "rest-test",
            )
        ),
    ),
);
                        

Doctrine driver configurations


return array(
    'doctrine' => array(
        'connection' => array(),
        'configuration' => array(),
        'driver' => array(
            'odm_default' => array(
                'drivers' => array(
                    'Application\\Document' => 'app'
                ),
            ),
            'app' => array(
                'class' => 'Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver',
                'cache' => 'array',
                'paths' => array(
                    __DIR__ . '/../../module/Application/src/Application/Document'
                )
            )
        ),
    ),
);
                        

Ready

Thanks DoctrineModule & DoctrineMongoODMModule!


$ php public/index.php
Zend Framework 2.3.3 application
-------------------------------------------------------------------------------
DoctrineModule
-------------------------------------------------------------------------------
DoctrineModule Command Line Interface version 0.8.0
Available commands:
odm
  odm:generate:documents      Generate document classes and method stubs from
                              your mapping information.
  odm:generate:hydrators      Generates hydrator classes for document classes.
  odm:generate:proxies        Generates proxy classes for document classes.
  odm:generate:repositories   Generate repository classes from your mapping information.
  odm:query                   Query mongodb and inspect the outputted results from
                              your document classes.
  odm:schema:create           Create databases, collections and indexes for your documents
  odm:schema:drop             Drop databases, collections and indexes for your documents
                        

Document Manager Service


class Controller extends AbstractRestfulController
{
    public function get($id){
        $dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
    }
}
                        

User Document


namespace Application\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Zend\Form\Annotation;
/**
* @ODM\Document(collection="users",
*   repositoryClass="Application\Document\Repository\UserRepository")
*/
class User
{
    /**
    * @ODM\Id(strategy="AUTO")
    */
    private $id;
    /**
    * @ODM\Field(name="name", type="string")
    */
    private $name;
    ...
}
                        

Generate document (getter/setter)


    $ php public/index.php odm:generate:documents
                        

Application\Controller\UserController


namespace Application\Controller;

use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;

class UserController extends AbstractRestfulController
{
    public function create($data) {}
    public function delete($id) {}
    public function get($id) {}
    public function getList() {}
    public function update($id, $data) {}
}
                        

Get list /user METHOD GET


class UserController extends AbstractRestfulController
{
    public function getList()
    {
        $content = array();
        $dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
        $hydrator = $this->getServiceLocator()->get("Hydrator\User");
        $userRepo = $dm->getRepository("Application\\Document\\User");

        $users = $userRepo->findAll();
        foreach($users as $user){
            $content[] = $hydrator->extract($user);
        }

        return new JsonModel($content);
    }
}
                        

Get single /user[/id] METHOD GET


class UserController extends AbstractRestfulController
{
    public function get($id)
    {
        $dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
        $hydrator = $this->getServiceLocator()->get("Hydrator\User");
        $userRepo = $dm->getRepository("Application\\Document\\User");
        $user = $userRepo->find($id);
        if(!$user)  {
            // User not found STATUS code 404
        }

        return new JsonModel($hydrator->extract($user));
    }
}
                        

Create user /user METHOD POST


class UserController extends AbstractRestfulController
{
    public function create($data)
    {
        $dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');

        $filter = $this->getServiceLocator()->get("Filter\User");
        $filter = $filter->validate($data);
        if (!$filter->isValid()) {
            // Not Valid STATUS code 400 Bad Request
        }
        $user = new \Application\Document\User();
        $hydrator = $this->getServiceLocator()->get("Hydrator\User");
        $hydrator->hydrate($data, $user);
        $dm->persist($user);
        $dm->flush();
    }
}
                        

Delete /user[/id] - METHOD DELETE


class UserController extends AbstractRestfulController
{
    public function delete($id)
    {
        $dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
        $userRepo = $dm->getRepository("Application\\Document\\User");

        $user = $userRepo->find($id);
        if (!$user) {
            // User not found STATUS code 404
        }
        $dm->remove($user);
        $dm->flush();

        return new JsonModel(array("status" => "deleted"));
    }
}
                        

Update user /user[/id] METHOD PUT


class UserController extends AbstractRestfulController
{
    public function update($id, $data)
    {
        $dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
        $hydrator = $this->getServiceLocator()->get("Hydrator\User");
        $userRepo = $dm->getRepository("Application\\Document\\User");

        $user = $userRepo->find($id);
        if(!$user)  {
            // User not found STATUS code 404
        }
        $hydrator->hydrate($data, $user);
        $userArray = $hydrator->extract($user);
        $filter = $this->getServiceLocator()->get("Filter\User");
        $filter = $filter->validate($userArray);
        if (!$filter->isValid()) {
            // Not Valid STATUS code 400 Bad Request
        }

        $dm->persist($user);
        $dm->flush();
        return new JsonModel($userArray);
    }
}
                        

Filters & Validator


namespace Application\Model\Filter;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
class User
{
    private $inputFilter;

    public function __construct()
    {
        $this->inputFilter = new InputFilter();
        $factory = new InputFactory();
        ....
        $this->inputFilter->add($factory->createInput(array(
            'name'     => 'role',
            'required' => true,
            'filters'  => array(
                array('name' => 'StringTrim'),
            ),
            'validators' => array(
                array(
                    'name'    => 'InArray',
                    'options' => array(
                        'haystack' => array('admin', 'client')
                    ),
                ),
            ),
        )));
    }
}
                        

Filters & Validator


namespace Application\Model\Filter;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
class User
{
    private $inputFilter;

    public function __construct()
    {
        $this->inputFilter = new InputFilter();
        $factory = new InputFactory();
        ....
    }

    public function validate($data)
    {
        return $this->inputFilter->setData($data);
    }
}
                        

Thanks!


    git clone git@github.com:gianarb/zf2-api-test.git
                    

Try APP and run tests


    vendor/bin/phpunit