André Roaldseth
Developer at NAV
André Roaldseth - @androa
interface BootstrapListenerInterface
{
/**
* Listen to the bootstrap event
*
* @param EventInterface $e
* @return array
*/
public function onBootstrap(EventInterface $e);
}
interface ConfigProviderInterface
{
/**
* Returns configuration to merge with application configuration
*
* @return array|\Traversable
*/
public function getConfig();
}
interface ControllerPluginProviderInterface
{
/**
* Expected to return \Zend\ServiceManager\Config object or array
* to seed such an object.
*
* @return array|\Zend\ServiceManager\Config
*/
public function getControllerPluginConfig();
}
interface ControllerProviderInterface
{
/**
* Expected to return \Zend\ServiceManager\Config object or array
* to seed such an object.
*
* @return array|\Zend\ServiceManager\Config
*/
public function getControllerConfig();
}
interface InitProviderInterface
{
/**
* Initialize workflow
*
* @param ModuleManagerInterface $manager
* @return void
*/
public function init(ModuleManagerInterface $manager);
}
interface ServiceProviderInterface
{
/**
* Expected to return \Zend\ServiceManager\Config object or array
* to seed such an object.
*
* @return array|\Zend\ServiceManager\Config
*/
public function getServiceConfig();
}
interface ViewHelperProviderInterface
{
/**
* Expected to return \Zend\ServiceManager\Config object or array
* to seed such an object.
*
* @return array|\Zend\ServiceManager\Config
*/
public function getViewHelperConfig();
}

interface Breakfast {
/**
* Every Breakfast requires Bacon!
*
* @param Bacon $bacon ALL the bacon you have!
*/
function __construct(Bacon $bacon);
/**
* But Eggs can be optional.
*
* @param Eggs $eggs Some eggs if you have :)
*/
function setEggs(Egg $eggs);
}
$bacon = $serviceManager->get('Bacon');
$eggs = $serviceManager->get('Eggs');
$breakfast = new Breakfast($bacon);
// Did we have any eggs?
if ($eggs) {
$breakfast->setEggs($eggs);
}
class Users {
public function __construct() {
$this->pdo = new PDO('mysql:..');
}
public function hasValidMembership($userId) {
$sql = 'SELECT 1 FROM users WHERE userId = :userId';
}
}
class Users {
public function __construct($pdo = null) {
$this->pdo = $pdo;
}
public function getUser($userId) {
// Get the user from MySQL
return new User($data);
}
public function hasValidMembership(User $user) {
return $user->membershipEndsDate > time();
}
}class Users {
public function hasValidMembership(
User $user,
DateTime $now = null) {
if ($now === null) {
$now = new DateTime();
}
return $user->membershipEndsDate > $now->getTimestamp();
}
}'invokables' => array(
'Bacon' => 'Breakfast\Refrigerator\Bacon',
'Eggs' => 'Breakfast\Refrigerator\Eggs',
);'breakfast' => function($serviceManager) {
$bacon = $serviceManager->get('Bacon');
$eggs = $serviceManager->get('Eggs');
$breakfast = new Breakfast($bacon);
$breakfast->setEggs($eggs);
return $breakfast;
}
'initializers' => array(
function($instance, $sm) {
if ($instance instanceof LoggerAwareInterface) {
$instance->setLogger($sm->get('logger'));
}
}
),
'shared' => array(
'breakfast' => false
);
. ├── config │ └── application.config.php ├── modules │ └── SomeModule ├── public │ ├── css │ ├── index.php │ └── js ├── tests │ └── phpunit.xml.dist └── vendor
.
├── config
│ └── module.config.php
├── Module.php
├── src
│ └── SomeModule
│ └── Controller
│ └── SomeController.php
└── tests
└── phpunit.xml.dist
{
"name": "vgno/article-export",
"description": "A CLI tool for exporting articles from Edrum.",
"license": "MIT",
"authors": [
{
"name": "André Roaldseth",
"email": "andrer@vg.no"
}
],
"require": {
"php": ">=5.3",
"symfony/console": "2.3.*",
"symfony/process": "2.3.*",
"ezyang/htmlpurifier": "4.5.*"
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
},
"autoload": {
"psr-0": {
"ArticleExport": "src"
}
}
}
class IndexController extends AbstactActionController {
public function indexAction() {
if (!$this->hasAccess()) {
return $this->getResponse()->setStatusCode(401);
}
// Tons of more logic to do if user has access
return new ViewModel();
}
}
class Module implements BootstrapInterface {
public function onBootstrap(EventInterface $event) {
$application = $event->getTarget();
$serviceManager = $application->getServiceManager();
$application->getEventManager()
->attach(function (MvcEvent $event) use ($serviceManager) {
$request = $event->getRequest();
$response = $event->getResponse();
if ($serviceManager->get('AuthHandler')
->hasAccess($request)) {
return; // Carry on
}
$response->setStatusCode(401);
// Stop the rest application to run
$event->setResult($response);
return false; // Stop other event listeners
}, MvcEvent::EVENT_DISPATCH);
}
}class Module implements BootstrapInterface {
public function onBootstrap(EventInterface $event) {
// ... Same as previous slide
->attach(function (MvcEvent $event) use ($serviceManager) {
$response = $event->getResponse();
$routeMatch = $event->getRouteMatch();
if ($routeMatch
->getMatchedRouteName() === 'articles') {
$articleId = $routeMatch->getParam('articleId');
$article = $serviceManager->get('ArticleLoader')
->fetchArticle($articleId));
if (!$article) {
$event->setResult($reponse->setStatusCode(404));
return false;
}
$routeMatch->setParam('article', $article);
}
}, MvcEvent::EVENT_DISPATCH);
}
}
class SomeArticleController extends AbstractActionController {
public function articleAction() {
$article = $this->getParam('article');
// Do article stuff
// Give the article to the view layer.
return new ViewModel('article', $article);
}
}class SomeController extends AbstractActionController {
public function getAction() {
$something = $this->getSomeServiceLayer()
->get($this->getParam('id'));
// We always want to deliver this as JSON,
// so we make JsonModel instead of ViewModel.
return new JsonModel($something);
}
}class SomeController extends AbstractActionController {
protected $acceptCriteria = array(
'Zend\View\Model\JsonModel' => array(
'application/json', // <- content-type, supports *
),
// ...
);
public function getAction() {
$something = $this->getSomeServiceLayer()
->get($this->getParam('id'));
// We want to do content negotiation so we use the,
// acceptableViewModelSelector which looks at the
// HTTP Accept header and returns a correct ViewModel.
$viewModel = $this->acceptableViewModelSelector(
$this->acceptCriteria
);
$viewModel->setVariables($something);
return $viewModel;
}
}By André Roaldseth
A short introduction to Zend Framework 2 intended for my co-workers at VG.