Upload
kirill-chebunin
View
1.399
Download
5
Embed Size (px)
DESCRIPTION
Some thoughts about IoC, annotations and AOP in PHP & ZF for ZFConf Ukraine 2010. Language: Russian.
Citation preview
Чуть сложнее чем Singleton
Аннотации, IoC, АОП
Kirill chEbba Chebunin
• Аннотации, IoC, АОП
• АОП через IoC + аннотации
• Далеко не новые технологии
• В PHP мало используются
О докладе
1. Аннотации
@Entitypublic class User {/**/}
[Class]
public class User {/**/}
/** @Entity */
class User {/**/}
Аннотации
• Метаданные, описывающие классы, методы, свойства
• Компромисс между «соглашениями» и «конфигурацией»
• Конфигурация непосредственно в коде
Аннотации
PHPUnit – возможно, одна из первых билиотек с использованием аннотаций.
/** * @expectedException RuntimeException */public function testException(){}
Аннотации. Аннотации в PHP
Zend_Reflection – чтение PHPDoc тегов.
$class = new Zend_Reflection_Class( 'MyClass');$docBlock = $class->getDocblock();$tag = $docBlock->getTag('myTag');echo $tag->getDescription();
Аннотации. Аннотации в PHP
И, конечно, Doctrine 2
/** @Entity */class MyPersistentClass{ /** @Column(type="integer") */ private $id; /** @Column(length=50) */ private $name; // type defaults to string //...}
Аннотации. Аннотации в PHP
$reader = new AnnotationReader();$reader->setDefaultAnnotationNamespace( 'Doctrine\ORM\Mapping‘);$entity = $reader->getClassAnnotation( 'MyPersistentClass', 'Doctrine\ORM\Mapping\Entity');if ($entity !== null) { //Entity! Do smth}
Аннотации. Аннотации в PHP
Можно использовать в ActionHelper’ах.
•ContextSwitch (AjaxContext)
•Cache
Аннотации. Аннотации в ZF
/** @ContextSwitchable */class FooController extends Zend_Controller_Action{
/** @Context({"xml", "json"}) */ public function barAction() { // Do smth }}
Аннотации. Аннотации в ZF
/** @PageCache(tags={"foo", "bar"}) */ public function barAction() { // Do smth }
Аннотации. Аннотации в ZF
2. IoC
Что же такое зависимости?
class FooController extends Zend_Controller_Action{ public function barAction() { $service = new MyUserService(); $service->getUser(1); }}
IoC. Зависимости
Шаг 1. Берем готовый объект из хранилища.
•Service Locator
•Registry
•etc
IoC. Контейнер
// Zend_Registry
$service =
Zend_Registry::get('userService');
// Bootstrap container
$service = $this->getInvokeArg('bootstrap')
->getResource('userService');
IoC. Контейнер
Шаг 2. Используем интерфейсы.
interface UserService
{/**/}
class MyUserService implements UserService {/**/}
IoC. Интерфейсы наше все
interface UserService { public function getUser($id);}
IoC. Интерфейсы наше все
class MyUserService implements UserService { protected $userDao;
public function __construct(UserDao $userDao) { $this->userDao = $userDao; }
public function getUser($id) { $this->userDao->getUserById($id); }}
IoC. Интерфейсы наше все
• Класс прдоставляет метод/свойство для инъекции (внедрения) зависимости.
• Внедрением занимается вышестоящий компонент
IoC. Dependency Injection
protected $userService;
public function setUserService( UserService $userService){ $this->userService = $userService;}
public function barAction(){ $this->userService->getUser(1);}
IoC. Dependency Injection
•Кто же будет заниматься внедрением?
•Как просто конфигурировать зависимости?
IoC. Dependency Injection
• Специальные IoC контерйнеры.
• Для PHP Symfony Dependency Injection
• Есть версия для 5.+ • Есть версия для 5.3
IoC. Symfony DI
• Контейнер содержит описание объектов.
• ZF2 - LazyLoadingBroker
IoC. Symfony DI
<service id="userDao" class="NotMyUserDao"> <!-- Some DB params for example --></service>
<service id="userService" class="MyUserService"> <argument type="service" id="userDao"/></service>
IoC. Symfony DI
$container = new ContainerBuilder();$loader = new XmlFileLoader($container);$loader->load('path/container.xml');
/* @var $service UserService */$service = $container->get('userService');
IoC. Symfony DI
Можно подменить контейнер.
$application->getBootstrap() ->setContainer($container);
$application->bootstrap()->run();
IoC. ZF + Symfony DI
А можно запустить непосредственно ФронтКонтроллер.
$front = $container->get('frontController');
$front->dispatch();
IoC. ZF + Symfony DI
Объекты, создаваемые ZF автоматически
•Контроллеры
•ActionHelper’ы
•ViewHerlper’ы
•Плагины
IoC. ZF + Symfony DI. Проблемы
ZF 1.x
•ActionHelper для инъекции в контроллеры
•Реализация Dispatcher’а
•Наследование Zend_Controller_Action
•Наследование Zend_View
IoC. ZF + Symfony DI. Решения
ZF 2.x
•ActionHelper для инъекции в контроллеры
•Реализация PluginLoader’a
•Dispatcher через PluginLoader
IoC. ZF + Symfony DI. Решения
3. АОП
• Прадигма программирования
• Сквозная функциональностьЛог, обработка ошибок, права доступа, транзакции.
• Первая реализация - AspectJ
АОП. Что это?
• JoinPoint (Точка соединения) – метод, которому нужно добавить функциональность
• Pointcut (Срез) – набор JoinPoint’ов
АОП. Основные понятия
/** @Cached */public function cacheMeDude() {/* */} /** @Log */public function plzLogMe() {/* */} /** @Transactional */public function iNeedTransaction() {/* */}
АОП. Реализация на PHP
• Aspect (Аспект)
• Advice (Совет)
Before, After, AfterException, AfterReturn, Around
АОП. Что это?
Advice как метод класса.
/** @Around("@annotation(Cached)") */
public function cache(
ProceedingJoinPoint $joinPoint)
{
// Cache result or return from cache
}
АОП. Что это?
Изменить работу метода, не трогая готовый код.
•Переопределение в рантайме (runkit, etc)
•«Предкомпилирование» кода
•Прокси классы
АОП. Реализация на PHP
Подмена объекта, прокси объектом.
Например, при создании в IoC контейнере.
$objectProxy =
ProxyClass::createProxyFromObject(
$object,
$handler
);
АОП. Реализация на PHP
Генерируем прокси-классы с помощью
Zend_CodeGenerator
class TestAOPCheProxy extends TestAOP
{
// Override all methods
}
АОП. Реализация на PHP
Override всех public и protected методов
public function method($foo, $bar){ return $this->invocationHandler->invoke( $this, new ReflectionMethod( get_parent_class(__CLASS__), __FUNCTION__ ), func_get_args() );}
АОП. Реализация на PHP
/** @Cached */public function cacheMeDude() {/* */} /** @Log */public function plzLogMe() {/* */} /** @Transactional */public function iNeedTransaction() {/* */}
АОП. Реализация на PHP
$aopedObject->cacheMeDude();•ProxyClass::cacheMeDude();
– Handler::invoke()
• CacheAspect::cache()
–? OriginalClass::cacheMeDude()
АОП. Реализация на PHP
• Не панацея
• Может усложнить систему
• Тестирование
АОП. Заключение