Pagination for nested items in the Laravel relationship - php

I am very beginner in Laravel. I use in my project Laravel 5.8.
I have this code:
class ForumCategory extends Model
{
use scopeActiveTrait;
protected $quarded = ['id'];
protected $fillable = ['company_id', 'enable', 'name', 'url_address', 'enable'];
public $timestamps = false;
public function themes()
{
return $this->hasMany('App\ForumPost', 'id_category', 'id')->where('parent_id', '=', null);
}
public function lastPost()
{
return $this->themes()->orderBy('id', 'desc')->first();
}
}
class ForumPost extends Model
{
use scopeActiveTrait;
protected $quarded = ['id'];
protected $fillable = ['company_id', 'id_category', 'parent_id', 'user_id', 'date', 'title', 'content', 'url_address', 'enable'];
public $timestamps = true;
protected $table = 'forum';
public function category()
{
return $this->belongsTo('App\ForumCategory', 'id_category');
}
public function author()
{
return $this->belongsTo('App\User', 'user_id');
}
public function postCount()
{
return $this->hasMany('App\ForumPost', 'parent_id', 'id')->where('parent_id', '!=', null)->count();
}
}
When I run this function:
ForumCategory::with('themes')->orderBy('name', 'asc')->paginate(35);
I have pagination only for pagination.
When I display the results of this function:
#foreach ($forums as $forum)
Welcome in {{ $forum->name }}<br/>
#foreach ($forum->themes as $post)
Post: {{ $post->title }}
#endforeach
<div class="paginationFormat"></div>
<div class="text-right">{{ $forums->links() }}</div>
#endforeach
I can display pagination for $ forums.
I would also like to display the pagination for $ post (data from relationships). How can this make it?

Maybe you could take a look at the Pagination documentation and examples from the Laravel docs: https://laravel.com/docs/5.8/pagination
The Laravel docs are a great place to start since everything is documented very well and there are a lot of examples.
If you want to add a page that paginates all posts, just return a view with Post::sortBy('name')->paginate() and use $posts->links().

If you have to do pagination an Eager loading constraint - it won't work, else you would have to use the constraint to execute the query as the parent Model/Object.
Refer to this link, go through it. https://laracasts.com/discuss/channels/laravel/paginate-constrained-eager-load
Use Themes as the Parent Object and paginate accordingly depending on the relationship defined in the models.
Themes::with(['forumCategory'=>function(query){
//condition here....
}])-paginate(10);
Or alternatively you have multiple paginations in one view but passed separately:
$themes = Themes::with('forumCategory')-paginate(10);
$forums = ForumCategory::with('themes')->orderBy('name', 'asc')->paginate(35);
Same issue in this link: Laravel Multiple Pagination in one page
And you might have to write an anonymous helper function to handle relative actions that involve both Models somewhere in your application.
Alternatively you could use lazyEager loading on the post model. So while you have this in your code, you could do lazy eager loading on the themes.
$forums = ForumCategory::with('themes')->orderBy('name', 'asc')->paginate(35);
$forums->load(['themes' => function($query) {
$query->take(5);
}]);
you could also utilize the loadCount() function.

Related

Eloquent relationship give [ticket_id] does not exist on this collection instance laravel

I am have some issue with eloquent relationship my first time working with it, after selecting and displaying list of selected events, I want to also select the ticket_id base on the event_id common between both(events and events_ticket) table, thanks for the help
Error Showing ->
Trying to get property 'ticket_id' of non-object (View: C:\wamp64\www\mahive\resources\views\tickets\index.blade.php)
Both Model
class EventsTicket extends Model
{
public $table = "events_ticket";
use HasFactory;
protected $fillable = [
'event_id',
'ticket_id',
'ticket_name',
'ticket_amount',
'ticket_sold',
];
public function event() {
return $this->belongsTo('App\Models\Event');
}
}
class Event extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'event_id',
'event_name',
'event_category',
'event_type',
'event_mode',
'event_description',
'event_image'
];
public function userModel() {
return $this->belongsTo('App\Models\User');
}
public function eticket() {
return $this->hasMany('App\Models\EventsTicket');
}
}
Controller
public function index()
{
$events = Event::where('ticket_statue', 'active')->with('eticket')->get();
return view('tickets.index', ['event_data' => $events]);
}
View
#foreach($event_data as $event)
{{ ucwords($event->event_name) }}
{{ $event->eticket->ticket_id }}
#endforeach
In this code every Event has many eticket. Try this:
#foreach($event_data as $event)
{{ ucwords($event->event_name) }}
{{ optional($event->eticket->first())->ticket_id }}
#endforeach
Use optional because there may not be any etickets.

