Yii PHP Add Pagination to my site - php

I would like to add pagination to my website, but I am very new to Yii and would like some advise.
This is the page that I am looking to add pagination: https://gocar2.com/newsproducts/center
As you can see I have numerous cells for each auto news, and now I am allowing only 18 news to show on the page. I would like to add pagination here so that I can browse more news.
And this is what I tried:
newscontroller.php
<?php
use yii\data\Pagination;
class NewsproductsController extends Controller
{
public function actionCentermore()
{
$criteria = new CDbCriteria;
$criteria->addCondition("approvedStatus = '1'");
$criteria->order = 'createdDate DESC';
$product = Newsproducts::model()->findAll($criteria);
$Pagination = new Pagination([
'defaultPageSize' => 15,
'totalCount' => $product->count(),
]);
$products = $product->offset($Pagination->offset)
->limit($Pagination->limit)
->all();
$this->renderPartial('centermore',compact('products', 'Pagination'));
}
}
newsview.php will render all the top menu and banners and it will render centermore.php
$this->renderPartial('centermore', compact('products', 'Pagination'));
centermore.php (view of the news cells), I then added the LinkPager widget at the bottom.
LinkPager::widget(['Pagination' => $Pagination])
And of course, there is an error, Class LinkPager cannot be found.
Can anyone give me some advise how to solve this/implement paging?

In Yii2 pagination is usually handled via DataProvider, have a look at the:
Yii2 Guide: Data Providers, especially ActiveDataProvider:
use yii\data\ActiveDataProvider;
$query = Post::find()->where(['status' => 1]);
$provider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => 10,
],
'sort' => [
'defaultOrder' => [
'created_at' => SORT_DESC,
'title' => SORT_ASC,
]
],
]);
// returns an array of Post objects
$posts = $provider->getModels();

Related

Automatically build laravel pagination object

in my app each time I retrieve paginated results from the database I have to do somethig like this:
$posts = Post::latest()->with(['category','user'])->paginate($request->input('paginate', 6));
$posts =
[
'data' => $posts,
'pagination' => [
'total' => $posts->total(),
'per_page' =>$posts->perPage(),
'current_page' => $posts->currentPage(),
'last_page' => $posts->lastPage(),
'from' => $posts->firstItem(),
'to' => $posts->lastItem()
]
];
As you see I first retrieve the results from database and then I have to manually create the paginated data array, always doing the same seems bad and tedious to me honestly, I was wondering if there is a laravel magic method to automatically build the pagination payload array?
You can use Eloquent: API Resources "https://laravel.com/docs/7.x/eloquent-resources"
You should create a resource: php artisan make:resource PostCollection
and you should change method toArray($request) for something like this:
public function toArray($request)
{
return [
'data' => $this->collection,
'pagination' => [
'total' => $this->total(),
'per_page' =>$this->perPage(),
'current_page' => $this->currentPage(),
'last_page' => $this->lastPage(),
'from' => $this->firstItem(),
'to' => $this->lastItem()
]
];
}
Now when you want to paginate your Model you just do it like this:
//Get posts
$posts = Post::latest()->with(['category','user'])
->paginate($request->input('paginate', 6)));
//Use your resource (Collection)
$postsPaginate = new PostCollection($posts);
//Return your resource
return $porstsPaginate;

Yii2 - Use dataProvider multiple times with different sorting

So I have a dataprovider which is created in a controller like this:
$modelSearch = new SearchModel();
$data_provider = $modelSearch->search(Yii::$app->request->queryParams); // returns the data provider
Then I use the $data_provider in a view like this:
GridView::widget([
'dataProvider' => $data_provider,
'export' => false,
'columns' => [
...
],
...
But now I'd like to use the same data from the $data_provider but without pagination and other sorting specifications.
Tried this but doesn't work:
$data_provider->sort = ['defaultOrder'=> ['column_a' => SORT_ASC, 'column_b' => SORT_DESC]]
$data_provider->pagination = false;
I think that's because the data is already retrieved with the ->search() method. Do I need to create a whole new search model class? just to get a different sorting?
Thanks in advance!
You should use two dataProvider eg:
$modelSearch = new SearchModel();
$data_provider = $modelSearch->search(Yii::$app->request->queryParams);
$data_provider2 = $data_provider;
$data_provider2->pagination = false;
$data_provider2->sort = ['defaultOrder'=> ['column_a' => SORT_ASC, 'column_b' => SORT_DESC]]
return $this->render('your_view', [
'searchModel' => $searchModel,
'dataProvider' => $data_provider,
'dataProvider2' => $data_provider2,
]);
Before I asked the question I didn't know the dataProvider already retrieved the data on creation. So altering properties of the dataProvider doesn't do another search, it does different sorting but with the same data it already retrieved.
Answer:
I ended up making a new method in the searchModel class like this:
public function searchByCreatedAt() {
$query = Model::find()->orderBy(['created_at' => SORT_ASC]);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => false,
]);
...
}

