SlideShare a Scribd company logo
Примеры
решения
типичных задач
за рамками ядра
Yii2
QuartSoft
YiiSoft
Климов П.В.
Интернационализация статического
текста
I18N
$translations
translate()
“translation
source”
1
*
MessageSource
translate()
DbMessageSource
PhpMessageSource
Client
“Yii::t()”
Интернационализация сущностей в
базе данных
Item
n
id
canonicalName
price
Language
id
name
locale
Translation
n
itemId
languageId
name
description
Расширение «yii2tech/ar-variation»
VariationBehavior
$variationRelation
$defaultVariationRelation
“attached behavior”
1
*
Item
$canonicalName
Language
ItemTranslation
$name
1
1
1
* “has many”
“has many”
“has many via”
class Item extends yiidbActiveRecord
{
public function behaviors()
{
return [
‘translations’ => [
'class' => VariationBehavior::class,
'variationsRelation' => 'translations',
'variationOptionReferenceAttribute' => 'languageId',
'optionModelClass' => Language::class,
]
];
}
public function getTranslations()
{
return $this->hasMany(ItemTranslation::class, [‘itemId' => 'id']);
}
}
Конфигурация «VariationBehavior»
$model = new Item();
// `getVariationModels()` возвращает список моделей-вариаций
$variations = $model->getVariationModels();
// их количество всегда равно количеству доступных опций:
var_dump(count($variations) == Language::find()->count()); // `true`
// валидация и сохранение производятся автоматически:
$post = Yii::$app->request->post();
if ($model->load($post)
&& Model::loadMultiple($model->getVariationModels(), $post)
&& $model->save())
{
return $this->redirect(['index']);
}
Управление вариаторами
class Item extends yiidbActiveRecord
{
public function behaviors()
{
return [
‘translations’ => [
// …
'defaultVariationRelation' => 'defaultTranslation',
'defaultVariationOptionReference' => function () {
return Yii::$app->language; // ID опции по умолчанию
},
'variationAttributeDefaultValueMap' => [
‘name' => ‘canonicalName‘ // fallback для атрибутов вариатора
],
]
];
}
public function getDefaultTranslation()
{
return $this->hasDefaultVariationRelation(); // `has many` -> `has one`
}
}
Вариация «по умолчанию»
class VariationBehavior extends yiibaseBehavior
{
public function __get($name)
{
try {
return parent::__get($name);
} catch (yiibaseUnknownPropertyException $e) {
return $this->getDefaultVariationModel()->{$name};
}
}
public function __set($name, $value) {…}
public function canGetProperty($name, $checkVars = true) {…}
public function canSetProperty($name, $checkVars = true) {…}
}
Добавление виртуальных свойств
«хозяину» поведения
$model = Item::find()->one();
echo $model->name; // вернет `$model->defaultTranslation->name`
// а если `defaultTranslation` не найдено, то `$model->canonicalName`
// Задание нового значения:
$model->name = ‘New translation name’;
// «Жадная» загрузка:
$models = Item::find()->with(‘defaultTranslation’)->all();
foreach ($models as $model) {
echo $model->name;
}
Прямой доступ к атрибутам вариатора
Сущности с общими атрибутами
Преподаватель Студент
- Ученая
степень
- Зарплата
- ФИО
- Паспорт
- Адрес
- Телефон
- Учебная
группа
- Стипендия
Роли в реляционной базе данных
Person
id
name
address
phone Student
personId
studyGroupId
scolarship
Instructor
personId
rankId
salary
Роли в реляционной базе данных
Person
1
id
name
address
phone Student
personId
studyGroupId
scolarship
Can be
1
Instructor
personId
rankId
salary
Can be
1 1
Расширение «yii2tech/ar-role»
RoleBehavior
$roleRelation
“attached behavior”
1
Student
Instructor
Person
1
1
1
“has one”
“has one”
1
1
“attached behavior”
1
1
class Student extends yiidbActiveRecord
{
public function behaviors()
{
return [
‘translations’ => [
'class' => RoleBehavior::class,
‘roleRelation' => ‘person',
]
];
}
public function getPerson()
{
return $this->hasOne(Person::class, [‘id' => ‘personId']);
}
}
Конфигурация «RoleBehavior»
class RoleBehavior extends yiibaseBehavior
{
public function __get($name)
{
try {
return parent::__get($name);
} catch (yiibaseUnknownPropertyException $e) {
return $this->getRoleRelationModel()->{$name};
}
}
public function __call($name, $params)
{
$model = $this->getRoleRelationModel();
if ($model->hasMethod($name)) {
return call_user_func_array([$model, $name], $params);
}
return parent::__call($name, $params);
}
}
Эмуляция наследования
$model = Student::find()->one();
echo $model->name; // вернет `$model->person->name`
// Задание нового значения:
$model->name = ‘John Doe’;
// валидация и сохранение производятся автоматически:
$model->save(); // вызов `$model->person->save()`
$model->locateAddress(); // вызов `$model->person->locateAddress()`
// «Жадная» загрузка:
$models = Student::find()->with(‘person’)->all();
foreach ($models as $model) {
echo $model->name;
}
Прямой доступ к атрибутам роли
Сохранение файлов
Client
Web
Server
HTTP
requests
HDD
File read/write
Распределенные приложения
Client
Load
Balancer
Regular
HTTP
requests
Web
Server 1
Web
Server 2
Internal HTTP requests
HDD 1 HDD 2
File read/write File read/write
Централизованное файловое хранилище
Client
Load
Balancer
Regular
HTTP
requests
Web
Server 1
Web
Server 2
Internal HTTP requests
File
Server
FTP / SFTP / REST
FTP / SFTP / REST
Абстракция файловой системы
sftpStorage
fileStorage
$buckets
getBucket()
“consists of”
1
*
fileBucket
saveFileContent()
getFileContent()
localStorage
sftpBucket
localBucket
Client
“file
r/w”
$bucket = Yii::$app->fileStorage->getBucket('tempFiles');
// создать файл с заданным содержимым:
$bucket->saveFileContent('foo.txt', 'Foo content');
// удалить файл:
$bucket->deleteFile('foo.txt');
// скопировать файл в хранилище:
$bucket->copyFileIn('/path/to/source/file.txt', 'file.txt');
// скопировать файл из хранилища:
$bucket->copyFileOut('file.txt', '/path/to/destination/file.txt');
var_dump($bucket->fileExists('file.txt')); // выводит `true`
echo $bucket->getFileUrl('file.txt'); // выводит:
// http://domain.com/files/f/i/file.txt'
Операции с файлами
Файловые потоки
// Открыть локальный файл:
$resource = fopen(‘/path/to/file.txt’, ‘r’);
// Открыть удаленный файл по протоколу HTTP:
// файл загружается по протоколу HTTP и доступен как локальный:
$resource = fopen(‘http://example.com/file.txt’, ‘r’);
// Дескриптор потока в общем виде:
$resource = fopen(‘{PROTOCOL}://{PATH}[?{QUERY}]’, ‘r’);
Потоковая Обвертка
class StreamWrapper
{
public function stream_open($path, $mode, $options, &$openedPath) {}
public function stream_close() {}
public function stream_eof() {}
public function stream_read($count) {}
public function stream_write($data) {}
}
stream_wrapper_register(‘foo’, StreamWrapper::class, STREAM_IS_URL);
Примеры
// Потоковая обвертка для протокола HTTP:
$resource = fopen(‘http://example.com/file.txt’, ‘r’);
// Потоковая обвертка для протокола FTP:
$resource = fopen(‘ftp://user:password@example.com/file.txt’, ‘r’);
// Потоковая обвертка для протокола SFTP:
$resource = fopen(‘ssh2.sftp://1234file.txt’, ‘r’);
// Потоковая обвертка для MongoDB GridFS:
$resource = fopen(‘gridfs://mydatabase.fs?filename=file.txt’, ‘r’);
// Потоковая обвертка для Amazon S3:
$resource = fopen(‘s3://bucket-name/file.txt’, ‘r’);
$bucket = Yii::$app->fileStorage->getBucket('tempFiles');
// открытие дескриптора потока:
$resource = $bucket->openFile(‘file.dat’, ‘r’);
while (!feof($resource)) {
echo fread($resource, 1024);
}
fclose($resource);
Обработка больших файлов
Максимальное количество файлов в
одном каталоге
• Для «старых» файловых систем (FAT) –
65 000
• Для современных (NTFS) теоретическое
– 4 294 967 295
• Практическое (без существенной потери
производительности) – 50 000..100 000
Шаблон под-каталога
return [
'components' => [
'fileStorage' => [
'class' => 'yii2techfilestoragelocalStorage',
'buckets' => [
‘item' => [
'fileSubDirTemplate' => '{^name}/{^^name}',
],
]
// ...
];
$bucket = Yii::$app->fileStorage->getBucket(‘item');
$bucket->saveFileContent('foo.txt', 'Foo content');
// реальное имя файла - ‘f/o/foo.txt’
Связывание файлов с сущностями БД
Item
id
…
fileExtension
fileVersion
Имя файла
Сохранение
mime-типа
Чтобы
обмануть кэш
браузера
Расширение «yii2tech/ar-file»
"yii2tech/file-storage"
FileBehavior
“attached behavior”
Item
1
1
fileStorage
fileBucket
“consists of”
1
*
$fileAttribute
“read / write
file”
"yii2tech/ar-file"
class Item extends yiidbActiveRecord
{
public function behaviors()
{
return [
‘file’ => [
'class' => FileBehavior::class,
‘fileStorageBucket' => ‘item',
‘fileExtensionAttribute' => ‘fileExtension',
‘fileVersionAttribute' => ‘fileVersion',
]
];
}
}
Конфигурация «FileBehavior»
use yiiwebUploadedFile;
$model = Item::findOne(1);
$model->file = UploadedFile::getInstance($model, 'file');
$model->save();
var_dump($model->fileExists()); // выводит `true`
Сохранение файлов
{
“name”: “John Doe”,
“email”: “johndoe@example.com”,
“address” : {
“city”: “Houston”,
“region”: “Texas”,
},
“comments”: [
{
“date”: “2016-11-26 08:16:11”,
“content”: “Hello World”
},
…
]
}
Комплексные записи
Вложенные модели
User
$name
$email
1“has address”
1
1
Address
$city
$region
Comment
$date
$content
mongodbActiveRecord
“has comments”
*
Model
Расширение «yii2tech/embedded»
"yii2tech/embedded"
User
1
ContainerTrait
*
Container
Interface
Mapping
Address
“Declare and
store”
Comment
“Satisfy
interface”
class User extends ActiveRecord implements ContainerInterface
{
use ContainerTrait;
public function embedAddressModel()
{
return $this->mapEmbedded(‘address', Address::class);
}
public function embedCommentModels()
{
return $this->mapEmbeddedList('comments', Comment::class);
}
}
Объявление вложенных объектов
$user = new User();
// Заполнение одиночного вложенного объекта:
$user->addressModel->city = ‘Houston';
$user->addressModel->region = ‘Texas';
// Заполнение списка:
$comment = new Comment();
$comment->content = ‘New comment’;
$user->comments[] = $comment;
// Синхронизация данных:
$user->refreshFromEmbedded();
var_dump($user->address); // выводит массив:
// ['city' => 'Houston', 'region' => 'Texas']
Доступ к вложенным объектам
События и поведения
Component
trigger()
attachBehavior()
$events
$behaviors
Behavior
events()
$owner
1
*
Event
$sender
1 1
* *
“Trigger” “Handle”
Handler
PHP
Callback
*
1
*
1
“Handle event” “Declare event handler”
1 *
“Has behavior”
“Has owner”
class User extends yiidbActiveRecord
{
public function behaviors()
{
return [
‘timestamp’ => [
'class' => TimestampBehavior::class,
// обрабатывает только 2 собыития:
// - `beforeInsert`
// - `beforeUpdate`
]
];
}
}
Конфигурация «TimestampBehavior»
$user = new User(); // срабатывает событие `init`
// поведения проинициализированы!
$models = User::find()->all(); // срабатывает событие `afterFind`
// поведения проинициализированы!
unset($models); // объекты НЕ разрушены!
gc_collect_cycles(); // принудительная сборка мусора
// только теперь объекты разрушены
Инициализация и разрушение
поведений
class User extends yiidbActiveRecord
{
public function init()
{
// «прыжок» через родителя
// убираем событие «init»
yiibaseModel::init();
}
public function afterFind()
{
// нет вызова родительской реализации
// убираем событие «afterFind»
}
}
Устранение «лишних» событий
$user = new User(); // нет события `init`
// поведения НЕ проинициализированы!
$models = User::find()->all(); // нет события `afterFind`
// поведения НЕ проинициализированы!
unset($models); // объекты разрушены!
echo gc_collect_cycles(); // выводит `0`
$user->save(); // событие `beforeInsert`
// поведения проинициализированы!
Отложенная инициализация
поведений
Расширение «yii2tech/behavior-trait»
User BehaviorTrait
ActiveRecord
“Allow usage of
inline methods as
event handlers”
TimestampTrait
“Add particular event
handler”
class User extends yiidbActiveRecord
{
use BehaviorTrait;
use TimestampTrait;
}
trait TimestampTrait
{
// Имя обработчика: «{событие}Handler{суффикс}»
// Обработка события «beforeInsert»
public function beforeInsertHandlerTimestamp($event)
{
$this->createdAt = time();
}
}
Использование «BehaviorTrait»
Примеры решения типичных задач за
рамками ядра Yii2
• Интернационализация в БД
• Роли в реляционных БД
• Абстракция файлового хранилища
• Связывание файлов с записями в БД
• Вложенные модели
• Trait вместо Behavior
http://www.yiiframework.com/
https://github.com/yii2tech

More Related Content

What's hot

Почему Mojolicious?
Почему Mojolicious?Почему Mojolicious?
Почему Mojolicious?
Anatoly Sharifulin
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoMagecom Ukraine
 
Laravel 4 fwdays
Laravel 4 fwdaysLaravel 4 fwdays
Laravel 4 fwdays
Evgeniy Kosinskiy
 
Industrial Programming Java - Lection Pack 01 - Building an application - Lav...
Industrial Programming Java - Lection Pack 01 - Building an application - Lav...Industrial Programming Java - Lection Pack 01 - Building an application - Lav...
Industrial Programming Java - Lection Pack 01 - Building an application - Lav...
Fedor Lavrentyev
 
Perl 5.10 и 5.12
Perl 5.10 и 5.12Perl 5.10 и 5.12
Perl 5.10 и 5.12
Andrew Shitov
 
Perl: Symbol table
Perl: Symbol tablePerl: Symbol table
Perl: Symbol table
Elena Shishkina
 
Организация работы с API на Vue.js, Виталий Копачёв
Организация работы с API на Vue.js, Виталий КопачёвОрганизация работы с API на Vue.js, Виталий Копачёв
Организация работы с API на Vue.js, Виталий Копачёв
Mail.ru Group
 
Yii2
Yii2Yii2
Yii2
Noveo
 
Yii 2. Что нового?
Yii 2. Что нового?Yii 2. Что нового?
Yii 2. Что нового?
yiiconf
 
YiiConf 2012 - Alexander Makarov - Yii2, что нового
YiiConf 2012 - Alexander Makarov - Yii2, что новогоYiiConf 2012 - Alexander Makarov - Yii2, что нового
YiiConf 2012 - Alexander Makarov - Yii2, что новогоAlexander Makarov
 
Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavren...
Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavren...Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavren...
Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavren...
Fedor Lavrentyev
 
FileAPI 2.0
FileAPI 2.0FileAPI 2.0
Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2
Ilyas Salikhov
 
"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс
it-people
 
UWDC 2013, Yii2
UWDC 2013, Yii2UWDC 2013, Yii2
UWDC 2013, Yii2
Alexander Makarov
 
10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)
Roman Brovko
 
2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock
Bohdan Danyliuk
 
Web осень 2012 лекция 4
Web осень 2012 лекция 4Web осень 2012 лекция 4
Web осень 2012 лекция 4Technopark
 
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в MagentoMagecom Ukraine
 
Web весна 2012 лекция 9
Web весна 2012 лекция 9Web весна 2012 лекция 9
Web весна 2012 лекция 9Technopark
 

What's hot (20)

Почему Mojolicious?
Почему Mojolicious?Почему Mojolicious?
Почему Mojolicious?
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в Magento
 
Laravel 4 fwdays
Laravel 4 fwdaysLaravel 4 fwdays
Laravel 4 fwdays
 
Industrial Programming Java - Lection Pack 01 - Building an application - Lav...
Industrial Programming Java - Lection Pack 01 - Building an application - Lav...Industrial Programming Java - Lection Pack 01 - Building an application - Lav...
Industrial Programming Java - Lection Pack 01 - Building an application - Lav...
 
Perl 5.10 и 5.12
Perl 5.10 и 5.12Perl 5.10 и 5.12
Perl 5.10 и 5.12
 
Perl: Symbol table
Perl: Symbol tablePerl: Symbol table
Perl: Symbol table
 
Организация работы с API на Vue.js, Виталий Копачёв
Организация работы с API на Vue.js, Виталий КопачёвОрганизация работы с API на Vue.js, Виталий Копачёв
Организация работы с API на Vue.js, Виталий Копачёв
 
Yii2
Yii2Yii2
Yii2
 
Yii 2. Что нового?
Yii 2. Что нового?Yii 2. Что нового?
Yii 2. Что нового?
 
YiiConf 2012 - Alexander Makarov - Yii2, что нового
YiiConf 2012 - Alexander Makarov - Yii2, что новогоYiiConf 2012 - Alexander Makarov - Yii2, что нового
YiiConf 2012 - Alexander Makarov - Yii2, что нового
 
Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavren...
Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavren...Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavren...
Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavren...
 
FileAPI 2.0
FileAPI 2.0FileAPI 2.0
FileAPI 2.0
 
Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2
 
"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс
 
UWDC 2013, Yii2
UWDC 2013, Yii2UWDC 2013, Yii2
UWDC 2013, Yii2
 
10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)
 
2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock
 
Web осень 2012 лекция 4
Web осень 2012 лекция 4Web осень 2012 лекция 4
Web осень 2012 лекция 4
 
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в Magento
 
Web весна 2012 лекция 9
Web весна 2012 лекция 9Web весна 2012 лекция 9
Web весна 2012 лекция 9
 

Viewers also liked

Yii Academy - Rest APIs
Yii Academy - Rest APIsYii Academy - Rest APIs
Yii Academy - Rest APIs
Kilderson Sena
 
WebCamp 2016: PHP. Дмитрий Науменко: Рецепты для Yii2.
WebCamp 2016: PHP. Дмитрий Науменко: Рецепты для Yii2.WebCamp 2016: PHP. Дмитрий Науменко: Рецепты для Yii2.
WebCamp 2016: PHP. Дмитрий Науменко: Рецепты для Yii2.
WebCamp
 
Кортунов Никита. Как ускорить разработку приложений или есть ли жизнь после P...
Кортунов Никита. Как ускорить разработку приложений или есть ли жизнь после P...Кортунов Никита. Как ускорить разработку приложений или есть ли жизнь после P...
Кортунов Никита. Как ускорить разработку приложений или есть ли жизнь после P...
AvitoTech
 
Вадим Дробинин. Защищаем себя и пользователей: руководство по безопасности
Вадим Дробинин. Защищаем себя и пользователей: руководство по безопасностиВадим Дробинин. Защищаем себя и пользователей: руководство по безопасности
Вадим Дробинин. Защищаем себя и пользователей: руководство по безопасности
AvitoTech
 
Андрей Юткин. Media Picker — to infinity and beyond
Андрей Юткин. Media Picker — to infinity and beyondАндрей Юткин. Media Picker — to infinity and beyond
Андрей Юткин. Media Picker — to infinity and beyond
AvitoTech
 
TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma
Badoo Development
 
TechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, ErlyvideoTechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, Erlyvideo
Badoo Development
 
TechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, BadooTechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, Badoo
Badoo Development
 
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruTechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
Badoo Development
 

Viewers also liked (9)

Yii Academy - Rest APIs
Yii Academy - Rest APIsYii Academy - Rest APIs
Yii Academy - Rest APIs
 
WebCamp 2016: PHP. Дмитрий Науменко: Рецепты для Yii2.
WebCamp 2016: PHP. Дмитрий Науменко: Рецепты для Yii2.WebCamp 2016: PHP. Дмитрий Науменко: Рецепты для Yii2.
WebCamp 2016: PHP. Дмитрий Науменко: Рецепты для Yii2.
 
Кортунов Никита. Как ускорить разработку приложений или есть ли жизнь после P...
Кортунов Никита. Как ускорить разработку приложений или есть ли жизнь после P...Кортунов Никита. Как ускорить разработку приложений или есть ли жизнь после P...
Кортунов Никита. Как ускорить разработку приложений или есть ли жизнь после P...
 
Вадим Дробинин. Защищаем себя и пользователей: руководство по безопасности
Вадим Дробинин. Защищаем себя и пользователей: руководство по безопасностиВадим Дробинин. Защищаем себя и пользователей: руководство по безопасности
Вадим Дробинин. Защищаем себя и пользователей: руководство по безопасности
 
Андрей Юткин. Media Picker — to infinity and beyond
Андрей Юткин. Media Picker — to infinity and beyondАндрей Юткин. Media Picker — to infinity and beyond
Андрей Юткин. Media Picker — to infinity and beyond
 
TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma
 
TechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, ErlyvideoTechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, Erlyvideo
 
TechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, BadooTechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, Badoo
 
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruTechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
 

Similar to Примеры решения типичных задач за рамками ядра Yii2

PHP Advanced
PHP AdvancedPHP Advanced
PHP Advanced
Noveo
 
Что нового в PHP-5.3
Что нового в PHP-5.3 Что нового в PHP-5.3
Что нового в PHP-5.3 phpclub
 
Разработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PIРазработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PI
Ilya Chesnokov
 
Yii: миграции и инсталляции
Yii: миграции и инсталляцииYii: миграции и инсталляции
Yii: миграции и инсталляции
Paul Klimov
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
PVasili
 
Чуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОПЧуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОП
Kirill Chebunin
 
I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jqueryITmozg
 
Nginx.pm
Nginx.pmNginx.pm
Nginx.pm
Ilya Zelenchuk
 
DevConf 2012 - Yii, его разработка и Yii2
DevConf 2012 - Yii, его разработка и Yii2DevConf 2012 - Yii, его разработка и Yii2
DevConf 2012 - Yii, его разработка и Yii2Alexander Makarov
 
PHP7 - что ожидать?
PHP7 - что ожидать?PHP7 - что ожидать?
PHP7 - что ожидать?
Дмитрий Золотов
 
Алексей Плеханов: 25 причин попробовать Laravel
Алексей Плеханов: 25 причин попробовать LaravelАлексей Плеханов: 25 причин попробовать Laravel
Алексей Плеханов: 25 причин попробовать Laravel
Oleg Poludnenko
 
О безопасном использовании PHP wrappers
О безопасном использовании PHP wrappersО безопасном использовании PHP wrappers
О безопасном использовании PHP wrappersPositive Hack Days
 
Behat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и MinkBehat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и Minktyomo4ka
 
PHP basic
PHP basicPHP basic
PHP basic
Noveo
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf Conference
 
plwww (24.03) MEPHI (PHDays)
plwww (24.03) MEPHI (PHDays)plwww (24.03) MEPHI (PHDays)
plwww (24.03) MEPHI (PHDays)ygoltsev
 
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
Technopark
 

Similar to Примеры решения типичных задач за рамками ядра Yii2 (20)

PHP Advanced
PHP AdvancedPHP Advanced
PHP Advanced
 
Что нового в PHP-5.3
Что нового в PHP-5.3 Что нового в PHP-5.3
Что нового в PHP-5.3
 
Разработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PIРазработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PI
 
Yii: миграции и инсталляции
Yii: миграции и инсталляцииYii: миграции и инсталляции
Yii: миграции и инсталляции
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
 
Чуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОПЧуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОП
 
I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jquery
 
Nginx.pm
Nginx.pmNginx.pm
Nginx.pm
 
DevConf 2012 - Yii, его разработка и Yii2
DevConf 2012 - Yii, его разработка и Yii2DevConf 2012 - Yii, его разработка и Yii2
DevConf 2012 - Yii, его разработка и Yii2
 
PHP7 - что ожидать?
PHP7 - что ожидать?PHP7 - что ожидать?
PHP7 - что ожидать?
 
Алексей Плеханов: 25 причин попробовать Laravel
Алексей Плеханов: 25 причин попробовать LaravelАлексей Плеханов: 25 причин попробовать Laravel
Алексей Плеханов: 25 причин попробовать Laravel
 
О безопасном использовании PHP wrappers
О безопасном использовании PHP wrappersО безопасном использовании PHP wrappers
О безопасном использовании PHP wrappers
 
Behat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и MinkBehat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и Mink
 
Yserver
YserverYserver
Yserver
 
PHP basic
PHP basicPHP basic
PHP basic
 
DBIx Class
DBIx ClassDBIx Class
DBIx Class
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
 
plwww (24.03) MEPHI (PHDays)
plwww (24.03) MEPHI (PHDays)plwww (24.03) MEPHI (PHDays)
plwww (24.03) MEPHI (PHDays)
 
Render API.
Render API.Render API.
Render API.
 
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
 

Примеры решения типичных задач за рамками ядра Yii2

  • 1. Примеры решения типичных задач за рамками ядра Yii2 QuartSoft YiiSoft Климов П.В.
  • 3. Интернационализация сущностей в базе данных Item n id canonicalName price Language id name locale Translation n itemId languageId name description
  • 5. class Item extends yiidbActiveRecord { public function behaviors() { return [ ‘translations’ => [ 'class' => VariationBehavior::class, 'variationsRelation' => 'translations', 'variationOptionReferenceAttribute' => 'languageId', 'optionModelClass' => Language::class, ] ]; } public function getTranslations() { return $this->hasMany(ItemTranslation::class, [‘itemId' => 'id']); } } Конфигурация «VariationBehavior»
  • 6. $model = new Item(); // `getVariationModels()` возвращает список моделей-вариаций $variations = $model->getVariationModels(); // их количество всегда равно количеству доступных опций: var_dump(count($variations) == Language::find()->count()); // `true` // валидация и сохранение производятся автоматически: $post = Yii::$app->request->post(); if ($model->load($post) && Model::loadMultiple($model->getVariationModels(), $post) && $model->save()) { return $this->redirect(['index']); } Управление вариаторами
  • 7. class Item extends yiidbActiveRecord { public function behaviors() { return [ ‘translations’ => [ // … 'defaultVariationRelation' => 'defaultTranslation', 'defaultVariationOptionReference' => function () { return Yii::$app->language; // ID опции по умолчанию }, 'variationAttributeDefaultValueMap' => [ ‘name' => ‘canonicalName‘ // fallback для атрибутов вариатора ], ] ]; } public function getDefaultTranslation() { return $this->hasDefaultVariationRelation(); // `has many` -> `has one` } } Вариация «по умолчанию»
  • 8. class VariationBehavior extends yiibaseBehavior { public function __get($name) { try { return parent::__get($name); } catch (yiibaseUnknownPropertyException $e) { return $this->getDefaultVariationModel()->{$name}; } } public function __set($name, $value) {…} public function canGetProperty($name, $checkVars = true) {…} public function canSetProperty($name, $checkVars = true) {…} } Добавление виртуальных свойств «хозяину» поведения
  • 9. $model = Item::find()->one(); echo $model->name; // вернет `$model->defaultTranslation->name` // а если `defaultTranslation` не найдено, то `$model->canonicalName` // Задание нового значения: $model->name = ‘New translation name’; // «Жадная» загрузка: $models = Item::find()->with(‘defaultTranslation’)->all(); foreach ($models as $model) { echo $model->name; } Прямой доступ к атрибутам вариатора
  • 10. Сущности с общими атрибутами Преподаватель Студент - Ученая степень - Зарплата - ФИО - Паспорт - Адрес - Телефон - Учебная группа - Стипендия
  • 11. Роли в реляционной базе данных Person id name address phone Student personId studyGroupId scolarship Instructor personId rankId salary
  • 12. Роли в реляционной базе данных Person 1 id name address phone Student personId studyGroupId scolarship Can be 1 Instructor personId rankId salary Can be 1 1
  • 14. class Student extends yiidbActiveRecord { public function behaviors() { return [ ‘translations’ => [ 'class' => RoleBehavior::class, ‘roleRelation' => ‘person', ] ]; } public function getPerson() { return $this->hasOne(Person::class, [‘id' => ‘personId']); } } Конфигурация «RoleBehavior»
  • 15. class RoleBehavior extends yiibaseBehavior { public function __get($name) { try { return parent::__get($name); } catch (yiibaseUnknownPropertyException $e) { return $this->getRoleRelationModel()->{$name}; } } public function __call($name, $params) { $model = $this->getRoleRelationModel(); if ($model->hasMethod($name)) { return call_user_func_array([$model, $name], $params); } return parent::__call($name, $params); } } Эмуляция наследования
  • 16. $model = Student::find()->one(); echo $model->name; // вернет `$model->person->name` // Задание нового значения: $model->name = ‘John Doe’; // валидация и сохранение производятся автоматически: $model->save(); // вызов `$model->person->save()` $model->locateAddress(); // вызов `$model->person->locateAddress()` // «Жадная» загрузка: $models = Student::find()->with(‘person’)->all(); foreach ($models as $model) { echo $model->name; } Прямой доступ к атрибутам роли
  • 19. Централизованное файловое хранилище Client Load Balancer Regular HTTP requests Web Server 1 Web Server 2 Internal HTTP requests File Server FTP / SFTP / REST FTP / SFTP / REST
  • 20. Абстракция файловой системы sftpStorage fileStorage $buckets getBucket() “consists of” 1 * fileBucket saveFileContent() getFileContent() localStorage sftpBucket localBucket Client “file r/w”
  • 21. $bucket = Yii::$app->fileStorage->getBucket('tempFiles'); // создать файл с заданным содержимым: $bucket->saveFileContent('foo.txt', 'Foo content'); // удалить файл: $bucket->deleteFile('foo.txt'); // скопировать файл в хранилище: $bucket->copyFileIn('/path/to/source/file.txt', 'file.txt'); // скопировать файл из хранилища: $bucket->copyFileOut('file.txt', '/path/to/destination/file.txt'); var_dump($bucket->fileExists('file.txt')); // выводит `true` echo $bucket->getFileUrl('file.txt'); // выводит: // http://domain.com/files/f/i/file.txt' Операции с файлами
  • 22. Файловые потоки // Открыть локальный файл: $resource = fopen(‘/path/to/file.txt’, ‘r’); // Открыть удаленный файл по протоколу HTTP: // файл загружается по протоколу HTTP и доступен как локальный: $resource = fopen(‘http://example.com/file.txt’, ‘r’); // Дескриптор потока в общем виде: $resource = fopen(‘{PROTOCOL}://{PATH}[?{QUERY}]’, ‘r’);
  • 23. Потоковая Обвертка class StreamWrapper { public function stream_open($path, $mode, $options, &$openedPath) {} public function stream_close() {} public function stream_eof() {} public function stream_read($count) {} public function stream_write($data) {} } stream_wrapper_register(‘foo’, StreamWrapper::class, STREAM_IS_URL);
  • 24. Примеры // Потоковая обвертка для протокола HTTP: $resource = fopen(‘http://example.com/file.txt’, ‘r’); // Потоковая обвертка для протокола FTP: $resource = fopen(‘ftp://user:password@example.com/file.txt’, ‘r’); // Потоковая обвертка для протокола SFTP: $resource = fopen(‘ssh2.sftp://1234file.txt’, ‘r’); // Потоковая обвертка для MongoDB GridFS: $resource = fopen(‘gridfs://mydatabase.fs?filename=file.txt’, ‘r’); // Потоковая обвертка для Amazon S3: $resource = fopen(‘s3://bucket-name/file.txt’, ‘r’);
  • 25. $bucket = Yii::$app->fileStorage->getBucket('tempFiles'); // открытие дескриптора потока: $resource = $bucket->openFile(‘file.dat’, ‘r’); while (!feof($resource)) { echo fread($resource, 1024); } fclose($resource); Обработка больших файлов
  • 26. Максимальное количество файлов в одном каталоге • Для «старых» файловых систем (FAT) – 65 000 • Для современных (NTFS) теоретическое – 4 294 967 295 • Практическое (без существенной потери производительности) – 50 000..100 000
  • 27. Шаблон под-каталога return [ 'components' => [ 'fileStorage' => [ 'class' => 'yii2techfilestoragelocalStorage', 'buckets' => [ ‘item' => [ 'fileSubDirTemplate' => '{^name}/{^^name}', ], ] // ... ]; $bucket = Yii::$app->fileStorage->getBucket(‘item'); $bucket->saveFileContent('foo.txt', 'Foo content'); // реальное имя файла - ‘f/o/foo.txt’
  • 28. Связывание файлов с сущностями БД Item id … fileExtension fileVersion Имя файла Сохранение mime-типа Чтобы обмануть кэш браузера
  • 30. class Item extends yiidbActiveRecord { public function behaviors() { return [ ‘file’ => [ 'class' => FileBehavior::class, ‘fileStorageBucket' => ‘item', ‘fileExtensionAttribute' => ‘fileExtension', ‘fileVersionAttribute' => ‘fileVersion', ] ]; } } Конфигурация «FileBehavior»
  • 31. use yiiwebUploadedFile; $model = Item::findOne(1); $model->file = UploadedFile::getInstance($model, 'file'); $model->save(); var_dump($model->fileExists()); // выводит `true` Сохранение файлов
  • 32. { “name”: “John Doe”, “email”: “johndoe@example.com”, “address” : { “city”: “Houston”, “region”: “Texas”, }, “comments”: [ { “date”: “2016-11-26 08:16:11”, “content”: “Hello World” }, … ] } Комплексные записи
  • 35. class User extends ActiveRecord implements ContainerInterface { use ContainerTrait; public function embedAddressModel() { return $this->mapEmbedded(‘address', Address::class); } public function embedCommentModels() { return $this->mapEmbeddedList('comments', Comment::class); } } Объявление вложенных объектов
  • 36. $user = new User(); // Заполнение одиночного вложенного объекта: $user->addressModel->city = ‘Houston'; $user->addressModel->region = ‘Texas'; // Заполнение списка: $comment = new Comment(); $comment->content = ‘New comment’; $user->comments[] = $comment; // Синхронизация данных: $user->refreshFromEmbedded(); var_dump($user->address); // выводит массив: // ['city' => 'Houston', 'region' => 'Texas'] Доступ к вложенным объектам
  • 37. События и поведения Component trigger() attachBehavior() $events $behaviors Behavior events() $owner 1 * Event $sender 1 1 * * “Trigger” “Handle” Handler PHP Callback * 1 * 1 “Handle event” “Declare event handler” 1 * “Has behavior” “Has owner”
  • 38. class User extends yiidbActiveRecord { public function behaviors() { return [ ‘timestamp’ => [ 'class' => TimestampBehavior::class, // обрабатывает только 2 собыития: // - `beforeInsert` // - `beforeUpdate` ] ]; } } Конфигурация «TimestampBehavior»
  • 39. $user = new User(); // срабатывает событие `init` // поведения проинициализированы! $models = User::find()->all(); // срабатывает событие `afterFind` // поведения проинициализированы! unset($models); // объекты НЕ разрушены! gc_collect_cycles(); // принудительная сборка мусора // только теперь объекты разрушены Инициализация и разрушение поведений
  • 40. class User extends yiidbActiveRecord { public function init() { // «прыжок» через родителя // убираем событие «init» yiibaseModel::init(); } public function afterFind() { // нет вызова родительской реализации // убираем событие «afterFind» } } Устранение «лишних» событий
  • 41. $user = new User(); // нет события `init` // поведения НЕ проинициализированы! $models = User::find()->all(); // нет события `afterFind` // поведения НЕ проинициализированы! unset($models); // объекты разрушены! echo gc_collect_cycles(); // выводит `0` $user->save(); // событие `beforeInsert` // поведения проинициализированы! Отложенная инициализация поведений
  • 42. Расширение «yii2tech/behavior-trait» User BehaviorTrait ActiveRecord “Allow usage of inline methods as event handlers” TimestampTrait “Add particular event handler”
  • 43. class User extends yiidbActiveRecord { use BehaviorTrait; use TimestampTrait; } trait TimestampTrait { // Имя обработчика: «{событие}Handler{суффикс}» // Обработка события «beforeInsert» public function beforeInsertHandlerTimestamp($event) { $this->createdAt = time(); } } Использование «BehaviorTrait»
  • 44. Примеры решения типичных задач за рамками ядра Yii2 • Интернационализация в БД • Роли в реляционных БД • Абстракция файлового хранилища • Связывание файлов с записями в БД • Вложенные модели • Trait вместо Behavior http://www.yiiframework.com/ https://github.com/yii2tech