I have a list of books in my database and each book have chapters. my models are
Books.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
protected $guarded = [];
public function chapters()
{
return $this->hasMany(Chapter::class);
}
}
Chapter.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Chapter extends Model
{
protected $guarded = [];
public function book()
{
return $this->belongsTo(Book::class);
}
}
How can make a page that will show the books in order manner from latest to old?
Also, the order is based on the chapter being updated or added in a book. If one of the old books is being updated by adding 1 more chapter, that book will show first on the most recent updated books.
Thank you!
I am using Laravel 5.6 and Vue JS
Option 1:
You should use joins in query:
$books = Books::select('books.*')
->leftJoin('chapters', 'chapters.book_id', '=', 'books.id')
->groupBy('books.id')
->orderByDesc('chapters.updated_at')
->get();
Option 2:
If you don't need paginate and want to show all books in one page, you can try to sort a collection by relation value.
Add latestChapter relation:
public function latestChapter()
{
return $this->hasOne(Chapter::class)->orderByDesc('updated_at');
}
Get and sort:
$books = Books::with('latestChapter')->get();
$books = $books->sortByDesc(function($item){
return $item->latestChapter ? $item->latestChapter->updated_at : '1970-01-01';
});
Related
I am using Laravel 8.X and eloquent to develop a web app.
I have a pivot table 'portal_event_users'
I am trying to add a belongsToMany relationship to the portal_users in the model of portal_event_users table.
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class EventUser extends Model
{
use HasFactory;
protected $table = 'portal_event_users';
public function users()
{
return $this->belongsToMany(User::class);
}
public function events()
{
return $this->belongsToMany(Event::class);
}
}
I have the following statements in the controller
$eventusersobj = \App\Models\EventUser::select('*')
->where('event_id', '=', $event_id)
->get();
$response = $eventusersobj->users->keyBy('id');
It is returning the following error
Property [users] does not exist on this collection instance.
Can someone please advice on how can i change this error?
Thanks in advance
As it returns a collection, you can use pluck()
$eventusersobj->pluck('users')->each(function($user){
$user->keyBy('id');
})
How can I get all the records from the relationship? I mean not only the related records, but also the rest.
Let's say I have a post which belongs to some category. If I want to change the category of this post I need a list of all available categories. Can I get this list from the relationship?
The Post model:
class Post extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
The Category model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function posts()
{
return $this->hasMany('App\Post');
}
}
In the PostsController I tried:
$postModel->category->find('all'); // Returns null
$postModel->category->all(); // Returns only the related categories
I know I can simply use the Category model in the PostsController, but I prefer to do it using the relationship.
If you feel you must use the relationship to get to the other model you could try:
$categories = $post->category()->getRelated()->get();
I'm kinda lost one this one, I really can't find the problem, I have been watching a lot of questions all over the web but still can't seem to put this working properly.
I have two tables, the tabelaAngaricao table and the tabelaFotos table with a relationship of one-to-many, meaning that a tabelaAngariacao can have many tabelaFotos, and tabelaFotos as a angariacaoid(foreign key) so my tabelaAngariacao model is:
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\TabelaFotos;
class TabelaAngariacao extends Model
{
protected $table = 'tabelaAngariacao';
public function TabelaFotos()
{
return $this->hasMany(TabelaFotos::class, 'angariacaoid');
}
}
and my tabelaFotos model is:
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\TabelaAngariacao;
class TabelaFotos extends Model
{
protected $table = 'tabelaFotos';
public function TabelaAngariacao()
{
return $this->belongsTo('App\TabelaAngariacao');
}
}
What I want is to get all results joined by the angariacaoid, so in my controller I have:
public function index()
{
$results = DB::table('tabelaAngariacao')
->leftJoin('tabelaFotos', 'tabelaAngariacao.id', '=', 'tabelaFotos.angariacaoid')
->select('tabelaAngariacao.*')
->get();
}
Could someone help me on finding the problem? What is that I'm doing wrong?
You don't need to add select. Try following
$results = DB::table('tabelaAngariacao')
->leftJoin('tabelaFotos', 'tabelaAngariacao.id', '=', 'tabelaFotos.angariacaoid')
->get();
The above script will give you columns from both tables.
And probably you don't need to use DB::table, you can use Eloquent Queries instead, since you've defined your relationsips
You can try it by doing this.
$results = TabelaFotos::with('TabelaAngariacao')->get();
Here is how it works
$results = ModelName::with('relationship_in_model_name')->get();
Hope it works
I'm learning VueJS and trying to develop a forum system
I am trying to get the latest post from the threads relationship per forum in my forum model.
This is my Forum Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Forum extends Model
{
public $table = 'forums';
public $timestamps = false;
public function threads() {
return $this->hasMany('App\Thread')->orderBy('id', 'DESC');
}
public function getFirstThread() {
return $this->threads()->first();
}
}
So I thought maybe this would work but it didn't
Forum::with('getFirstThread')->get();
Any idea's how I can achieve this without having to loop through everything and getting first thread for every result?
TLDR: Trying to get the latest Thread per Forum without having to loop through all forums.
You can $append the method results by using getMethodNameAttribute()
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Forum extends Model
{
public $table = 'forums';
public $timestamps = false;
protected $appends = ['firstthread'];
public function threads() {
return $this->hasMany('App\Thread')->orderBy('id', 'DESC');
}
public function getFirstThreadAttribute() {
return $this->threads()->first();
}
}
You could define another mapping as hasOne in your model to get latest thread per forum, Call latest('id') on your mapping and pass id as a column to sort
public function latest_threads() {
return $this->hasOne('App\Thread')->latest('id');
}
Then you can easily eager load your relationship as
Forum::with('latest_threads')->get();
So I have two tables: posts and categories. It is a many-to-many relationship: A post has many categories and a category belongs to many posts.
Here are the models that describe their relationships:
Category.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $fillable = ['name', 'slug'];
public function posts()
{
return $this->belongsToMany('App\Post');
}
}
Post.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function categories()
{
return $this->belongsToMany('App\Category');
}
}
I want to get all posts that have a particular category: tips
Here is what I tried:
$tips = Category::where('name', 'Tips')->posts()->with('categories')->take(4)->get();
I don't know the level of ignorance in this query, but I honestly expected it to work. It didn't.
I'll appreciate any help.
It's really as simple as:
$tipsCategory = Category::where('name', 'tips')
->get();
$posts = $tipsCategory->posts;