Yii2 cache of grid view - caching

I have a relatively complex query across 8 tables which returns up to 10,000 records with 20 columns. These are then displayed in a GridView
The user repeatedly sorts and filters the GridView - causing a page reload - in order to rank the data. One column contains an Ajax “five star” rating function and the user then marks each row: one star to five stars
Naturally, this isn’t the fastest loading page so I was wondering if I could use caching to accelerate the page load but don’t know if this can be done considering the filtering and marking
Can caching be used in this example? The data in the 19 columns are always the same (the user cannot change the data) but the user constantly changes the rating in the 20th column
Can I cache the 19 columns and filter / sort after??
Can I cache the 19 columns and join the rating column thereafter??
Many thanks

You can easily use the PageCache filter behavior of yii2 to easily cache pages.
Just add the following code to your controller and fit the dependency and variation properties to your needs.
public function behaviors()
{
return [
'pageCache' => [
'class' => 'yii\filters\PageCache',
'only' => ['index'],
'duration' => 60,
'dependency' => [
'class' => 'yii\caching\DbDependency',
'sql' => 'SELECT COUNT(*) FROM post',
],
'variations' => [
\Yii::$app->language,
]
],
];
}

Related

How to add validation for preventing duplicate level points in laravel query?

Here is a table named stages and below are the fields
I don't want to allow to add the same from and to points example, if points from 1 to 10 is already added means not allow them to add the same range, another one condition is don't allow to add in between points example in-between 1to 10 like 5 to 7 are also not allowed.
Tried laravel query
$isexist = Stage::whereBetween('from', [$request->from, $request->to])
->orWhereBetweenColumn('to','from', [$request->from, $request->to])->exists();
but it not satisfying all conditions.
Any one please help, thanks in advance.
you can validate the data like this
$validator = Validator::make($inputData, [
'label' => 'required|unique:tableName,label'
]);
if($validator->fails()){
//Throw validation errors
}
Or you can use
Model::query()->updateOrCreate(['label' => $request->label], [
'from' => $request->from,
'to' => $request->to
]);
Read more on unique validation reference: https://laravel.com/docs/9.x/validation#quick-writing-the-validation-logic

What is the best way to use one layout for different pages? (without database)

I'm working on a website and I have a layout for at least 20 services which are only different in description and image. I'm trying to find a way to implement one layout and add data for a specific link and I don't want to use a database because the data isn't important to save. Is there another way or I have to use 20 blades that extend one layout?
You can have an array like this that you will pass to a layout
$servicesLayout = [
'service_1' => [
'description' => 'Service 1 description',
'image' => 'www.host.com/assets/img/section_1.jpg'],
'service_2' => [
'description' => 'Service 2 description',
'image' => 'www.host.com/assets/img/section_2.jpg']
];
Now when viewing a section, you pass the section key for example 'section_1' to the layout
To display section description in layout
{{$servicesLayout['service_1']['description']}}

Laravel 5.8 pagination without Eloquent

I need a custom pagination but in my case, i do not use eloquent for fetching data. I use an API where i fetch data.
I've been dealing with Pagination class, but as far as i know, it takes a collection and paginate it. That's not what i need.
What i need is creating a paginate object based on a subset of records gotten by a search query. Let's say such query has a total of 10000 records and I only get an array of 50 items, so each paginate has 50 elements. So, i need to create the pagination links based on this info.
Is there any way of accomplish it?
EDIT:
$models = array('total' => $n_results,
'per_page' => 30,
'current_page' => 1,
'last_page' => ceil($n_results/30),
'next_page' => "******",
'prev_page' => "******",
'from' => 1,
'to' => 30,
'data' => $items);
Based on what I understood here what I would do:
1- if you cannot ask the limit and offset for each call of the API and the API provides all the results to you at once but you want to show them 50 at a time, then I would create a temp_table and insert the data to it and then it's like it's on my own database then I would be able to sort,limit and offset by myself.
2- if the total result is not that much (like less than 500) and you want the user to not be overwhelmed by all the results together and you wanna show it to them 50 results at a time or 20 results at a time you can load all the result in blade by hide their element. (it's not what I would recommend but it would do the trick if you don't want a temp_table)

createMany equivalent for updateOrCreate

