Design pattern decorator

<?php
 
interface IDecorator {
    public function decorate();
}
 
abstract class Decorator implements IDecorator {
    protected $_toDecorate;
 
    public function __construct(IDecorator $toDecorate) {
        $this->_toDecorate = $toDecorate;
    }
}
 
class Html implements IDecorator {
    protected $_str;
 
    public function __construct($str) {
        $this->_str = $str;
    }
 
    public function decorate() {
        return $this->_str;
    }
}
 
class Strong extends Decorator {
    public function decorate() {
        return '<strong>'.$this->_toDecorate->decorate().'</strong>';
    }
}
 
class Em extends Decorator {
    public function decorate() {
        return '<em>'.$this->_toDecorate->decorate().'</em>';
    }
}
 
 
$html = new Html('text to decorate');
 
$decorate = new Strong($html);
$decorated = $decorate->decorate();
echo $decorated.PHP_EOL;
 
$decorate = new Em($html);
$decorated = $decorate->decorate();
echo $decorated.PHP_EOL;
 
$decorate = new Strong(new Em($html));
$decorated = $decorate->decorate();
echo $decorated.PHP_EOL;

Symfony2 preExecute Controller

Listener/PublisherListener.php

<?php
namespace Main\PublisherBundle\Listener;
 
use Symfony\Component\EventDispatcher\Event; 
use Symfony\Component\HttpKernel\HttpKernelInterface; 
use Symfony\Component\HttpKernel\Event\FilterControllerEvent; 
 
class PublisherListener {
 
    public function onCoreController(FilterControllerEvent $event) {
        if(HttpKernelInterface::MASTER_REQUEST == $event->getRequestType()) {
            $_controller = $event->getController();
            if(isset($_controller[0])) {
                $controller = $_controller[0];
                if(method_exists($controller, 'preExecute')) {
                    $controller->preExecute();
                }
            }
        }
    }
}

Resources/config/services.xml

<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
 
    <parameters>
        <parameter key="main_publisher.listener.class">Main\PublisherBundle\Listener\PublisherListener</parameter>
    </parameters>
 
    <services>
        <service id="main_publisher_listener" class="%main_publisher.listener.class%">
            <tag name="kernel.event_listener" event="kernel.controller" method="onCoreController"/>
        </service>
    </services>
</container>

Controller/PublisherController.php

<?php
namespace Main\PublisherBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
 
class GamesController extends Controller {
   public function preExecute() {
        $this->gameManager = $this->container->get('main_publisher.game.manager');
        $this->userManager = $this->container->get('main_user_manager');
    }
}

symfony2 twig i18n date

sudo aptitude install php5-intl

app/config/config.yml

services:
    twig.extension.intl:
       class: Twig_Extensions_Extension_Intl
       tags:
           - { name: twig.extension }

In twig template

{{ game.created_at| localizeddate('full', 'none') }}

twig macro link title translation

