I encountered a problem with pagination in my Laravel app.
Normally, when I want to use Laravel pagination with let's say 3 rows for one page, I use Eloquent method paginate/simplePaginate in combination with method latest() like so:
//MyController.php
$posts= Post->latest()->paginate(3);
//MyView.blade.php
#foreach ($posts as $post)
{{ $post->id }}
#endforeach
{{ $posts->links() }}
So when i have 6 posts in my database and I use Laravel pagination + Infinite scroll, that becomes:
6
5 (1. page)
4
--- ('page separator')
3
2 (2. page)
1
But, if user inserts new row into database table before I reach page 2,
the collection shifts and second page of data becomes:
6
5 (1. page)
4
--- POST WITH ID 4 IS DUPLICATED BECAUSE OF SHIFT IN COLLECTION
4
3 (2. page)
2
So, for example --- if user inserts three new rows into database before I reach paginator, then the second page will output the same three table rows as my current first page, but i'd like to output the remaining table rows:
6
5 (1. page)
4
--- AT SOME TIME BEFORE PAGINATION WAS TRIGGERED, POST WITH ID '7' HAS BEEN ADDED
3
2 (2. page) - continues normally with remaining rows (pagination ignores newly added row)
1
Is there any workaround for this problem?
Thanks.
I solved this issue by asking for the first record id of the first page served
// {initial query} $records->orderBy('created_at', 'desc');
if(is_int($last_id)){
$records = $records->where('id', '<=' , $last_id);
}
$records = $records->paginate($per_page);
This way, the paginator get's records starting from that id, ignoring new records
You could try this:
$posts= Post->orderBy('id', 'desc')
->distinct()
->paginate(3);
Related
I'm pretty new to joins so excuse me as I get my head round it! I'm trying to join 2 tables onto a links table.
One table is clicks. I want the SUM of any data in the clicks.clicks column where link_id matches. (ie 2 columns, One with 1 in the column and a second with 4 in the clicks column both for link_id=1 would return 5)
And the second table is suggestions which I want the COUNT of any occurrence of link_id to be displayed (ie 4 rows where link_id=1 would return 4)
I'm using eloquent with 2 left joins for this and have managed to get both working independently, however when I put both together, clicks_sum which is the name of my SUM join goes wildly high (Seeming as if the suggestion_count is interfering with what's going on there)
Here's my code so far for what I'm trying to achieve. I'm loading Link ID 2872719 just to test with. It should return 585 for suggestion_count and 4 for clicks_sum but I am getting totally different results than expected
use App\Models\Link;
use App\Models\Suggestion;
return Link::select(
'links.id',
DB::raw('SUM(clicks.clicks) AS click_sum'),
DB::raw('COUNT(suggestions.link_id) AS suggestion_count'),
)
->leftJoin('clicks', 'clicks.link_id', '=', 'links.id')
->leftJoin('suggestions', 'suggestions.link_id', '=', 'links.id')
->where('links.id', 2872719)
->first();
Returned is the following:
App\Models\Link {#1278
id: 2872719,
click_sum: "2340", // Should be 4
suggestion_count: 585, // The presence of this join appears to affect click_sum
}
Any ideas on where I am going wrong?
All my best!
Rather than having two leftJoin instances in your eloquent query you need to combine the two joins together into one leftJoin.
return Link::select(
'links.id',
// get the count of suggestions for each link
DB::raw('(SELECT COUNT(*) FROM suggestions WHERE suggestions.link_id = links.id) AS suggestion_count'),
DB::raw('SUM(clicks.clicks) AS click_sum'),
)
->leftJoin('clicks', 'clicks.link_id', '=', 'links.id', 'suggestions.link_id', '=', 'links.id')
->where('links.id', 2872719)
->groupBy('links.id')
->first();
This should give you the correct result as below:
#original: array:3 [▼
"id" => 2872719
"suggestion_count" => 586
"click_sum" => "4"
]
When performing two leftJoin as you were previously, the click_sum was being multiplied by the total count of suggestions leading to the inflated number being returned.
i want to get only 3 blog of per category. but code return me all blogs of per category laravel
example i have 2 category (category 1 haves 10 blogs and category 2 haves 7 blog). now i want only 3 records of category 1 and 3 records of category 2 from DB
my controller code.
$categories = Category::has('blogs')->take(10)->get();
Category::with('blogs')->get()->map(function($category) {
$category->setRelation('blogs', $category->blogs->take(3));
return $category;
});
Should do your work
In my Laravel project, I have a multiple rows in my DB table, similar to each other in every thing except ID, other column called stage
Stages table
ID
name
1
first
2
second
3
third
subjects Table
ID
name
stage_id
1
English
1
2
English
2
3
English
3
I need to show em in a blade like this
#
name
stage
1
English
first, two, three, etc
I already have the relations in my modals, and I am already showing them in my blade by loop, but I just want to group the rows by name and show the different stages
I hope that I explained the case well, I am not very good at explaining
Updates : before editing I wrote a dummy data now I hope I explained the issue in more details
The project idea is that you can create more than faculty
and every faculty has Stages and sections and every section has specialties and every specialty has subjects
now about subjects and stages
user can create subject like English and make it available to the first stage and 2nd and third ..etc ( the available stages in this faculty)
The Stages belongs to Faculty
The Subjects belongs to Stage
so the relations are
Subject Model
public function stage()
{
return $this->belongsTo(Stage::class);
}
Stage Model
public function subjects()
{
return $this->hasMany(Subject::class);
}
As you have "English" Multiple Times, you should have a subject Table :
Stages table
ID
name
1
first
2
second
3
third
Subject table
ID
name
1
English
stage_subject Table :
ID
stage_id
subject_id
1
1
1
1
2
1
1
3
1
Subject Model
public function stage()
{
return $this->belongsToMany(Stage::class);
}
Stage Model
public function subjects()
{
return $this->belongsToMany(Subject::class);
}
Then in your foreach:
#php($subjects = Subject::with('stages')->get())
#foreach($subjects as $subject)
{{ $subject->id }} | {{$subject->name}} | {{$subject->stages->pluck('name')->implode(', ')}}
#endforeach
If you don't / can't do a pivot table, then you can use collection :
#php($subjects = Subject::with('stages')->get())
#foreach($subjects->groupBy('name') as $name => $subjects)
{{ $subjects->first()->id }} | {{$name}} | {{$subjects->pluck('stage.name')->implode(', ')}}
#endforeach
I want to give index to each result from a query, something like this
page 1
1
2
3
4
5
page 2
6
7
8
9
10
page 3
etc
How would I do that? I can't use the id from the table, and I can't use $loop->iteration to print out a the index for each result, since loop->iteration would reset for each page load if I am correct?
How would I give index to all returned results and have it work accors all the pages
You can use $loop->iteration and pagination instance methods:
($results->currentPage() - 1) * $results->perPage() + $loop->iteration
I am developing one custom search module in joomla. so I am using joomla's in-built database connection and function.
Problem is that I want to use pagination class in this module but don't know any hint.
Please help me on this.
Thanks.
Step 1: Get the total number of items in your database
ex: select count(*) from #__some_table where ....
Step 2: Import joomla pagination and create pagination object
jimport('joomla.html.pagination');
$pagination = new JPagination($total, $limitstart, $limit);
where
$total = total number of items that you count in step 1
$limit = total number of items you want to display on a page
$limitstart = index of the first item in the page. For example if you have 20 items per page, 0 is start index for 1 page, 20 is start index for second and so on.
Step 3: Show pagination on your page
echo $pagination->getPagesLinks();
echo $pagination->getPagesCounter();