Retrieve post by category id laravel - php

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();

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.

Laravel HasMany relationship not giving expected result

I have three table with following columns:
posts table
id
author
title
content
seen
post_img
post_category table
id
category_id
post_id
categories table
id
category
I created post_category table to store post catergories. I wanted to get posts that have specific category. And i created my PostModel associated with posts table like this:
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\AuthorModel;
use App\Models\PostCategoryModel;
use App\Models\CategoryModel;
class PostModel extends Model
{
use HasFactory;
protected $table = 'posts';
public function getAuthor(){
return $this->hasOne(AuthorModel::class, 'id', 'author');
}
public function getCategories(){
return $this->hasMany(PostCategoryModel::class, 'post_id', 'id');
}
}
After i got the PostCategoryModel from calling getCategories method, i created PostCategoryModel associated with post_category table like this:
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\CategoryModel;
use App\Models\PostModel;
class PostCategoryModel extends Model
{
use HasFactory;
protected $table = 'post_category';
public function getCategory(){
return $this->hasMany(CategoryModel::class, 'id', 'category_id');
}
public function getPosts(){
return $this->belongsToMany(PostModel::class, 'id', 'post_id');
}
}
But here is the problem, when i call PostModel::getCategories in my Controller method it gives me this error: Undefined constant App\Models\PostModel::getCategories. How can i get categories of a post in my case?
Laravel version: Laravel Framework 8.22.1
PHP version: PHP 8.0.1 (cli) (built: Jan 5 2021 23:43:33) ( NTS Visual C++ 2019 x64 )
As I know you can't call relation methods like static method cause it needs an instance to check its id and match with other table. You can use something like this:
$cats = PostModel::find(1)->getCategories();
But it's just an example and in real application you probably use route model binding or anything else.
I believe you have a many to many relation between post and category, If so then you don't need intermediate model for junction table post_category unless you have another specific reason to introduce model for this table.
For many to many relationship you need to adjust your post and category models as
class Post extends Model
{
//.. Other methods
public function categories(){
return $this->belongsToMany(Category::class, 'post_category', 'post_id', 'category_id');
}
}
class Category extends Model
{
//.. Other methods
public function posts(){
return $this->belongsToMany(Post::class, 'post_category', 'category_id','post_id');
}
}
I wanted to get posts that have specific category
Once you have proper relations in place you can get posts for specific category using whereHas()
$posts = Post::whereHas('categories', function (Builder $query) use($category_id) {
$query->where('id', $category_id);
})->get();
How can i get categories of a post in my case?
To get categories associated with posts you can eager load them as
$posts = Post::with('categories')
->whereHas('categories', function (Builder $query) use($category_id) {
$query->where('id', $category_id);
})->get();

how to get desired column from other table

there are two tables products and categories, that I created by PHPMyAdmin.
In the products table, it has a column name prd_category that has the foreign key of table categories named cat_id(primary key of categories table).
i am quite new in laravel
i want return all data from product table with category name(cat_name) from another table
//here is my controller
use App\Models\product;
class items extends Controller
{
public function sample(){
return product::all();
}
}
//route
Route::get('/',[items::class,'sample']);
//model for products table
class product extends Model
{
use HasFactory;
function category(){
return $this->hasOne('App\Models\category','cat_id','prd_id');
}
}
//model for category
class category extends Model
{
protected $table='categories';
use HasFactory;
}
pls help and thanks in advance..
you can use this code:
$products = product::whereHas('category',function($q)use($cat_name){
$q->where('name',$cat_name)
})->get();
or :
$categories = Category::where('name',$cat_name)->get()->pluck('id')->toArray()
$products = product::whereIn('category_id',$categories)->get();
Are you sure that one-to-many relation is correct? If a product can belong to many categories, you need to use many-to-many relations. Furthermore, if something else belongs to categories you should use many-to-many polymorphic relations. But let's go with one-to-many.
First, the relation function in Product.php looks incorrect. I think products should belong to a category.
function category(){
return $this->belongsTo('App\Models\Category','cust_name','name');
}
Then you need to define reverse relation in Category.php
function products(){
return $this->hasMany('App\Models\Product','cust_name','name');
}
When you define the relations properly, all you need yo do is to fetch data in controller:
use App\Models\Category
...
Category::with('products')->get();
you can use relationship with forign key like pro_id
function category(){
return $this->belongsTo('App\Models\Category','pro_id');
}
function products(){
return $this->hasMany('App\Models\Product','id');
}
$cat = Category::with('products')->all();
in Blade :
{{ $cat->products->cat_name; }}

Laravel queries (function find() ) in Laravel throught using polymorphic ralationship