Single category and multi categories

I have articles witch can have one single category that's Main category with category_id.
and additional multi categories with pivot table everything working it's stores but i can't get data on web i'm only getting articles with single category how can i get articles with single and with multi categories in one variable?
article model:
public function category()
{
return $this->belongsTo(AllCategory::class, 'category_id', 'id');
}
public function manyCategories()
{
return $this->belongsToMany(AllCategory::class, 'articles_categories', 'article_id', 'category_id')
->using(ArticleCategory::class);
}
AllCategory model:
public function articles()
{
return $this->hasMany(Article::class, 'category_id', 'id')->orderBy('published_at', 'Desc');
}
public function manyArticles()
{
return $this->belongsToMany(Article::class, 'articles_categories', 'category_id', 'article_id')
->using(ArticleCategory::class);
}
and pivot table:
class ArticleCategory extends Pivot
{
use HasFactory;
public $table = 'articles_categories';
protected $fillable = [
'article_id', 'category_id'
];
protected $guarded = ['*'];
}
and in controller i'm getting like this
$offsetPage = ($page - 1);
$perPage = 24;
$category = AllCategory::bySlug($slug);
if (! $category) {
abort(404);
}
$categoryArticles = $category->articles()
->with('manyCategories')
->skip($perPage * $offsetPage)
->take($perPage)
->get();
I'm getting single category articles with articles() and i'm trying to get manycategories to ->with but it's only getting me single category articles what i'm doing wrong?
You could create an accessor that would add the main category to the Collection of categories that the Article belongs to.
public function getCategoriesAttribute()
{
// adding the main category (if there is one) to the Collection
return (clone $this->manyCategories)->when(
this->category,
fn ($collection, $category) => $collection->prepend($category)
);
}
Controller:
$categoryArticles = $category->articles()
->with(['category', 'manyCategories'])
->skip($perPage * $offsetPage)
->take($perPage)
->get();
View:
#foreach ($articles as $article)
#foreach ($article->categories as $category)
...
#endforeach
#endforeach
Laravel 8.x Docs - Eloquent - Mutators & Casting - Defining an Accessor
Laravel 8.x Docs - Collections - Available Methods - when
Laravel 8.x Docs - Collections - Available Methods - prepend

Laravel Eloquent join throug pivot tables

Unfortunately, I don't have that much experience with Eloquent yet. I try to create a query from three tables which have two pivot tables.
My tables:
My Models:
Player
class Player extends Model
{
protected $table = 'players';
protected $fillable = [
'name'
];
public function layout(){
return $this->belongsToMany('App\Layout', 'layout_player', 'player_id', 'layout_id');
}
public function information(){
return $this->hasMany('App\Information', 'player_id');
}
}
Layout
class Layout extends Model
{
protected $table = 'layouts';
protected $fillable = [
'name'
];
public function player(){
return $this->belongsToMany('App\Player', 'layout_player', 'layout_id', 'player_id');
}
public function item(){
return $this->belongsToMany('App\Item', 'item_layout', 'layout_id', 'item_id');
}
}
Item
class Item extends Model
{
protected $table = 'items';
protected $fillable = [
'name'
];
public function layout(){
//return $this->hasOne(Layout::class);
return $this->belongsToMany('App\Layout', 'item_layout', 'item_id', 'layout_id');
}
}
Starting from the player, I want to retrieve the current player, all layouts and the corresponding items. Unfortunately I can't do it.
I call up the player and layouts as follows:
Player::where('id',1)->with('layout')->get();
How do I additionally get all items in the query?
You made a relationship perfectly. Now from Player to layout you're getting it with('layout'). Try it.
$players = Player::with('layout.item')->where('id',1)->get();
It'll give you players along with layouts with items.
If I understand your question, I think you are almost there.
Add this to Player model too, like other methods you did.
public function contents(){
return $this->belongsToMany('App\Content');
}
To get all contents regarding a player write these in controller and pass it to view file.
$player = Player::findOrFail(1);
return view('path.to.file_name',compact('player'));
In view file
//get all contents of a player
#foreach($player->contents as $content)
<p>{{ $content->text}}</p>
#endforeach
//get all layouts of a player
#foreach($player->layout as $layout)
<p>{{ $layout->name}}</p>
#endforeach
//get all items of a player
#foreach($player->layout as $layout)
<p>{{ $layout->name}}</p>
#foreach($layout->item as $item)
<p>{{ $item->name }}</p>
#endforeach
#endforeach
Thank you very much for the quick answer. Unfortunately this does not solve my problem.
I call the PlayerController via the api route and need all objects of the player in the form as return:
player
layout
item
public function show($id)
{
$player = Player::findOrFail($id);
//$player = Player::where('id',$id)->with('layout')->get();
return $player;
}
I get this response:
{"id":1,"name":"Testplayer","created_at":"2019-09-22 15:53:07","updated_at":"2019-09-22 15:53:07"}
But I need also the layouts and Items.
I hope you still understand my bad English.;)

Laravel get records from model with certain data and relations

I have model Post:
protected $with = ['user']
public function user() {
return $this->belongsTo(User::class);
}
When on controller I set only title and image:
$posts = Post::get(['title', 'image']);
Relation user return me null.
#foreach($posts as $post)
User: {{ $post->user->name }} //null
#endforeach
Why? If I delete array from get method, then relation is working, If I set array, then relation user return me null. Please help.
With Post::get(['title', 'image']); you are specifying that you only need these columns.
If you want to use that approach,
$posts = Post::with('user')->get(['title', 'image']);
Or you can include user not with protected $with property, but instead protected $appends to always add that in your model as a default field
// In Post Class:
protected $appends = "user";
// Then this should work
$posts = Post::get(['title', 'image', 'user']);

Eloquent Relationship using DB Laravel

I've got 4 tables.
Clients
Jobs
Rounds
Job_Rounds
I've created the following relationships:
Clients > Jobs
Jobs > Rounds
Here are my models
Client
class Client extends Model
{
protected $dates = [
'created_at',
'updated_at',
'last_done'
];
public function Jobs()
{
return $this->hasMany('App\Job','client_id');
}
}
Job
class Job extends Model
{
protected $dates = [
'created_at',
'updated_at',
'last_done',
'due_date'
];
public function Round()
{
return $this->belongsTo('App\Round','round_id');
}
public function Client()
{
return $this->belongsTo('App\Client','client_id');
}
}
Round
class Round extends Model
{
protected $dates = [
'created_at',
'updated_at',
'date_scheduled',
'date_finished'
];
public function Clients()
{
return $this->hasMany('App\RoundClients', 'round_id');
}
public function Jobs()
{
return $this->belongsToMany('App\Job', 'job_rounds', 'round_id', 'job_id');
}
}
JobRound
class JobRound extends Model
{
public $timestamps = false;
}
On my round view I'm outputting all the jobs not in the round and all the jobs in the round.
I'm doing this by creating a DB::table to perform the check - see my code:
public function show($id)
{
$round = Auth::user()->rounds()->FindOrFail($id);
$not = DB::table('jobs')->whereNotIn('id', function($query) use($round) {
$query->select('job_id')
->from('job_rounds')
->where('round_id', $round->id);
})->get();
$are = DB::table('job_rounds')
->join('jobs', 'job_rounds.job_id', '=', 'jobs.id')
->select('job_rounds.*', 'jobs.*' ,'job_rounds.id as DAS')
->where('job_rounds.round_id',$round->id)
->get();
return view('app.round',compact('round','not','are'));
}
The problem I have is in my view, the Client to Job relationship for outputting the client name won't work as I have created my own DB query, I'm outputting the client information on my view like
Jobs on the round
#foreach($are as $job)
{{ $job->client->first_name }}
#endforeach
Jobs not on the round
#foreach($not as $job)
{{ $job->client->first_name }}
#endforeach
I get the error:
Variable $client not found etc
Your relationships methods starts with uppercase (which btw, you should change to start with lowercase for standard).
The problem is that your methods and the ones you call are not the same, you need to use the same case in both, like this...
#foreach($are as $job)
{{ $job->Client->first_name }}
#endforeach
Update
Besides the fact of the case, you are not using Eloquent.
You are just using the database query builder directly.
In order to use Eloquent you must use the Model class static methods, like this:
Job::whereNoIn('id', .....
Instead of this:
DB::table('jobs')->whereNotIn('id', ....
DB::table does not return an App\Job class. For this reason you cannot use relationship. ( $job->Client... )
Try make the queries using Eloquent instead.For more details, follow this offical Laravel documantation.

Categories