Is there a createMany equivalent for updateOrCreate in Laravel for when you want to "updateOrCreate" many records in one call?
In other words, is there a sort of updateOrCreateMany function?
From the documentation there doesn't appear to be a function with that name, but maybe there's another friendly Laravel way of doing this... or should I just use a foreach (maybe also using MySQL's insert on duplicate feature)?
Based upon the documentation of Laravel, no there is no method on eloquent like updateOrCreateMany
If you give it a thought, it makes sense because the execution will anyway need to be sequential. As its possible that some entry might affect the previous one so the insertion or updation mode cannot be concurrent. So even if there was some method like that, it would anyway use a loop internally to execute query one by one.
To clear further let's say there was a method updateOrCreateMany which would probably take input like array of arrays like so:
Model::updateOrCreateMany([
[
'email' => 'x#y.com'
],
[
'email' => 'x2#y2.com'
],
[
'email' => 'x#y.com'
]
],
[
[
'name' => 'X Y'
],
[
'name' => 'X2 Y2'
],
[
'name' => 'X Y Updated'
]
]);
As you can see that record 3 is supposed to update the record 1 so basically, you cannot enter all at once by only comparing each with the database image of the insertion time of record1, that way you will enter in error of duplicated email as x#y.com did not exist initially.
Hence, there is no updateOrCreateMany method because it cannot be done concurrent, it needs to be sequential which means some kind of looping mechanism like foreach.
By the way Good Question! +1
Makes sense?
I suggest using a foreach loop on your data and using updateOrCreate method
foreach($records as $record){
Model::updateOrCreate([$record->id, $record->name], [$record->likes, $record->dislikes]);
}

Custom Magento Report for Taxable/Non-Taxable sales

Let me preface by saying I'm new to Magento as well as Data Collections in general (only recently begun working with OOP/frameworks).
I've followed the excellent tutorial here and I'm familiar with Alan Storm's overviews on the subject. My aim is to create a custom Magento report which, given a start/end date, will return the following totals:
Taxable Net (SUM subtotal for orders with tax)
Non-Taxable Net (SUM subtotal for orders without tax)
*Total Gross Sales (Grand total)
*Total Net Sales (Grand subtotal)
*Total Shipping
*Total Tax
*For these figures, I realize they are available in existing separate reports or can be manually calculated from them, however the purpose of this report is to give our store owner a single page to visit and file to export to send to his accountant for tax purposes.
I have the basic report structure already in place in Adminhtml including the date range, and I'm confident I can include additional filters if needed for order status/etc. Now I just need to pull the correct Data collection and figure out how to retrieve the relevant data.
My trouble is I can't make heads or tails of how the orders data is stored, what Joins are necessary (if any), how to manipulate the data once I have it, or how they interface with the Grid I've set up. The existing tutorials on the subject that I've found are all specifically dealing with product reports, as opposed to the aggregate sales data I need.
Many thanks in advance if anyone can point me in the right direction to a resource that can help me understand how to work with Magento sales data, or offer any other insight.
I have been working on something extremely similar and I used that tutorial as my base.
Expanding Orders Join Inner
Most of the order information you need is located in sales_flat_order with relates to $this->getTable('sales/order')
This actually already exists in her code but the array is empty so you need to populate it with the fields you want, here for example is mine:
->joinInner(
array('order' => $this->getTable('sales/order')),
implode(' AND ', $orderJoinCondition),
array(
'order_id' => 'order.entity_id',
'store_id' => 'order.store_id',
'currency_code' => 'order.order_currency_code',
'state' => 'order.state',
'status' => 'order.status',
'shipping_amount' => 'order.shipping_amount',
'shipping_tax_amount' => 'order.shipping_tax_amount',
'shipping_incl_tax' => 'base_shipping_incl_tax',
'subtotal' => 'order.subtotal',
'subtotal_incl_tax' => 'order.subtotal_incl_tax',
'total_item_count' => 'order.total_item_count',
'created_at' => 'order.created_at',
'updated_at' => 'order.updated_at'
))
To find the fields just desc sales_flat_order in mysql.
Adding additional Join Left
Ok so if you want information from other tables you need to add an ->joinLeft() for example I needed the shipment tracking number:
Create the Join condition:
$shipmentJoinCondition = array(
$orderTableAliasName . '.entity_id = shipment.order_id'
);
Perform the join left:
->joinLeft(
array('shipment' => $this->getTable('sales/shipment_track')),
implode(' AND ', $shipmentJoinCondition),
array(
'track_number' => 'shipment.track_number'
)
)
Sorry I couldn't go into more depth just dropping the snippet for you here.
Performing Calculations
To modify the data returned to the grid you have to change addItem(Varien_Object $item) in your model, basically whatever is returned from here get put in the grid, and well I am not 100% sure how it works and it seems a bit magical to me.
Ok first things first $item is an object, whatever you do to this object will stay with the object (sorry terrible explanation): Example, I wanted to return each order on a separate line and for each have (1/3, 2/3, 3/3), any changes I made would happen globally to the order object so they would all show (3/3). So keep this in mind, if funky stuff starts happening use PHP Clone.
$item_array = clone $item;
So now onto your logic, you can add any key you want to the array and it will be accessible in Grid.php
For example(bad since subtotal_incl_tax exists) :
$item_array['my_taxable_net_calc'] = $item['sub_total'] + $item['tax'];
Then at the end do:
$this->_items[] = $item_array;
return $this->_items;
You can also add more rows based on the existing by just adding more data to $this->_items[];
$this->_items[] = $item_array;
$this->_items[] = $item_array;
return $this->_items;
Would return same item on two lines.
Sorry I have started to lose the plot, if something doesn't make sense just ask, hope this helped.
Oh and to add to Block/Adminhtml/namespace/Grid.php
$this->addColumn('my_taxable_net_calc', array(
'header' => Mage::helper('report')->__('Taxable Net'),
'sortable' => false,
'filter' => false,
'index' => 'my_taxable_net_calc'
));

Resources