The Scenario -
I'm assuming that i have thousands of Post and each post have 1-1000 comments.
well i can simply paginate Post by 10 or 20 with its comments.
This will return paginated posts with its comments.
$Posts = \App\Post::where('published',true)->with('comments')->paginate(10);
The problem is that I want to paginate comments so each posts return 4 comments. Then how do I call other comments if a posts have more then 4 comments?
I think the best way is to store posts on a separate table. For example create a post table using the following migration
Schema::create('posts', function(Blueprint $table){
$table->increments('id');
$table->string('title');
$table->timestamps();
});
Now create comments table using migration:
Schema::create('comments', function(Blueprint $table){
$table->increments('id');
$table->integer('post_id')->unsigned();
$table->string('name');
$table->text('comment_body');
$table->timestamps();
$table->foreign('poem_id')->references('id')->on('posts');
});
Create a one to many relations between these two tables as follows:
For Post model,
class Post extends Model
{
...
public function comments(){
return $this->hasMany('App\Comment');
}
}
and for the Comment model,
class Comment extends Model
{
protected $fillable = ['post_id', 'c_body', 'name'];
public function posts(){
return $this->belongsTo('App\Poem', 'post_id');
}
}
At this point, after populating the two database tables: posts and comments, you can then query them separately in your controller.
To do that, add the two lines at the top of your controller:
use App\Post;
use App\Comment;
now in any method of your choice in that controller, query posts and comments for each most as follows
public function index(){
$posts = Post::where('published',true);
$comments = Post::where('published',true)->comments;
// pass this data to your view
return view('anyview', compact('posts', 'comments');
}
My answer is long, though i tried to make it short. Hope it helped.
Related
I have a comments table which in turn can contain replies to comments via the parent_id table.
Attached, is the migration
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->string('comment');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('commentable_id');
$table->string('commentable_type');
$table->unsignedBigInteger('parent_id')->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('parent_id')->references('id')->on('comments')->onDelete('cascade');
$table->timestamps();
});
Attached, Model Relationship
public function replys()
{
return $this->hasMany(Comment::class, 'parent_id');
}
I would like to bring all comments and their replies sorted by id desc.
This way I get the parents back correctly but I need to sort the replys as well.
$comments = $this->post->comments()->with('user', 'replys')->get();
$comments = $comments->sortByDesc('id')->values()->all();
How should I do it? thank you very much
I think it's possible to do it in 2 ways:
1 - You can add an orderBy method directly to the relation
public function replys()
{
return $this->hasMany(Comment::class, 'parent_id')->orderBy('created_at');
}
2 - You can chain the orderBy Method on a controller or wherever you're using the relation.
class Controller
{
public function index()
{
$replies = Model::find(1)->replys()->orderBy('created_at')->get();
}
}
Please, try this solution and check if it works for you!
I have created two models called video and file using Laravel 6.
A video can have only one file.
This is the relationship I created:
Video
public function file() {
return $this->hasOne('App\File');
}
File model
public function video() {
return $this->hasOne('App\Video');
}
If I loop all videos then I get the related media
#foreach($videos as $video)
{{$video->link->media}}
#endforeach
If I go to the related video single page it doesnt work.
{{$video->link->media}
Here the route:
Route::get('/video/{slug}', 'HomeController#singleVideo')->name('single');
I get following error:
Trying to get property 'media' of non-object
I also add the table Schema:
Schema::create('files', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('media')->default('none');
$table->unsignedBigInteger('video_id');
$table->timestamps();
});
Schema::create('videos', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title',128);
$table->string('slug')->unique();
$table->text('description');
$table->string('url',247);
$table->string('category',128);
$table->unsignedBigInteger('views')->default(200);
$table->string('video_youtube_status')->default('off');
$table->string('video_status')->default('off');
$table->string('status')->default('off');
$table->timestamps();
});
Model Video
protected $guarded = [];
public function file() {
return $this->hasOne('App\File');
}
....
According to the Laravel documentation, the relation "hasOne" is not applied in this way, the primary model(let's say it's File) will have hasOne like in your code, but the secondary Model will have the Inverse Of The Relationship, which is 'belongsTo' so, in your video Model you should write:
public function file() {
return $this->belongsTo('App\File','file_id');
}
This will allows you to access to the entities like:
$video->file->some_property
$file->video->another_property
and another major problem in your videos table:
this table must have a foreign key to files table, which means:
in your videos migration you should add :
$table->unsignedBigInteger('file_id')->nullable(false);
$table->foreign('file_id')->references('id')->on('files');
According to Laravel documentation
You should implement the use of belognsTo relationship
and your query to get your results set must include the use of method with()
$users = User::with('podcasts')->get();
foreach ($users->flatMap->podcasts as $podcast) {
echo $podcast->subscription->created_at;
}
I am trying to select the picture with the most likes within a specific category from my database. I have a database table storing the pictures and a table storing the likes. The pictures table is related to likeable table through a hasMany polymorphic relationship.
Like model:
public function likeable()
{
return $this->morphTo();
}
Picture model:
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
Home Controller:
Picture::where('picture_type', 'food')->orderBy(likes(), 'desc')->first();
Likeable Migration:
public function up()
{
Schema::create('likeable', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('likeable_id');
$table->string('likeable_type');
$table->timestamps();
});
}
So far, the above line of code, in my home controller returns an error. From what I understand, the likes method has to be called on a specific instance. However, I do not know how to implement this all the while keeping my where clause.
Thank you for your help.
I assume you are wanting to order pictures by the most likes.
In which case, you want something like this:
Picture::withCount('likes')->where('picture_type', 'food')->orderBy('likes_count', 'desc')->first();
I have created two table to store post information:
Posts table where I store overall information except categories.
Migration file of each table looks like this:
posts
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->string('slug');
$table->longText('excerpt');
$table->longText('description');
$table->tinyInteger('feature')->default(1);
$table->enum('status',['publish','draft']);
$table->string('image');
$table->timestamps();
});
post_categories
Schema::create('post_categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('category_id')->nullable();
$table->unsignedBigInteger('post_id')->nullable();
$table->foreign('category_id')->references('id')->on('categories');
$table->foreign('post_id')->references('id')->on('posts');
$table->timestamps();
});
Now, I have following function in PostCategory model:
public function post(){
return $this->belongsToMany(Post::class);
}
Now, when I try to fetch data using following:
\App\Models\PostCategory::find(5)->post()->orderBy('created_at')->get();
I get call to member function post() on null
What should I do to get post with the category 5?
You misunderstood some concepts.
Here your relationship is between post and categories.
In post Model
public function categories(){
return $this->belongsToMany(Category::class,'post_categories','post_id','category_id');
}
In the Category model
public function posts(){
return $this->belongsToMany(Post::class,'post_categories','category_id','post_id');
}
Now, You're free to access posts from category and categories from post.
$post = Post::with('categories')->where('id',5)->first();
By this, you'll get a post with its categories.
$category= Category::with('posts')->where('id',5)->first();
By this, you'll get category with its posts.
Check more detail how many to many work
Edit:-
If by using post you want to make a condition in the categories then.
$post = Post::with('categories')->whereHas('categories', function($q){
$q->where('id',5);
})->get();
I create a table post__post_category_relations to save categories of post.
Schema::create('post__post_category_relations', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('post_id')->unsinged();
$table->integer('category_id')->unsinged();
$table->timestamps();
});
At blade template edit post, I want show list categories of post.
In Post model I wrote:
public function categories(){
return $this->belongsTo(PostCategoryRelations::class,'id','post_id','category_id');
}
But it only return one category. Can you show me how to show all categories? Thank so much!
This looks similar to Many To Many approach between posts and categories. And a junction table which connects post and category table should have post_id, category_id and other columns are not required like id , timestamps() i guess you won't be using them in your application.
Migration would minimize to
Schema::create('post__post_category_relations', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->integer('post_id')->unsinged();
$table->integer('category_id')->unsinged();
});
For many to many you can add definitions in your models like
class Post extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class, 'post__post_category_relations', 'post_id');
}
}
class Category extends Model
{
public function posts()
{
return $this->belongsToMany(Post::class, 'post__post_category_relations', 'category_id');
}
}
If you still want to keep other columns from junction table post__post_category_relations you can access them by defining as pivot attributes in your model like
class Post extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class, 'post__post_category_relations', 'post_id')
->withPivot('id','cols')
->as('post__post_category_relation_cols');
}
}