Если он работает в одиночку, то проще отказаться от AR. Если он работает в команде, то нужно как-то это объяснить команде. С этим уже сложнее, поскольку со стороны такие манипуляции выглядят глупо.Почему не получится?
1) Обычным способом выделить aggregate roots, создавать их фабриками
2) В репозиториях загружать aggregate roots с полным набором with(), и сохранять так же целиком
3) Извне игнорировать наличие eloquent-методов, как будто их нет
interface PayementGatewayAdapter{
public function getPaymentStatus($transaction_id);
}
class YandexKassa implements PayementGatewayAdapter{
public function getPaymentStatus($transaction_id){
return true;
}
}
class RobocassaAdapter implements PayementGatewayAdapter{
public function getPaymentStatus($transaction_id){
//curl requests here
return $result;
}
}
class PaymentAdapterFactory{
/** @return PayementGatewayAdapter */
public static function getPaymentAdapter($type){
return new $type.'Adapter';
}
}
class PaymentStatusChecker{
/** @var PayementGatewayAdapter */
private $adapter;
public function setPaymentAdapter(PayementGatewayAdapter $Adapter){
$this->adapter = $Adapter;
}
public function check(Order $Order){
$status = $this->adapter->getPaymentStatus($Order->getExternalTransactionId());
if (...)
}
}
class Order{
protected $is_paid;
protected $payment_method;
protected $transaction_id;
public function setIsPaid($is_paid){$this->is_paid = $is_paid;}
public function getPaymentMethod(){return $this->payment_method;}
public function getExternalTransactionId(){return $this->transaction_id;}
public static function loadById($id){
//SELECT FROM orders to properties
return new self;
}
}
class OrderProcessor{
public function checkProcessOrder($order_id){
$Order = Order::loadById($order_id);
$Adapter = PaymentAdapterFactory::getPaymentAdapter($Order);
$Checker = new PaymentStatusChecker();
$Checker->setPaymentAdapter($Adapter);
$Checker->check($Order);
// delivery costs accounting, setting order to the packing queue
}
}
class OrderProcessController{
public function processOrderNotification(){
$order_id = $_POST['order_id'];
$processor = new OrderProcessor();
$processor->checkProcessOrder($order_id);
}
}
interface PaymentGateway
{
public function getPaymentStatus(PaymentMethod $method, int $transactionId) : bool;
}
Это признаки процедурного подхода. В ООП это выглядело бы скорее какмодель-проверяльщик ... обновляльщик
class Order
{
public function checkAndPay(PaymentGateway $paymentGateway)
{
if ($paymentGateway->getPaymentStatus($this->payment_method, $this->transaction_id)) {
$this->is_paid = true;
}
}
}
$this->checkPermission($currentRoute, ['model' => $model]);
class AuthorRule extends Rule
{
public $name = 'isAuthor';
/**
* @param string|integer $user the user ID.
* @param Item $item the role or permission that this rule is associated with
* @param array $params parameters passed to ManagerInterface::checkAccess().
* @return boolean a value indicating whether the rule permits the role or permission it is associated with.
*/
public function execute($user, $item, $params)
{
return isset($params['post']) ? $params['post']->createdBy == $user : false;
}
}
1) тут либо раздутый до неприличных размеров базовый конструктор, либо SLчто смущает?
вот финальный вариантПочему не получится?
1) Обычным способом выделить aggregate roots, создавать их фабриками
2) В репозиториях загружать aggregate roots с полным набором with(), и сохранять так же целиком
3) Извне игнорировать наличие eloquent-методов, как будто их нет
//создается обьект формы, в котором вся модель мапится на DTO
$form = $this->formBuilder->create($this->form, $model);
if ($request->isMethod(Request::METHOD_POST)){
//апдейт именно DTO
$form->updateData($request->input());
//валидация DTO
if ($form->validate()){
//сетим DTO в модель, там уже все парсится по бизнес правилам, по сути AggregateRoot со всем говном присущим AR
$model->updateFromDto($form->getData());
...
}
}