I'm quite new in Laravel and have some question about Laravel SQL query through using polymorphic relationship
The situation is:
I have two different tables in my SQL.
One table 'estates' contains a list of estates and their parameters
Another table is 'type_categories' which contains a list of type categories
Every estate can be related to many type categories and every type category can have many estates (so I use polymorphic relationships many to many).
They are related through the third table ''
So, as a result, I need to do a query, which will find all estates which is related to category, but my user can choose a numerous of category, not just one.
I tried to use function find(1)->estates; which as a parameter have an id of type category, which related estates I tried to find. It works fine, but the problem is, that my user needs to find an estate to several categories and function, but function finds works with just one parameter in the situation we nave polymorphic relation, not with the several parameters as I need.
Is there some way to use several parameters in function find() and also use polymorphism?
Sure, that there exist some other functions for it...
Then I show you my code.
Estates model looks:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class Estate extends Model
{
protected $fillable = ['title', 'slug', 'estate_text', 'created_by', 'modified_by'];
public function categories() {
return $this->morphToMany('App\TypeCategory', 'categoryable');
}
}
Type categories model looks:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class TypeCategory extends Model
{
protected $fillable = ['title', 'slug', 'parent_id', 'created_by', 'modified_by'];
public function estates() {
return $this->morphedByMany('App\Estate', 'categoryable');
}
}
And finally, estates controller where I tried to select estates model looks:
use Illuminate\Http\Request;
use App\Estate;
use App\TypeCategory;
class EstateController extends Controller {
public function searchEstate() {
$estates = TypeCategory::find(1)->estates;
return view('main', [
'estates' => $estates
] );
}
}
I don't sure it is your problem or not.
try this:
$estates = Estate::whereHas('categories', function ($query) {
$query->whereIn('slug', ['xxx','yyy','zzz']);
})->get();

Getting all objects from hasMany relation and paginate

In my Laravel application, I have a category listing page. When the user clicks on a certain subcategory, I'd like to list all the products and use pagination on that result. I'm already listing all the products related to that subcategory, for now, with the help of a subcategory ID:
public function subcategoryListing($slug){
$products = Subcategory::find($idofSubcat)->products;
return view('pages.subcategorylisting')
->with(array(
'products' => $products,
));
}
There are three classes involved in this structure: Category, Subcategory and Products. They were declared as follows:
Category
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use App\Subcategory;
class Category extends Model
{
protected $table = 'category';
public $timestamps = false;
public function subCategory(){
return $this->hasMany('App\Subcategory', 'category_id');
}
}
Subcategory
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Subcategory extends Model
{
protected $table = 'subcategory';
public $timestamps = false;
public function products(){
return $this->hasMany('App\Products');
}
}
Products
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Products extends Model
{
protected $table = 'products';
}
For each model class I have one table, with this structure:
Category
- id
- category_name
SubCategory
- id
- category_id
- subcategory_name
Products
- id
- subcategory_id
- product_title
- description
- price
What I want is to paginate the results retrieved from the query in my page. Is there any better way to fetch the products associated to the subcategory and paginate them?
In Eloquent (Laravel's ORM) when you call a relation as a property ($subCategory->products), it returns the related object or a collection of objects depending on the relation type (belongs to, has many, ...). Instead, if you call it as a function ($subCategory->products()), you get a QueryBuilder instance.
Refer to http://laravel.com/docs/5.1/eloquent-relationships#querying-relations, under section Relationship Methods Vs. Dynamic Properties for more details on that.
Anyway, using the relationship method, you can call paginate() for your collection. Then, with that in mind, you can change your code slightly to get what you want:
public function subcategoryListing($slug) {
// I'm supposing here that in somewhere before
// run the query, you set the value to $idofSubcat
// variable
$products = Subcategory::find($idofSubcat)->products()->paginate();
return view('pages.subcategorylisting')
->with(array(
'products' => $products,
));
}
I think, that create two categories table not so correctly, it will be better to use next:
table categories
id category_name parent_id(nullable)
and Products
id category_id product_title description price
It's more usefull, you can remove one Subcategory model and do all in Category.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'category';
public $timestamps = false;
public function subCategory(){
return $this->belongsToMany('App\Category', 'categories', 'id', 'parent_id');
}
public function products(){
return $this->hasMany('App\Products');
}
}
and products model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Products extends Model
{
protected $table = 'products';
public function category() {
return $this->belongsTo('App\Category')
}
}
then, you can get the query result
public function subcategoryListing($slug){
$products = Category::find($idofSubcat)->products;
return view('pages.subcategorylisting')
->withProducts($products); // it's a magic))
}
But, existing one not pretty thing. Do you really sure, that products will be only in one category?)
I couldn't really understand some of your initial function:
// $slug is not being used anywhere within the function
public function subcategoryListing($slug){
// $idOfSubcat isn't passed to this function so will throw an error
$products = Subcategory::find($idofSubcat)->products;
return view('pages.subcategorylisting')
->with(array(
'products' => $products,
));
}
If all you're trying to do is paginate the Products that belong to a specific subcategory_id, given you have the subcategory_id then the following code will work:
$products = Product::where('subcategory_id', $idofSubcat)->paginate();
Then you can return this paginated collection to your view as you're already doing:
return view('pages.subcategorylisting')
->with(compact('products'));

Categories