Общая архитектура Yii2
Управление зависимостями
Автозагрузка классов
Магия в PHP
Порождение объектов
Задание любого объекта через массив:
Dependency Injection (DI)
MVC в Yii2
Маршрутизация web запроса
Построение отображения
Структура отображения
Виджет (Widget)
Asset Management
Модель
Доступ к базе данных через PDO
Абстракция базы данных
Select Query Shortcut
Active Record
«Жадная» загрузка отношений
NOSQL Active Record
Cross-DBMS отношения
События (Events) в Yii
Обработка события
Проблема множественного наследования
Поведение (Behavior)
Расширение интерфейса
Обработка событий
Отправка электронной почты
Расширение «AuthClient»
Дополнительные расширения
Yii2

Общая архитектура Yii2

1. Общая архитектура Yii2

Климов П.В.
YiiSoft

2.

Область применения
• Построение функциональности не
имеющей аналогов
• Новая интерпретация уже существующих
бизнес процессов
• Стык или объединение различных
областей и процессов
• Системы с повышенными требованиями к
качеству

3.

Основные характеристики
PHP 5.4
ООП
Модульность
Простота
Высокое быстродействие

4. Управление зависимостями

Composer
Manages PHP packages
"request non-PHP package"
composer-asset-plugin
Substitute Bower client,
compatible with composer
"use Bower protocol as client"
Bower
Manages CSS and
JavaScript packages

5. Автозагрузка классов

// Autoload via Composer by PSR-4 :
$model = new yii\base\Model();
// Yii built-in autoload by PSR via alias:
Yii::setAlias(‘@app’, ‘/var/www/myproject’);
$someObj = new app\models\Customer();
// include ‘/var/www/myproject/models/Customer.php’;

6. Магия в PHP

class Object
{
public $publicProperty;
private $_privateProperty;
public function setPrivateProperty($value)
{
$this->_privateProperty = $value;
}
public function getPrivateProperty()
{
return $this->_privateProperty;
}
}

7.

class Object
{
public function __get($propertyName)
{
$methodName = 'get‘ . $propertyName;
if (method_exists($this, $methodName)) {
return call_user_func([$this, $methodName]);
} else {
throw new Exception("Missing property {$propertyName}'!");
}
}
public function __set($propertyName, $value)
{
$methodName = 'set‘ . $propertyName;
if (method_exists($this, $methodName)) {
return call_user_func([$this, $methodName], $value);
} else {
throw new Exception("Missing property {$propertyName}'!");
}
}

8.

$object = new Object();
$object ->publicProperty = 'Public value';
echo ($object->publicProperty);
$object->privateProperty = 'Private value';
echo ($object->privateProperty);

9. Порождение объектов

function createObject(array $config)
{
$className = $config['class'];
if (empty($className)) {
throw new Exception(‘Missing parameter "class"!');
}
unset($config['class']);
$object = new $className();
foreach ($config as $name=>$value) {
$object->$name = $value; // Конфигурация
}
return $object;
}

10. Задание любого объекта через массив:

$config = [
'class‘ => ‘yii\web\UrlManager',
'enablePrettyUrl‘ => true,
'showScriptName‘ => false,
'rules‘ => [
'/‘ => 'site/index',
'<controller:\w+>/<id:\d+>*‘ => '<controller>/view',
],
];
$object = Yii::createObject($config);

11. Dependency Injection (DI)

di\ServiceLocator
$definitions
$components
get($id)
“Get class
instance”
“Request component
by id”
1
Client
“Create and
store by id”
*
base\Component
“instantiate”
di\Container
$definitions
$dependencies
$singletons
set($class, $params)
get($class)
ComponentA

12.

di\ServiceLocator
base\Module
base\Application

13.

$config = [
'name‘ => 'My Web Application',

'components‘ => [
'user‘ => [
‘enableAutoLogin‘ => true,
],

],
];
(new yii\web\Application($config))->run();

$application = Yii::$app;
$user = Yii::$app->get(‘user’);

14. MVC в Yii2

1
1
Application
*
1
Module
Widget
*
*
Component
*
“create”
View
*
Model
C
*
Controller
“render” 1
“render
part”
*
“register”
*
*
AssetBundle
V
M

15. Маршрутизация web запроса

:Application
web server
‘run’
:Request
:UrlManager
‘handle’
‘resolve’
‘data’
‘route’
:Controller
‘run action’
‘response’
‘compose output’
‘output’
‘output’
:Response

16. Построение отображения

class View extends Component
{
public function renderFile($viewFile, $data = null)
{
require($viewFile);
}
}
<html>
<body>
<h1>Data <?php echo $data; ?></h1>
<hr />
<?php $this->render(‘main_menu.php’); ?>
</body>
</html>

17. Структура отображения

“determine view path”
View
render()
1
1
ViewContextInterface
“by file extension”
1
*
ViewRenderer
“Define specific renderer”
smarty\ViewRenderer
handles *.tpl
twig\ViewRenderer
handles *.twig

18. Виджет (Widget)

<?php echo GridView::widget([
'dataProvider' => $dataProvider,
'options' => ['class' => 'detail-grid-view table-responsive'],
'filterModel' => $searchModel,
'columns' => [
'time',
'level',
'category',
'message',
],
]); ?>

19. Asset Management

Client
Shortcut static
method
"register()"
View
“Depends on”
$assetBundles
registerAssetBundle()
“Get Asset
Bundle”
AssetManager
$bundles
1
“Create,
override
and
register”
*
AssetBundle
$css
$js
$depends
getBundle()
“Compose
actual files”
AssetConverter
convert()
JqueryAsset

20.

