Skip to content

Instantly share code, notes, and snippets.

@nanasess
Last active November 28, 2016 07:01
Show Gist options
  • Save nanasess/b213bffe4c8f05390f5c6f91b1568887 to your computer and use it in GitHub Desktop.
Save nanasess/b213bffe4c8f05390f5c6f91b1568887 to your computer and use it in GitHub Desktop.
単価集計の案
<?php
class ShopingController
{
public function confirm(Request $request)
{
// 単価集計
// 集計済みの Order を返す.
// 管理画面でも同じインターフェイスを使用可能
$Order = $app['eccube.service.calculator']->calculate();
$orderService->setOrderUpdate($em, $Order, $formData);
// 在庫情報を更新
$orderService->setStockUpdate($em, $Order);
$paymentService = $app['eccube.service.payment'];
$paymentService->setOrder($Order);
// 支払実行
$paymentMethod = $app['payment.method'];
$paymentMethod->setPayment($Order->getPayment());
$orderResult = $paymentService->doCheckout($paymentMethod);
/** これを関数型言語っぽく書きたい */
$Order = $OrderService->doCheckout(
// これだとプラッガブルではないので、
// プラッガブルにするには Strategy パターンしか思いつかない...
$Calculate
->execute($OrderDetails)
->execute($Shipping)
->execute($Point)
);
if (!$orderResult->isSuccess()) {
// 在庫戻す
$em->getConnection()->rollback();
return $app->redirect($app->url('shopping_error'));
}
return $app->redirect($app->url('shopping_complete'));
}
}
/** カスタマイズ開発者が実装するのはここから */
class PaymentCash implements PaymentMethod
{}
class PaymentBank implements PaymentMethod
{}
class PaymentCreditCard implements PaymentMethod
{
// 決済処理中に在庫情報をロックするのはイケてないので,
// 失敗したら在庫を戻す等の処理が必要
// 画面遷移を伴うものは Delegate する。
// 完了処理は共通化しておく
}
class Coupon implements CalculateStrategy
{
public function execute(array &$OrderDetails)
{
$point = -100;
$OrderDetail = new OrderDetail();
$OrderDetail->setProductName('利用クーポン')
->setPrice($point);
$OrderDetails[] = $OrderDetail;
}
}
class Cart implements CalculateStrategy
{
public function execute(array &$OrderDetails)
{
$point = -100;
$OrderDetail = new OrderDetail();
$OrderDetail->setProductName('利用クーポン')
->setPrice($point);
$OrderDetails[] = $OrderDetail;
}
}
class Batch implements CalculateStrategy
{
public function execute(array &$OrderDetails)
{
$point = -100;
$OrderDetail = new OrderDetail();
$OrderDetail->setProductName('利用クーポン')
->setPrice($point);
$OrderDetails[] = $OrderDetail;
}
}
/**
* 利用ポイント
*/
class UsePoint implements CalculateStrategy
{
public function execute(array &$OrderDetails)
{
$point = -100;
$OrderDetail = new OrderDetail();
$OrderDetail->setProductName('利用ポイント')
->setPrice($point);
$OrderDetails[] = $OrderDetail;
}
}
/**
* 送料計算クラス
*
* @PointCut(Order->total <= 3000)
*/
class Shipping implements CalculateStrategy
{
protected $Pref;
protected $Shippings;
public function execute(array &$OrderDetails)
{
$shipping_fee = 0;
foreach ($Shippings as $Shipping) {
$shipping_fee += $Shipping->getDeliveryFee();
}
$OrderDetail = new OrderDetail();
$OrderDetail->setProductName('送料')
->setPrice($shipping_fee);
$OrderDetails[] = $OrderDetail;
}
}
/** カスタマイズ開発者が実装するのはここまで */
// 今風にやるなら Closure
interface CalculateStrategy
{
public function execute(array $OrderDetails);
}
class CalculateContext
{
protected $Order;
protected $OrderDetails = [];
// $app['eccube.calculate.strategies'] に DI する
protected $CalculateStrategies = [];
public function executeCalculator()
{
foreach ($CalculateStrategies as $Strategy) {
$strategy->execute($this->OrderDetails);
}
return $this->calculateOrder($this->Order, $this->OrderDetails);
}
public function calculateOrder(Order $Order, array $OrderDetails)
{
// OrderDetails の計算結果を Order にセットする
return $Order;
}
}
class CalculateService
{
protected $Customer;
protected $Order;
protected $ProductClasses = [];
protected $Deliveries = [];
protected $Payment;
protected $CalculateContext;
public function addCalculator(CalculateStrategy $strategy)
{
$CalculateContext->CalculateStrategy[] = $strategy;
}
public function calculate()
{
$Order = $CalculateContext->executeCalculator();
return $Order;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment