Laravel Eloquent belongsTo filtering elements - php

To start, my models look something like this:
class Post extends Eloquent {
public function url() {
return $this->belongsTo('Url', 'url_id');
}
}
class Url extends Eloquent {
public function category() {
return $this->belongsTo('Category', 'category_id');
}
}
The relationship that is intended is that a Post has a Url and a Url has a Category, so a Post should implicitly have a Category. I am trying to write an Eloquent query to filter posts by category_id. I have a variable that is being passed into a GET route that represents the category_id and want to filter all posts by the category_id that is passed to that route.
Any help is appreciated.
Thanks in advance.

Related

is there a way to get all related data in laravel connection?

I have two tables named posts and categories. these two tables have one-to-many relationship and I wrote them in models like this:
class Post extends Model
{
...
public function category()
{
return $this->belongsTo(Category::class, 'category_id', 'id');
}
...
}
class Category extends Model
{
...
public function posts()
{
return $this->hasMany(Post::class, 'category_id', 'id');
}
...
}
This is work fine when I use $post = Post::find($id) in controller and retrieve one post and use $post->category to get category of this post. but what if I want to retrieve all posts and their categories together?
I mean, let's assume that I have 10 posts in DataBase and I have $posts = Post::get(); to get all posts. now, how I can get categories of each post?
One way is loop! for example:
foreach($posts as $post) {
$post['category'] = $post->category;
}
return response()->json($posts);
Yeah! I want to response in Json and I forgot to say earlier, sorry.
Is there better way to do this? I searched and I got nothing by my search. I'll be appreciated if anyone response to my problem. :)
The easiest way to include categories in each post model with json, is simply including it using with() and it will automatically transform it.
return Post::with('category')->get();
In Laravel you do not have to wrap models or collections in response->json(); it will automatically do that.

Retrieve post by category id laravel

I want to retrieve all post with given category,
i am developing api, at input i will receive category name, and then i want to retrieve that category by its id in posts table,i want to do this because if some changed category name in the future i dont have to change that in my code
i have create like this
PostController.php
public function getPostsByCategory(Request $request)
{
$posts=Posts::where('category',$request->category)->get();
return response()->json(['posts'=>$posts]);
}
Post model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Posts extends Model
{
protected $fillable = [
'post_title','post_description', 'category', 'user_id',
];
Category Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Posts_Category extends Model
{
}
can you please help me with this, please suggest me any idea
i think you are looking for with eager load function
You must store category id not the name of the category..
class Posts extends Model
{
protected $fillable = [
'post_title','post_description', 'category_id', 'user_id',
];
public function category()
{
return $this->belongsTo(Posts_Category::class, 'category_id', 'id');
}
}
use as
$posts = Posts::where('category_id',$request->category)->with('category')->get();
If you really want to search by name
$posts = Posts::whereHas('category', function ($q) {
$q->where('category_name', 'like', "%{$request->category}%");
})->get();
You can fetch the category by its name first, and then filter posts by category id
public function getPostsByCategory(Request $request)
{
$category = Posts_Category::whereName($request->category)->firstOrFail();
$posts=Posts::where('category',$category->id)->get();
return response()->json(['posts'=>$posts]);
}
you're doing this the wrong way from the get go. best practice is to store category_id in posts table, of course this is only if you need a one-to-many relation between posts and categories table. plus I wouldn't recommend to break the convention of naming models unless you have no other way. I suggest you to read this section more thorough
https://laravel.com/docs/5.6/eloquent-relationships
Please i need a fix solution to this, i want to fetch all the latest post from a specific category in my laravel blog project
These are my models
Category model
public function posts()
{
return $this->belongsToMany('App\Post')->withTimestamps();
}
Post model
public function categories()
{
return $this->belongsToMany('App\Category')->withTimestamps();
}
What's they next thing to do?
please help
$posts = Posts::where('category_id', $category->id)->get();

Laravel count-function in Model, then sortBy count()

I am trying to Order the Posts table by the number of votes a Post has got.
The votes are stored in an other table
(Votes: post_id, user_id, vote_type)
Post-Model:
class Post extends Model
{
public function user()
{
return $this->hasOne(User::class);
}
public function votes()
{
return DB::table('votes')->where('post_id','=',$this->id)->sum('vote_type');
}
}
The votes functions returns the number of votes a post has recieved(The Votes a stored in a seperate table)
Now I am trying to order all the Posts by the number of votes they have got.
Post::get()->sortBy('votes');
This returns follwing Error:
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
I would be thankful about any help to fix this!
give it a try
Post::get()->sortBy(function($query){
return $query->votes();
});
Alternative
You can use withCount() as it will place a {relation}_count column on your resulting models.
Post::withCount(['votes'])
->orderBy('votes_count')
->get()
For Pagination
Refer docs for more details on paginations
Post::withCount(['votes'])
->orderBy('votes_count')
->paginate();
Add the following function in your Post Model
protected static function boot()
{
parent::boot();
static::addGlobalScope('voteCount', function ($builder) {
$builder->withCount('votes');
});
}
Now, each of your post model will always have a voteCount value and You can sort on that.
In your controller, use:
Post::get()->sortBy('voteCount');
Keep in mind that this will always return a votesCount with the PostModel, but I'm assuming it will be required as it usually does in this kind of applications.
If you want to sort votes as a attribute you have to to make it to be attribute by adding getVotesAttribute() method in your Post Model.
class Post extends Model
{
public function user()
{
return $this->hasOne(User::class);
}
public function getVotesAttribute()
{
return DB::table('votes')->where('post_id','=',$this->id)->sum('vote_type');
}
}

Calling a list of posts based on category

Im trying to call a list os posts based on a category, but it isnt working, is giving me the error:Non-static method App\Category::posts() should not be called statically, assuming $this from incompatible context.
I already tried calling from both sides, going threw the post model methdos or categories, but same error message. Can figure out what im doing wrong.
Database:
Posts:
-id;
-title;
-text;
Categories:
-id;
-name;
-internal_name;
category_post:
-id;
-post_id;
-category_id
Controller:
public function categoryPostList($category)
{
$category = Category::posts()->where('internal_name',$category)->first();
$posts = Post::categories()->where('category_id',$category->id)->get();
dd($posts)
}
Model Post:
class Post extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
Model Category:
class Category extends Model
{
public function posts()
{
return $this->belongsTo('App\Post');
}
}
First of all if relationship is many to many (you're using pivot table) your relation should be belongsToMany(), but not belongsTo().
To load relation You should use with() method. For example, if you want to load one category with all it's posts:
Post::where('category_id', $category->id)->with('categories')->first();
You can use whereHas as:
$category = Category::where('internal_name',$category)->first();
$posts = Post::whereHas('categories', function($q) use($category) {
$q->where('category_id',$category->id);
})->get();
Or
$category = Category::where('internal_name',$category)->first();
$posts = $category->posts;
The whereHas method is used to put "where" conditions on your has
queries.

Laravel Eloquent ORM relationship naming conventions

When defining an inverse relation in Eloquent, do you have to name your dynamic property the same as your related model?
class Book extends Eloquent {
public function author()
{
return $this->belongsTo('Author');
}
}
$books = Book::all()
foreach ($books as $book) {
echo $book->author->firstname;
}
In the above example, do I have to call this method author or can I name it something else? I tried to name it to something else (just out of curiosity) but it then returns null hence the errors "Trying to get property of non-object".
EDIT: I got it to work by passing the foreign key to belongsTo, like this:
class Book extends Eloquent {
public function daauthor()
{
return $this->belongsTo('Author', 'author_id');
}
}
$book = Book::find(55);
dd($book->daauthor);
Can someone explain why?
The method belongsTo tries to determine the attribute which links to the Author model. To accomplish this Laravel uses the function name of the caller.
So in your code Laravel sees the daauthor function and tries to use the attribute daauthor_id in the books table to fully your request. As your books table does not have this attribute it fails.
By setting the $foreignKey on the method you can override the default behaviour:
public function daauthor()
{
return $this->belongsTo('Author', 'author_id');
}
For more details check out the source code of \Illuminate\Database\Eloquent\Model.

Categories