class YiiAsset extends AssetBundle
{
public $sourcePath = '@yii/assets';
public $js = [
'yii.js',
];
public $depends = [
'yii\web\JqueryAsset',
];
}
class JqueryAsset extends AssetBundle
{
public $sourcePath = '@bower/jquery/dist';
public $js = [
'jquery.js',
];
}

21. Модель

Model
“Create and run”
setAttributes()
getAttributes()
validate()
1
*
Validator
“Define specific validator”
EmailValidator
RangeValidator

22. Доступ к базе данных через PDO

Client
PDO
1
1
PDO Driver
PDO MySQL
PDO PostgreSQL
MySQL
PostgreSQL

23. Абстракция базы данных

PDO
1
1
“Syntax”
1
1
QueryBuilder
“Use”
1
*
mysql\QueryBuilder
Connection
1
*
“Types, keys, etc.”
“Create”
Command

1
1
“Use”
*
1
Schema
mysql\Schema

24. Select Query Shortcut

1
Query
“Create”
*
BatchQueryResult
“Create and
execute”
1
*
*
“Build”
Command
1 QueryBuilder
1
Iterator
1
DataReader
Countable

25. Active Record

BaseActiveRecord
save()
delete()
Shortcut static
method "find()"
ActiveRecord
1
*
ActiveRelationTrait
*
1
“Instantiate by
query result”
ActiveQuery
“Database
access”
Command
Query

26.

// Выборка записей:
$allUsers = User::find()->all();
// Вставка новой записи:
$newUser = new User();
$newUser->name = ‘new user’;
$newUser->save();
// Обновление существующей записи:
$existingUser = User::find()->where([‘name’=>‘testuser’])->one();
$existingUser->email = ‘[email protected]’;
$existingUser->save();
// Отложенная загрузка отношения:
$bio = $existingUser->profile->bio;
// Жадная загрузка отношения:
$allUsers = User::find()->with(‘profile’)->all();

27. «Жадная» загрузка отношений

:ActiveQuery
Client
‘find with
"profile"’
‘create from
query result’
:User
‘get "profile"
info’
‘relation info’
:ActiveQuery
‘find where userId in set’
‘profile references’
‘bind "profile"’
‘result’
:Profile

28. NOSQL Active Record


MongoDB
Redis
ElasticSearch
Sphinx

29. Cross-DBMS отношения

BaseActiveRecord
db\ActiveRecord
mongodb\ActiveRecord
“Has relation”
User
Profile

30. События (Events) в Yii

Component
1
“Raise”
eventHandlers
Event
sender
data
trigger()
1
*
1
PHP
Callback
“Handle”
*
Handler
“List of PHP callbacks”
*

31. Обработка события

Event Handler
:ActiveRecord
Client
‘save’
‘raise
“beforeInsert”’
:Event
*
‘handle “beforeInsert”’
‘get event
info’
‘sender’
‘adjust event sender’
‘saving
result’
‘actual data
saving’

32.

function handleBeforeInsert(Event $event)
{
$sender = $event->sender;
// Изменяем состояние отправителя события:
$sender->create_date = date('Y-m-d', strtotime('NOW'));
}
$user = new User();
// Назначаем обработчик события:
$user->on(‘beforeInsert’, ‘handleBeforeInsert’);
$user->name = ‘test name’;
$user->save();
echo $user->create_date; // Вывод: ‘2015-03-21’

33. Проблема множественного наследования

ActiveRecord
ArPosition
ArFile
Save custom records
display order
Bind physical file with
the db record
ArPositionFile
Position + File

34. Поведение (Behavior)

1
*
Component
Behavior
behaviors
owner
__call()
attachBehavior()
getOwner()
events()
1
1
“Raise”
*
Event
data
*
“Handle”

35. Расширение интерфейса

class Component
{
private $_behaviors = [ ];
public function __call($method, $arguments)
{
// Ищем недостающий метод среди поведений:
foreach ($this->_behaviors as $behavior) {
if (method_exists($behavior, $method)) {
return $behavior->$method($arguments);
}
}
throw new Exception(“Missing method {$method}”);
}

}

36.

class ArBehaviorExample extends Behavior
{
public function behaviorMethod()
{
$this->owner->create_date = date('Y-m-d', strtotime('NOW'));
}
}
$user = new User();
// Добавляем поведение:
$behavior = new ArBehaviorExample();
$user->attachBehavior($behavior);
// Вызываем метод поведения:
$user->behaviorMethod();
echo $user->create_date; // Вывод: ‘2015-03-21’

37. Обработка событий

class ExampleBehavior extends Behavior
{
public function events()
{
return [
‘beforeInsert’ => ‘handleBeforeInsert’,
‘afterInsert’ => ‘handleAfterInsert’
];
}
public function handleBeforeSave(Event $event)
{
// Обработка события «beforeInsert»
}

}

38. Отправка электронной почты

yii\mail
MailerInterface
1
“Send”
*
MessageInterface
Shortcut method "send()"
BaseMailer
BaseMessage
yii\swiftmailer
Mailer
Message

39. Расширение «AuthClient»

Collection
1
*
ClientInterface
“Configure and
create”
BaseClient
OAuth1
Twitter
BaseOAuth
OAuth2
Facebook
OpenId
Yandex

40. Дополнительные расширения


Gii
Debug
Boostrap
JUI
Codeception
Imagine
ApiDoc

41. Yii2


Composer + Bower
Компонентная структура и DI
MVC
Управление «assets»
PDO и Active Record
NOSQL и Active Record
Cross-DBMS отношения
События
Поведения
Стандартные расширения
ZFort приглашает на работу:
Senior Magento
Developer /
TechLead
Middle
ASP.NET
Developer
Senior
Project
Manager
Middle PHP
CMS
Developer
Middle
FrontEnd
Developer
English     Русский Правила