[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: ActiveRecord в боевом применении.
Страницы: 1, 2, 3, 4, 5, 6
twin
Santehnick Спасибо.
Цитата (Santehnick @ 5.04.2018 - 08:34)
P/S Советую это всё изучать на пет-проекте. От простого к сложному. Не надо без опыта пытаться применить доменную модель на рабочем проекте. Зафакапишь все сроки или за пару дней до дедлайна будешь делать как попало лишь бы работало и в итоге сделаешь еще хуже, чем без неё.
Да там не жестко со сроками. Друг попросил. Безвозмездно))) Сайт работает, он просто хочет ребрендинга. smile.gif Так что совмещаю полезное с приятным.

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
twin
Разобрался я наконец то с этими луковицами. Раз нашему всезнайке не понравилась луковица от анкл Боба (жаль Ron не слышал biggrin.gif ), нарисую иначе. Кому интересно, вот кстати чем навеяло. Луковица действительно лучше воспринимается после того, как развернута в линию. Хотя сама по себе суть отражает лучше.

В двух словах что тут.

Тут пока два слоя, чтоб не путаться. Потому что третий слой пока не нужен. Это как в CQRS часть read, только всё же на AR. Потому что изначалная задача - испытать её в действии. Кроме того, померла, так померла. Что бы небыло соблазна использовать чистый SQL.

Первый слой - фреймворк. Тут думаю пояснять ничего не нужно.

Внутренний слой - доменная модель. Делится на службы и сущности. Службы (или юзеркейсы) описывают сценарии модели, сущности разыгрывают представление.

По идее между ними должен быть еще один слой - приложение. Но его нет, так как делать его ради того, чтоб былО - не в моих правилах. Он понадобится позже, когда начнутся мутации, транзакции и прочая "нестабильность". smile.gif В этом слое будут находиться шины, команды, адаптеры и почие связующие (вернее разделители) между фреймворком и моделью.

Примерно так:

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
twin
Ну и код теперь такой.

Теперь почти вся бизнес-логика находится в сущностях. Там теперь обрабатываются объекты модели, а в обработчик возвращается колекция (массив) DTO. Туда же, в сущность, прокидывается калькуллятор, и там же идет перерасчет стоимости.

Собственно на обработчик CatalogueHandler возлагается обязанность инициировать агрегаты из продукта и акций, и отравить результат наружу.

Неймспейс теперь Shop, так как каталог, это модуль магазина. По сути контекст. Так удобнее располагать это все в файловой системе.

И последний момент. Метод не зря назван process(). Ну во первых это внешний интерфейс с претензией на универсальность. А во вторых для корреляции с мидлварами, кои в изобилии присутствуют в моей поделке. :)

Итак. Элементарнейший юзеркейс.
<?php 

namespace App\Models\Shop;

use App\Models\Shop\Product;

/**
* Shop
*
*/

class CatalogueReader
{
protected $calculator;

public function __construct()
{
$this->calculator = new Calculator;
}

/**
* Генерируем список продуктов
*
*
@return array
*/

public function process()
{
$products = Product::find()->with(
[
'promotion' => function ($query) {
return $query->andWhere(['<=', 'date_start','NOW()'])
->
andWhere(['>=', 'date_end', 'NOW()']);
}])
->
order('priority');

return $products->getCatalogue($this->calculator);
}
}




И сущность
<?php 

namespace App\Models\Shop;

use ABC\Core\ActiveRecord\Model;

/**
* Shop
*
*/

class Product extends Model
{
protected function getPromotion()
{
return $this->belongsTo(Promotion::class);
}


/**
*
*
*
@return object
*/

public function getCatalogue(calculator $calculator)
{
$products = $this->all();

foreach ($products as $product) {
$price = $this->calculatePrice($product, $calculator);
$product->newPrice = $price;
$collect[] = $product->asDTO();
}

return $collect;
}

/**
* Вычисляем цену с учетом скидки
*
*
@return float
*/

protected function calculatePrice($product, $calculator)
{
if (!is_object($product->promotion)) {
return $product->price;
}

$discount = $product->promotion->discount;
return $calculator->createPrice($product->price, $discount);
}
}


Остальное малозначительно. Вот что получается на выходе:
array (
[0] => ABC\Core\ActiveRecord\DTO object (
[id] => 1
[promotion_id] => 1
[name] => Тандыр большой «Премиум»
[description] =>
[price] => 10000.00
[photo] =>
[priority] => 1
[newPrice] => 8000
)

[1] => ABC\Core\ActiveRecord\DTO object (
[id] => 2
[promotion_id] =>
[name] => Тандыр Большой «Семейный»
[description] =>
[price] => 30000.00
[photo] =>
[priority] => 2
[newPrice] => 30000.00
)

[2] => ABC\Core\ActiveRecord\DTO object (
[id] => 3
[promotion_id] => 2
[name] => Тандыр Средний «Дачный»
[description] =>
[price] => 40000.00
[photo] =>
[priority] => 3
[newPrice] => 20000
)

Вроде бы ничего не нарушил. Принципы имею ввиду. Реализация - дело второе. :)

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.