{% macro link(route, title, name, attr) %}
{% spaceless %}
<a href="{{ path(route) }}" title="{{ title|trans({}, 'link') }}"{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>{{ name|trans({}, 'link') }}</a>
{% endspaceless %}
{% endmacro %}
 
<!-- Usage 
{{ macro.link('route_name', 'link title', 'link name', {'class':'css_class'}) }}
-->
 
<!-- HTML
<a href="/dashboard" title="Manage" class="pouet">Manage</a>
-->

Symfony2 service + manager

Resources/config/services.xml

<?xml version="1.0" ?>
 
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
 
    <parameters>
        <parameter key="main_publisher.game.manager.class">Main\PublisherBundle\Manager\GameManager</parameter>
    </parameters>
 
    <services>
        <service id="main_publisher.game.manager" class="%main_publisher.game.manager.class%">
            <argument type="service" id="doctrine.orm.entity_manager" />
        </service>
    </services>
</container>

Manager/BaseManager.php

<?php
namespace Main\PublisherBundle\Manager;
 
class BaseManager {
 
    protected function persistAndFlush($entity) {
        $this->_em->persist($entity);
        $this->_em->flush();
    }
 
}

Manager/GameManager.php

<?php
namespace Main\PublisherBundle\Manager;
 
use Doctrine\ORM\EntityManager;
use Main\PublisherBundle\Manager\BaseManager;
use Main\PublisherBundle\Entity\Game;
 
class GameManager extends BaseManager {
    protected $_em;
 
    public function __construct(EntityManager $em) {
        $this->_em = $em;
    } 
 
    public function save(Game $game) {
        return $this->persistAndFlush($game);
    }
 
    public function getRepository() {
        return $this->_em->getRepository('MainPublisherBundle:Game');
    }
}

Controller/GamesController.php

<?php
 
namespace Main\PublisherBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
 
use Main\PublisherBundle\Entity\Game;
use Main\PublisherBundle\Form\GameType;
 
class GamesController extends Controller
{
    public function newAction(Request $request) {
        $form = $this->createForm(new GameType(), new Game());
        if($request->getMethod() == 'POST') {
            $form->bindRequest($request);
            if($form->isValid()) {
                $game = $form->getData();
                $manager = $this->container->get('main_publisher.game.manager');
                $manager->save($game);
                return $this->redirect($this->get('router')->generate('homepage'));
            }
 
        }
        return $this->render('MainPublisherBundle:Games:new.html.twig',
            array('form' => $form->createView()));
    }
}

Design pattern registry

<?php
class Registry {
    private static $_registry = array();
 
    public static function add($name, $value) {
        self::$_registry[$name] = $value;
    }
 
    public static function get($name) {
        if(!self::exists($name))
            throw new Exception(sprintf('<%s> was not registered', $name));
 
        return self::$_registry[$name];
    }
 
    public static function exists($name) {
        if(array_key_exists($name, self::$_registry))
            return true;
        return false;
    }
}
 
Registry::add('logger', new Logger(new Logger_File('./logs/'.date('Y-m-d').'.log')));
$logger = Registry::get('logger');

Design pattern strategy

<?php
interface IFormater {
  public function format($message, $level);
}
 
class File_Xml implements IFormater {
  public function format($message, $level) {
    $date = date('Y-m-d H:i:s');
    $xml = '<message>'.PHP_EOL;
    $xml .= '  <date>'.$date.'</date>'.PHP_EOL;
    $xml .= '  <level>'.$level.'</level>'.PHP_EOL;
    $xml .= '  <desc>'.$message.'</desc>'.PHP_EOL;
    $xml .= '</message>'.PHP_EOL;
    return $xml;
  }
}
 
class File_Csv implements IFormater {
  public function format($message, $level) {
    $plain = date('Y-m-d H:i:s').';'.$level.';'.$message;
    return $plain.PHP_EOL;
  }
}
 
class Logger {
  private $_formater;
  private $_file;
 
  public function __construct(IFormater $formater, $file) {
    $this->_formater = $formater;
    $this->_file = $file;
  }
 
  public function write($message, $level = 'NOTICE') {
    $message = $this->_formater->format($message, $level);
    file_put_contents($this->_file, $message, FILE_APPEND | LOCK_EX);
  }
}
 
$logger = new Logger(new File_Csv(), '/tmp/log.csv');
$logger->write('this is an error test', 'ERROR');
$logger->write('this is a warning test', 'WARNING');
$logger->write('this is a notice test', 'NOTICE');

Design pattern observer

<?php
interface IObserver {
  public function onNew($sender, $arguments);
  public function onChange($sender, $arguments);
}
 
interface IObservable {
  public function addObserver(IObserver $observer);
}
 
class Users implements IObservable {
  private $_observers = array();
 
  public function addObserver(IObserver $observer) {
    $this->_observers[] = $observer;
  }
 
  public function addUser($name) {
    foreach($this->_observers as $observer)
      $observer->onNew($this, $name);
  }
 
  public function updateUser($name) {
    foreach($this->_observers as $observer)
      $observer->onChange($this, $name);
  }
}
 
class UsersLogger implements IObserver {
  public function onNew($sender, $arguments) {
    echo 'New user '.$arguments.'<br />';
  }
 
  public function onChange($sender, $arguments) {
    echo $arguments.' updated<br />';
  }
}
 
class MailUser implements IObserver {
  public function onNew($sender, $arguments) {
    echo 'Sendind account information to '.$arguments.'<br />';
  }
 
  public function onChange($sender, $arguments) {
    echo 'Sendind accound updates to '.$arguments.'<br />';
  }
}
 
$users = new Users();
$users->addObserver(new UsersLogger());
$users->addObserver(new MailUser());
$users->addUser('HiO');
$users->addUser('Hyun');
$users->updateUser('HiO');

Design pattern singleton

<?php
class Logger {
  static $file = null;
 
  private function __construct() {}
 
  public static function get() {
    if(is_null(self::$file))
      self::$file = fopen(date('Y-m-d').'.log', 'a+');
    return self::$file;
  }
}
 
var_dump(Logger::get(), Logger::get());

Design pattern chain of command

<?php
interface ICommand {
  public function onCommand($name, $arguments);
}
 
class CommandChain {
  private $_commands = array();
 
  public function addCommand($command) {
    $this->_commands[] = $command;
  }
 
  public function runCommand($name, $arguments) {
    foreach($this->_commands as $command) {
      if($command->onCommand($name, $arguments))
	return;
    }
  }
}
 
class Html implements ICommand {
  public function onCommand($name, $arguments) {
    if($name !== 'HTML')
      return false;
    header ("Content-Type: text/html");
    echo '<!DOCTYPE html><html><head></head><body><p>'.$arguments.'</p></body></html>';
    return true;
  }
}
 
class Xml implements ICommand {
  public function onCommand($name, $arguments) {
    if($name !== 'XML') return false;
    header("Content-Type: text/xml");
    echo '<?xml version="1.0" encoding="UTF-8" ?><out>'.$arguments.'</out>';
    return true;
  }
}
 
class Plain implements ICommand {
  public function onCommand($name, $arguments) {
    if($name !== 'PLAIN')
      return false;
    echo $arguments;
    return true;
  }
}
 
$chain = new CommandChain();
$chain->addCommand(new Html());
$chain->addCommand(new Xml());
$chain->addCommand(new Plain());
$chain->runCommand('XML', 'test xml');