Laravel有很多关于日期验证的低谷

时间:2018-02-25 03:25:09

标签: php mysql laravel eloquent relational-database

我需要重构我的数据关系,因为包含了日期。我有三种模式:

\App\Product;
discounts()->hasManyThrough('App\Discount', 'App\DiscountProduct', 'product_id','id','id','discount_id');
\App\DiscountProduct;
discount()->belongsTo('App\Discount', 'discount_id');
\App\Discount;
discountProduct()->hasMany('App\DiscountProduct');
  1. discounts_product表:id,discount_id,product_id
  2. 折扣表:id,name,start_date,end_date等。
  3. 产品表:id,名称,价格等
  4. 当我致电$product->with('discounts')时 结果是这样的

    {"id": 1,
     "name": "Wild Blue Shirt",
     "discounts": [{
         "method": "per_product",
         "type": "percentage",
         "nominal": 10,
         "start_date": "2018-03-01 16:34:50", <= this is my problem
         "end_date": "2018-03-31 16:34:50", <= this is my problem
          },...other expired discounts],
    },...other products
    

    我的问题是:如何过滤每种产品的当前(今天)折扣?

    我试过这个:

    \App\DiscountProduct;
    currentDiscount() {
       return $this->belongsTo("App\Discount", 'discount_id')->whereRaw('now() BETWEEN start_date AND end_date');
    };
    

    然后

    $product->with('discounts.currentDiscount'); <= doesn't worked
    

    这对我有用:

    $product_list = $products->with('variants')->with('discounts')->get();
    $product_list->transform(function($product) use ($discounts){
       $data = $product;
       $currentDiscount = collect($product->discounts)->map(function($discount){
           $data = null;
           if($discount['end_date'] > now()){
                $data = $discount;
           };
           return $data;
           });
        $data->currentDiscount = $currentDiscount->filter()->first();
        return $data;
    });
    

    但问题是我无法使用paginate()功能,使用forpage()非常痛苦

    否则这个原始数据库也可以使用:

    $products = DB::table('products')
    ->selectRaw("products.id, products.name, products.price, COALESCE(active_discount.discount_amount,0) AS discount")
    ->leftJoin(DB::raw("(discount_products.product_id, CAST(IF(discounts.`type`='percentage', ROUND((discounts.nominal/100)*products.price,0) ,discounts.nominal) AS UNSIGNED) AS discount_amount FROM discount_products JOIN discounts ON discount_products.discount_id=discounts.id JOIN products ON discount_products.product_id=products.id WHERE NOW() BETWEEN discounts.start_date AND discounts.end_date ) active_discount"),'products.id', '=', 'active_discount.product_id'));
    

    我不认为以上所有方法都是最佳解决方案。请帮忙。

1 个答案:

答案 0 :(得分:0)

我认为您的问题[与分页/等]是因为您正在制作Raw DB请求而不是使用Eloquent。

你可以constrain Eager Loading

  

约束Eager Loads

     

有时您可能希望加载关系,但也要指定   急切加载查询的附加查询约束。这是一个   例如:

$users = App\User::with(['posts' => function ($query) {
    $query->where('title', 'like', '%first%');

}])->get();
     

在这个例子中,Eloquent只会急切地加载帖子的帖子   标题栏包含第一个单词。当然,你可以打电话给其他人   查询构建器方法,以进一步自定义预先加载   操作:

$users = App\User::with(['posts' => function ($query) {
    $query->orderBy('created_at', 'desc');

}])->get();

所以在你的情况下,你可以做(​​没有测试它,但这应该有效):

$product->with(['discounts' => function ($query) {

        $query->where(['start_date' , '<', now()] , ['end_date', '>' , now()]);

        }])->paginate(10);

您也可以直接在关系中在模型中设置它:

public function currentDiscount()
    {
        return $this->belongsTo('App\Discount', 'discount_id')
            ->where(
                ['start_date', '<', now()],
                ['end_date', '>', now()]
            );
    }