在缓存中包装 laravel 查询::remember
Posted
技术标签:
【中文标题】在缓存中包装 laravel 查询::remember【英文标题】:Wrap laravel query inside cache::remember 【发布时间】:2022-01-14 20:31:36 【问题描述】:我想将我的 laravel 查询包装在 cache::remember() 方法中,这不是什么大问题。我的问题是我的查询首先从控制器调用该函数,并且该文件中有一个文件 transaction.php。我正在调用这个函数,在它之后,我在这个函数返回查询的最后放置了一些 where() 条件。最终查询给出结果,我将其传递到 Yajra 数据表中。 简而言之,我的查询不在同一个文件上,因此我可以包装在 cache::remember() 函数中。
我如何包装我的查询,它放在两个文件中,controller 和 transaction.php。希望你能理解。
这是控制器内部的一个函数:
public function index()
$is_admin = $this->businessUtil->is_admin(auth()->user());
if ( !$is_admin && !auth()->user()->hasAnyPermission(['sell.view', 'sell.create', 'direct_sell.access', 'direct_sell.view', 'view_own_sell_only', 'view_commission_agent_sell', 'access_shipping', 'access_own_shipping', 'access_commission_agent_shipping', 'so.view_all', 'so.view_own']) )
abort(403, 'Unauthorized action.');
$business_id = request()->session()->get('user.business_id');
$is_woocommerce = $this->moduleUtil->isModuleInstalled('Woocommerce');
$is_tables_enabled = $this->transactionUtil->isModuleEnabled('tables');
$is_service_staff_enabled = $this->transactionUtil->isModuleEnabled('service_staff');
$is_types_service_enabled = $this->moduleUtil->isModuleEnabled('types_of_service');
if (request()->ajax())
$payment_types = $this->transactionUtil->payment_types(null, true, $business_id);
$with = [];
$shipping_statuses = $this->transactionUtil->shipping_statuses();
$sale_type = !empty(request()->input('sale_type')) ? request()->input('sale_type') : 'sell';
$sells = $this->transactionUtil->getListSells($business_id, $sale_type, request()->customer_id);
$permitted_locations = auth()->user()->permitted_locations();
if ($permitted_locations != 'all')
$sells->whereIn('transactions.location_id', $permitted_locations);
//Add condition for created_by,used in sales representative sales report
if (request()->has('created_by'))
$created_by = request()->get('created_by');
if (!empty($created_by))
$sells->where('transactions.created_by', $created_by);
$partial_permissions = ['view_own_sell_only', 'view_commission_agent_sell', 'access_own_shipping', 'access_commission_agent_shipping'];
if (!auth()->user()->can('direct_sell.access'))
$sells->where( function($q)
if (auth()->user()->hasAnyPermission(['view_own_sell_only', 'access_own_shipping']))
$q->where('transactions.created_by', request()->session()->get('user.id'));
//if user is commission agent display only assigned sells
if (auth()->user()->hasAnyPermission(['view_commission_agent_sell', 'access_commission_agent_shipping']))
$q->orWhere('transactions.commission_agent', request()->session()->get('user.id'));
);
if (!empty(request()->input('payment_status')) && request()->input('payment_status') != 'overdue')
$sells->where('transactions.payment_status', request()->input('payment_status'));
elseif (request()->input('payment_status') == 'overdue')
$sells->whereIn('transactions.payment_status', ['due', 'partial'])
->whereNotNull('transactions.pay_term_number')
->whereNotNull('transactions.pay_term_type')
->whereRaw("IF(transactions.pay_term_type='days', DATE_ADD(transactions.transaction_date, INTERVAL transactions.pay_term_number DAY) < CURDATE(), DATE_ADD(transactions.transaction_date, INTERVAL transactions.pay_term_number MONTH) < CURDATE())");
//Add condition for location,used in sales representative expense report
if (request()->has('location_id'))
$location_id = request()->get('location_id');
if (!empty($location_id))
$sells->where('transactions.location_id', $location_id);
if (!empty(request()->input('rewards_only')) && request()->input('rewards_only') == true)
$sells->where(function ($q)
$q->whereNotNull('transactions.rp_earned')
->orWhere('transactions.rp_redeemed', '>', 0);
);
if (!empty(request()->customer_id))
$customer_id = request()->customer_id;
$sells->where('contacts.id', $customer_id);
if (!empty(request()->start_date) && !empty(request()->end_date))
$start = request()->start_date;
$end = request()->end_date;
$sells->whereDate('transactions.transaction_date', '>=', $start)
->whereDate('transactions.transaction_date', '<=', $end);
//Check is_direct sell
if (request()->has('is_direct_sale'))
$is_direct_sale = request()->is_direct_sale;
if ($is_direct_sale == 0)
$sells->where('transactions.is_direct_sale', 0);
$sells->whereNull('transactions.sub_type');
//Add condition for commission_agent,used in sales representative sales with commission report
if (request()->has('commission_agent'))
$commission_agent = request()->get('commission_agent');
if (!empty($commission_agent))
$sells->where('transactions.commission_agent', $commission_agent);
if ($is_woocommerce)
$sells->addSelect('transactions.woocommerce_order_id');
if (request()->only_woocommerce_sells)
$sells->whereNotNull('transactions.woocommerce_order_id');
if (request()->only_subscriptions)
$sells->where(function ($q)
$q->whereNotNull('transactions.recur_parent_id')
->orWhere('transactions.is_recurring', 1);
);
if (!empty(request()->list_for) && request()->list_for == 'service_staff_report')
$sells->whereNotNull('transactions.res_waiter_id');
if (!empty(request()->res_waiter_id))
$sells->where('transactions.res_waiter_id', request()->res_waiter_id);
if (!empty(request()->input('sub_type')))
$sells->where('transactions.sub_type', request()->input('sub_type'));
if (!empty(request()->input('created_by')))
$sells->where('transactions.created_by', request()->input('created_by'));
if (!empty(request()->input('status')))
$sells->where('transactions.status', request()->input('status'));
if (!empty(request()->input('sales_cmsn_agnt')))
$sells->where('transactions.commission_agent', request()->input('sales_cmsn_agnt'));
if (!empty(request()->input('service_staffs')))
$sells->where('transactions.res_waiter_id', request()->input('service_staffs'));
$only_shipments = request()->only_shipments == 'true' ? true : false;
if ($only_shipments)
$sells->whereNotNull('transactions.shipping_status');
if (!empty(request()->input('shipping_status')))
$sells->where('transactions.shipping_status', request()->input('shipping_status'));
if (!empty(request()->input('for_dashboard_sales_order')))
$sells->whereIn('transactions.status', ['partial', 'ordered'])
->orHavingRaw('so_qty_remaining > 0');
if ($sale_type == 'sales_order')
if (!auth()->user()->can('so.view_all') && auth()->user()->can('so.view_own'))
$sells->where('transactions.created_by', request()->session()->get('user.id'));
if (empty(request()->customer_id))
$sells->groupBy('transactions.id');
if (!empty(request()->suspended))
$transaction_sub_type = request()->get('transaction_sub_type');
if (!empty($transaction_sub_type))
$sells->where('transactions.sub_type', $transaction_sub_type);
else
$sells->where('transactions.sub_type', null);
$with = ['sell_lines'];
if ($is_tables_enabled)
$with[] = 'table';
if ($is_service_staff_enabled)
$with[] = 'service_staff';
$sales = $sells->where('transactions.is_suspend', 1)
->with($with)
->addSelect('transactions.is_suspend', 'transactions.res_table_id', 'transactions.res_waiter_id', 'transactions.additional_notes')
->get();
return view('sale_pos.partials.suspended_sales_modal')->with(compact('sales', 'is_tables_enabled', 'is_service_staff_enabled', 'transaction_sub_type'));
$with[] = 'payment_lines';
if (!empty($with))
$sells->with($with);
//$business_details = $this->businessUtil->getDetails($business_id);
if ($this->businessUtil->isModuleEnabled('subscription'))
$sells->addSelect('transactions.is_recurring', 'transactions.recur_parent_id');
$sales_order_statuses = Transaction::sales_order_statuses();
$datatable = Datatables::of($sells)
->addColumn(
'action',
function ($row) use ($only_shipments, $is_admin, $sale_type)
$html = '<div class="btn-group">
<button type="button" class="btn btn-info dropdown-toggle btn-xs"
data-toggle="dropdown" aria-expanded="false">' .
__("messages.actions") .
'<span class="caret"></span><span class="sr-only">Toggle Dropdown
</span>
</button>
<ul class="dropdown-menu dropdown-menu-left" role="menu">' ;
if (auth()->user()->can("sell.view") || auth()->user()->can("direct_sell.view") || auth()->user()->can("view_own_sell_only"))
$html .= '<li><a href="#" data-href="' . action("SellController@show", [$row->id]) . '" class="btn-modal" data-container=".view_modal"><i class="fas fa-eye" aria-hidden="true"></i> ' . __("messages.view") . '</a></li>';
if (!$only_shipments)
if ($row->is_direct_sale == 0)
if (auth()->user()->can("sell.update"))
$html .= '<li><a target="_blank" href="' . action('SellPosController@edit', [$row->id]) . '"><i class="fas fa-edit"></i> ' . __("messages.edit") . '</a></li>';
elseif ($row->type == 'sales_order')
if (auth()->user()->can("so.update"))
$html .= '<li><a target="_blank" href="' . action('SellController@edit', [$row->id]) . '"><i class="fas fa-edit"></i> ' . __("messages.edit") . '</a></li>';
else
if (auth()->user()->can("direct_sell.update"))
$html .= '<li><a target="_blank" href="' . action('SellController@edit', [$row->id]) . '"><i class="fas fa-edit"></i> ' . __("messages.edit") . '</a></li>';
$delete_link = '<li><a href="' . action('SellPosController@destroy', [$row->id]) . '" class="delete-sale"><i class="fas fa-trash"></i> ' . __("messages.delete") . '</a></li>';
if ($row->is_direct_sale == 0)
if (auth()->user()->can("sell.delete"))
$html .= $delete_link;
elseif ($row->type == 'sales_order')
if (auth()->user()->can("so.delete"))
$html .= $delete_link;
else
if (auth()->user()->can("direct_sell.delete"))
$html .= $delete_link;
if (config('constants.enable_download_pdf') && auth()->user()->can("print_invoice") && $sale_type != 'sales_order')
$html .= '<li><a href="' . route('sell.downloadPdf', [$row->id]) . '" target="_blank"><i class="fas fa-print" aria-hidden="true"></i> ' . __("lang_v1.download_pdf") . '</a></li>';
if (!empty($row->shipping_status))
$html .= '<li><a href="' . route('packing.downloadPdf', [$row->id]) . '" target="_blank"><i class="fas fa-print" aria-hidden="true"></i> ' . __("lang_v1.download_paking_pdf") . '</a></li>';
if (auth()->user()->can("sell.view") || auth()->user()->can("direct_sell.access"))
if (!empty($row->document))
$document_name = !empty(explode("_", $row->document, 2)[1]) ? explode("_", $row->document, 2)[1] : $row->document ;
$html .= '<li><a href="' . url('uploads/documents/' . $row->document) .'" download="' . $document_name . '"><i class="fas fa-download" aria-hidden="true"></i>' . __("purchase.download_document") . '</a></li>';
if (isFileImage($document_name))
$html .= '<li><a href="#" data-href="' . url('uploads/documents/' . $row->document) .'" class="view_uploaded_document"><i class="fas fa-image" aria-hidden="true"></i>' . __("lang_v1.view_document") . '</a></li>';
if ($is_admin || auth()->user()->hasAnyPermission(['access_shipping', 'access_own_shipping', 'access_commission_agent_shipping']) )
$html .= '<li><a href="#" data-href="' . action('SellController@editShipping', [$row->id]) . '" class="btn-modal" data-container=".view_modal"><i class="fas fa-truck" aria-hidden="true"></i>' . __("lang_v1.edit_shipping") . '</a></li>';
if ($row->type == 'sell')
if (auth()->user()->can("print_invoice"))
$html .= '<li><a href="#" class="print-invoice" data-href="' . route('sell.printInvoice', [$row->id]) . '"><i class="fas fa-print" aria-hidden="true"></i> ' . __("lang_v1.print_invoice") . '</a></li>
<li><a href="#" class="print-invoice" data-href="' . route('sell.printInvoice', [$row->id]) . '?package_slip=true"><i class="fas fa-file-alt" aria-hidden="true"></i> ' . __("lang_v1.packing_slip") . '</a></li>';
$html .= '<li class="divider"></li>';
if (!$only_shipments)
if ($row->payment_status != "paid" && auth()->user()->can("sell.payments"))
$html .= '<li><a href="' . action('TransactionPaymentController@addPayment', [$row->id]) . '" class="add_payment_modal"><i class="fas fa-money-bill-alt"></i> ' . __("purchase.add_payment") . '</a></li>';
$html .= '<li><a href="' . action('TransactionPaymentController@show', [$row->id]) . '" class="view_payment_modal"><i class="fas fa-money-bill-alt"></i> ' . __("purchase.view_payments") . '</a></li>';
if (auth()->user()->can("sell.create"))
$html .= '<li><a href="' . action('SellController@duplicateSell', [$row->id]) . '"><i class="fas fa-copy"></i> ' . __("lang_v1.duplicate_sell") . '</a></li>
<li><a href="' . action('SellReturnController@add', [$row->id]) . '"><i class="fas fa-undo"></i> ' . __("lang_v1.sell_return") . '</a></li>
<li><a href="' . action('SellPosController@showInvoiceUrl', [$row->id]) . '" class="view_invoice_url"><i class="fas fa-eye"></i> ' . __("lang_v1.view_invoice_url") . '</a></li>';
$html .= '<li><a href="#" data-href="' . action('NotificationController@getTemplate', ["transaction_id" => $row->id,"template_for" => "new_sale"]) . '" class="btn-modal" data-container=".view_modal"><i class="fa fa-envelope" aria-hidden="true"></i>' . __("lang_v1.new_sale_notification") . '</a></li>';
else
$html .= '<li><a href="#" data-href="' . action('SellController@viewMedia', ["model_id" => $row->id, "model_type" => "App\Transaction", 'model_media_type' => 'shipping_document']) . '" class="btn-modal" data-container=".view_modal"><i class="fas fa-paperclip" aria-hidden="true"></i>' . __("lang_v1.shipping_documents") . '</a></li>';
$html .= '</ul></div>';
return $html;
)
->removeColumn('id')
->editColumn(
'final_total',
'<span class="final-total" data-orig-value="$final_total">@format_currency($final_total)</span>'
)
->addColumn('products', function($row)
return $row->product_name;
)
->editColumn(
'unit_price',
'<span class="unit-price" data-orig-value="$unit_price">@format_currency($unit_price)</span>'
)
->editColumn(
'tax_amount',
'<span class="total-tax" data-orig-value="$tax_amount">@format_currency($tax_amount)</span>'
)
->editColumn(
'total_paid',
'<span class="total-paid" data-orig-value="$total_paid">@format_currency($total_paid)</span>'
)
->editColumn(
'total_before_tax',
'<span class="total_before_tax" data-orig-value="$total_before_tax">@format_currency($total_before_tax)</span>'
)
->editColumn(
'discount_amount',
function ($row)
$discount = !empty($row->discount_amount) ? $row->discount_amount : 0;
if (!empty($discount) && $row->discount_type == 'percentage')
$discount = $row->total_before_tax * ($discount / 100);
return '<span class="total-discount" data-orig-value="' . $discount . '">' . $this->transactionUtil->num_f($discount, true) . '</span>';
)
->editColumn('transaction_date', '@format_datetime($transaction_date)')
->editColumn(
'payment_status',
function ($row)
$payment_status = Transaction::getPaymentStatus($row);
return (string) view('sell.partials.payment_status', ['payment_status' => $payment_status, 'id' => $row->id]);
)
->editColumn(
'types_of_service_name',
'<span class="service-type-label" data-orig-value="$types_of_service_name" data-status-name="$types_of_service_name">$types_of_service_name</span>'
)
->addColumn('total_remaining', function ($row)
$total_remaining = $row->final_total - $row->total_paid;
$total_remaining_html = '<span class="payment_due" data-orig-value="' . $total_remaining . '">' . $this->transactionUtil->num_f($total_remaining, true) . '</span>';
return $total_remaining_html;
)
->addColumn('return_due', function ($row)
$return_due_html = '';
if (!empty($row->return_exists))
$return_due = $row->amount_return - $row->return_paid;
$return_due_html .= '<a href="' . action("TransactionPaymentController@show", [$row->return_transaction_id]) . '" class="view_purchase_return_payment_modal"><span class="sell_return_due" data-orig-value="' . $return_due . '">' . $this->transactionUtil->num_f($return_due, true) . '</span></a>';
return $return_due_html;
)
->editColumn('invoice_no', function ($row)
$invoice_no = $row->invoice_no;
if (!empty($row->woocommerce_order_id))
$invoice_no .= ' <i class="fab fa-wordpress text-primary no-print" title="' . __('lang_v1.synced_from_woocommerce') . '"></i>';
if (!empty($row->return_exists))
$invoice_no .= ' <small class="label bg-red label-round no-print" title="' . __('lang_v1.some_qty_returned_from_sell') .'"><i class="fas fa-undo"></i></small>';
if (!empty($row->is_recurring))
$invoice_no .= ' <small class="label bg-red label-round no-print" title="' . __('lang_v1.subscribed_invoice') .'"><i class="fas fa-recycle"></i></small>';
if (!empty($row->recur_parent_id))
$invoice_no .= ' <small class="label bg-info label-round no-print" title="' . __('lang_v1.subscription_invoice') .'"><i class="fas fa-recycle"></i></small>';
if (!empty($row->is_export))
$invoice_no .= '</br><small class="label label-default no-print" title="' . __('lang_v1.export') .'">'.__('lang_v1.export').'</small>';
return $invoice_no;
)
->editColumn('shipping_status', function ($row) use ($shipping_statuses)
$status_color = !empty($this->shipping_status_colors[$row->shipping_status]) ? $this->shipping_status_colors[$row->shipping_status] : 'bg-gray';
$status = !empty($row->shipping_status) ? '<a href="#" class="btn-modal" data-href="' . action('SellController@editShipping', [$row->id]) . '" data-container=".view_modal"><span class="label ' . $status_color .'">' . $shipping_statuses[$row->shipping_status] . '</span></a>' : '';
return $status;
)
->addColumn('conatct_name', '@if(!empty($supplier_business_name)) $supplier_business_name, <br> @endif $name')
->editColumn('quantity', '@format_quantity($quantity)')
->filterColumn('conatct_name', function ($query, $keyword)
$query->where( function($q) use($keyword)
$q->where('contacts.name', 'like', "%$keyword%")
->orWhere('contacts.supplier_business_name', 'like', "%$keyword%");
);
)
->addColumn('payment_methods', function ($row) use ($payment_types)
$methods = array_unique($row->payment_lines->pluck('method')->toArray());
$count = count($methods);
$payment_method = '';
if ($count == 1)
$payment_method = $payment_types[$methods[0]];
elseif ($count > 1)
$payment_method = __('lang_v1.checkout_multi_pay');
$html = !empty($payment_method) ? '<span class="payment-method" data-orig-value="' . $payment_method . '" data-status-name="' . $payment_method . '">' . $payment_method . '</span>' : '';
return $html;
)
->editColumn('status', function($row) use($sales_order_statuses, $is_admin)
$status = '';
if ($row->type == 'sales_order')
if ($is_admin && $row->status != 'completed')
$status = '<span class="edit-so-status label ' . $sales_order_statuses[$row->status]['class'] . '" data-href="'.action("SalesOrderController@getEditSalesOrderStatus", ['id' => $row->id]).'">' . $sales_order_statuses[$row->status]['label'] . '</span>';
else
$status = '<span class="label ' . $sales_order_statuses[$row->status]['class'] . '" >' . $sales_order_statuses[$row->status]['label'] . '</span>';
return $status;
)
->editColumn('so_qty_remaining', '@format_quantity($so_qty_remaining)')
->setRowAttr([
'data-href' => function ($row)
if (auth()->user()->can("sell.view") || auth()->user()->can("view_own_sell_only"))
return action('SellController@show', [$row->id]) ;
else
return '';
]);
$rawColumns = ['final_total', 'unit_price', 'action', 'total_paid', 'total_remaining', 'payment_status', 'invoice_no', 'discount_amount', 'tax_amount', 'total_before_tax', 'shipping_status', 'types_of_service_name', 'payment_methods', 'return_due', 'conatct_name', 'status'];
return $datatable->rawColumns($rawColumns)
->make(true);
$business_locations = BusinessLocation::forDropdown($business_id, false);
$customers = Contact::customersDropdown($business_id, false);
$sales_representative = User::forDropdown($business_id, false, false, true);
//Commission agent filter
$is_cmsn_agent_enabled = request()->session()->get('business.sales_cmsn_agnt');
$commission_agents = [];
if (!empty($is_cmsn_agent_enabled))
$commission_agents = User::forDropdown($business_id, false, true, true);
//Service staff filter
$service_staffs = null;
if ($this->productUtil->isModuleEnabled('service_staff'))
$service_staffs = $this->productUtil->serviceStaffDropdown($business_id);
$shipping_statuses = $this->transactionUtil->shipping_statuses();
return view('sell.index')
->with(compact('business_locations', 'customers', 'is_woocommerce', 'sales_representative', 'is_cmsn_agent_enabled', 'commission_agents', 'service_staffs', 'is_tables_enabled', 'is_service_staff_enabled', 'is_types_service_enabled', 'shipping_statuses'));
你可以看到附加的图片我的目标是如何在这个查询上使用 cache::remember。
Controller file
transactions.php file
【问题讨论】:
您应该在问题本身中分享相关代码,而不是图片。当人们必须在各个页面中跳转时,很难理解。我个人不太希望 imgur 收集我的任何个人信息,以便我了解您的问题。 我已经添加了代码。 代码太多了。尝试创建minimal reproducible example 并更简要地解释您的问题。 好的,先生,让我来做吧。 【参考方案1】:扩展 transactionUtil 文件以执行整个查询。您还需要收集用于构造查询的所有部分,以形成它们的唯一组合的唯一键。例如,这可能是事务实用程序中的一个函数:
function getFullResult($business_id, $sale_type)
$queryParameters = array_merge(compact('business_id, sale_type'), request()->all()); // You can filter these into the ones that are used for the query only
$cacheDurationSeconds = 3600;
return Cache::remember('getFullResult'.md5(json_encode($queryParameters)), $cacheDurationSeconds, function () use ($business_id, $sale_type)
$sells = $this->getListSells($business_id, $sale_type, request()->customer_id);
if (request()->only_subscriptions)
$sells->where(function ($q)
$q->whereNotNull('transactions.recur_parent_id')
->orWhere('transactions.is_recurring', 1);
);
if (!empty(request()->list_for) && request()->list_for == 'service_staff_report')
$sells->whereNotNull('transactions.res_waiter_id');
// ....
return $sells->where('transactions.is_suspend', 1)
->with($with)
->addSelect('transactions.is_suspend', 'transactions.res_table_id', 'transactions.res_waiter_id', 'transactions.additional_notes')
->get();
);
这里我使用md5
生成唯一密钥,因为它速度快,并且对于这个特定用例而言,哈希冲突的可能性很低。
但是,鉴于查询的复杂性,您需要质疑在请求中获得多个相同参数的可能性,因为如果您不这样做,那么缓存将无济于事。
【讨论】:
所以你的意思是我需要将我所有剩余的代码,包括 getListSell() 包含在缓存中? 构建和执行查询所需的所有代码都必须放在remember
回调中,因此只有在之前没有缓存过该确切查询的情况下才会执行
哇,非常感谢你每件事都很清楚,我很困惑。以上是关于在缓存中包装 laravel 查询::remember的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 7:禁用登录和自动登录(remember_token)
没有 remember_token 的 Laravel 5 身份验证
在 Laravel 4 中实现 Remember Me 函数会返回错误