Yii framework 2.0 multiple paginations on one page

Working with Yii framework 2.0 I tried to use the pagination feature and linkpager widget, following Yii documentation.
Below is my controller.
public function actionIndex()
{
$query = Country::find();
$pagination = new Pagination([
'defaultPageSize' => 5,
'totalCount' => $query->count(),
]);
$countries = $query->orderBy('name')
->offset($pagination->offset)
->limit($pagination->limit)
->all();
return $this->render('index', [
'countries' => $countries,
'pagination' => $pagination,
]);
}
In my index view, I use the following code.
<?= LinkPager::widget(['pagination' => $pagination]) ?>
Now I want to add one more pagination feature and LinkPager widget for another model City. In the actionIndex() method I follow the existing code, just create an object of City and an object of new Pagination and return it to the view. In the view I include LinkPager widget once again with another pagination variable $paginationCity. When I click on a pagination number I saw the query string page=xx in the URL. I notice that it is being used for both models Country and City. How can I use multiple pagination on one same page?
You can do it by changing pageParam property of Pagination class:
$cityPagination = new Pagination([
...
'pageParam' => 'city-page',
]);

Yii CLinkPager change link page

In my project I want to change the link url because it does not look good.
The link is as example below:
http://www.example.com/product?Product[pagesize]=24&page=2
http://www.example.com/product?Product[brand_id][]=3
so I want to the url like this
http://www.example.com/product?pagesize=24&page=2
http://www.example.com/product?brd[]=3
I use Yii framewrok, so is it possible to change it?
Thank you!
I do not know why u use difficult url instead of dataprovider of yii for paging. here is code:
controller:
$pageSize=5;
$news = News::model()->findAll(); //returns AR objects
$count = count($news);
$dataProvider= new CArrayDataProvider($news, array(
'sort'=>array('attributes'=>array('title')), //you can sort here if objects not sorted
'pagination'=>array('pageSize'=>$pageSize),
));
$models = $dataProvider->getData();
$this->render('index', array(
'models' => $models,
'dataProvider' => $dataProvider,
'itemCount' => $count,
));
on view:
<?php
$this->widget('CLinkPager', array(
'pages'=>$dataProvider->pagination,
));
?>

Pagination For Search Results using Yii

I have a search form, which returns a bunch of images. Because their number can be high, I would prefer having the results displayed using pagination. However, I cannot seem to get it to work properly. I have moved everything to the view to keep things as simple as possible.
Here is my code snippet for the search and pagination:
$searchData = $model->search(); // this is the result of the search
$pages = new CPagination($searchData->itemCount);
$searchData->setPagination($pages);
$pages->applyLimit($searchData->criteria);
$pages->pageSize = 2;
Then, I display the results using a "foreach" statement:
foreach($searchData->getData() as $data)
{
// results displayed here
}
Finally, I have the CLinkPager widget:
$this->widget('CLinkPager', array(
'pages' => $pages,
'header' => 'Отиди на страница: ',
'nextPageLabel' => 'Следваща',
'prevPageLabel' => 'Предишна',
)); `
The problem is: there is not a relation between the widget and the displayed results.
For instance, if I get 4 results, the widget correctly shows that there are 2 pages. However, the results are not displayed in two pages, all are shown in one and clicking the CLinkPager links does nothing.
I have done pagination in the past successfully before, but for all the data using
model()->findAll().
How do I state the relation between the pagination widget and the search results... ?
Thank you for your time.
I think you are possibly overcomplicating the process. You could more easily use CListView widget to display your results with pagination.
Your controller may have this;
public function actionIndex(){
$model = new Model;
$this->render('index', array('model' => $model);
}
Your model needs to have a search method that returns an instance of CActiveDataProvider, for example
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id, true);
$criteria->compare('title', $this->title, true);
$criteria->order = 'sortOrder';
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
Then in your view file you can use this code;
$this->widget('widgets.CListView', array(
'dataProvider' => $model->search(),
'itemView' => '_list',
'template' => '{pager}{items}',
'pager' => array(
'nextPageLabel' => 'Следваща',
'prevPageLabel' => 'Предишна',
)
));
You can extend the CListView by putting this in your extensions folder, and change the page size there.
<?php
Yii::import('zii.widgets.CListView');
class CustomListView extends CListView {
public function init() {
if ($this->dataProvider !== null)
$this->dataProvider->pagination->pageSize = 30;
$this->dataProvider->pagination->nextPageLabel => 'Следваща';
$this->dataProvider->pagination->prevPageLabel => 'Предишна';
parent::init();
}
}
Then, use the CustomListView as follows:
<?php $this->widget('CustomListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
)); ?>
You do not need to use CLinkPager widget directly this way.

Categories