How to show Laravel model with belongsToMany connection if has specified connection? - laravel

I have this product model:
public function categories() {
return $this->belongsToMany('App\Category', 'product_categories');
}
And in my controller:
public function search(Request $request) {
return Product::with([
'categories' => function($categories) use ($request) {
// ...
}
]);
}
If I try to use $request in the categories function it's search only in categories, but shows all products.
How do I show only that products whitch has defined categories in $request->category_id?

you may use the whereHas keyword in laravel:
public function search(Request $request) {
return Product::with('categories')
->whereHas('categories', function ($query) use ($request){
$query->where('category_id', $request->category_id);
})->get();
}
Here is the docs

You can search it in following way:
public function search(Request $request) {
return Product::with('categories')
->whereHas('categories', function ($q) use (request) {
$q->where('id', $request->category_id);
});
}

Related

Laravel Single User Data In A Multichained Distant Relationship

I have three models as per the code below.I have a problem of returning a single savings data for authenticated users. Any help will be highly appreciated.
I want a low like this:
$savings =Savings::client()->client_users()->where('user_id', '=', Auth::user()->id)->get();
Savings Model
class Savings extends Model
{
public function client()
{
return $this->hasOne(Client::class, 'id', 'client_id');
}
}
Client Model
class Client extends Model
{
public function client_users()
{
return $this->hasMany(ClientUser::class, 'client_id', 'id');
}
}
Client User Model
class ClientUser extends Model
{
public function user()
{
return $this->hasOne(User::class, 'id', 'user_id');
}
}
You can try this query:
$user = Auth::user();
return Savings::whereHas('client.client_users', function ($query) use ($user){
$query->where('user_id', $user->id);
}])->get();
I have fixed the above error. Thanks #Maik Lowrey
$user = Auth::user();
$savings= Savings::whereHas('client.client_users', function ($query) use ($user){
$query->where('user_id', $user->id);
})->get();
return response()->json($savings);
//return response($savings);

Eloquent collections with a relation of another relation

I have Post eloquent related with PostCategory and my collection is good.
class Post extends Model
{
public function post_categories()
{
return $this->belongsTo(PostCategory::class, 'category_id');
}
public function detail($slug_category, $slug)
{
$detail = Post::with('post_categories')
->whereHas('post_categories', function ($query) use ($slug_category){
$query->where('category_slug', $slug_category);
})->where('slug', $slug)
->first();
return($detail);
}
}
I have this another class 'Players' where i need to have a collection with all user's posts with PostCategory category relation.
class Players extends Model
{
public function posts()
{
return $this->hasMany(Post::class);
}
public function detail($slug_category, $slug_name)
{
$detail = Player::with('posts')
->whereHas('players_info', function ($query) use ($slug_name){
$query->where('slug', $slug_name);
})
->whereHas('player_categories', function ($query) use ($slug_category){
$query->where('category_slug', $slug_category);
})->first();
return($detail);
}
}
I read something about "belongsToMany" and "withPivot", but I'm still confused for correct way.
What can I do to resolve this?
thanks!
I solved just with this.
return $this->hasMany(Post::class)->with('post_categories');

Laravel, Simple and Correct way for relationship

I want to list related categories of related brand with this logic.
Products Table
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('slug');
$table->integer('brand_id')->unsigned();
$table->foreign('brand_id')->references('id')->on('brands')->onDelete('cascade');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
}
web.php
Route::get('{Brand}/{Category}/{Product}', 'ProductsController#show');
Route::get('{Brand}/{Category}', 'ProductsController#index');
1st route, for example; Samsung/phones should list all of Samsung's phones with following code part. Is there another way to make these codes simple? And this query returns null. I checked that query is getting correct columns but returns null.
use App\Product;
use App\Brand;
use App\Category;
class ProductsController extends Controller
{
public function index(Request $request)
{
$category = $request->Category;
$cat_id = Category::select('id')
->where('slug',$category)
->get();
$brand = $request->Brand;
$br_id = Brand::select('id')
->where('slug', $brand)
->get();
$products = Product::select('id','name','slug')
->where('category_id', $cat_id)
->where('brand_id', $br_id)
->get();
return view('products.index', compact('products'));
}
}
Product.php
class Product extends Model
{
public function brands()
{
return $this->belongsTo('App\Brand');
}
public function categories()
{
return $this->belongsTo('App\Category');
}
}
Category.php
class Category extends Model
{
public function brands()
{
return $this->belongsToMany('App\Brand');
}
public function products()
{
return $this->hasMany('App\Product');
}
}
First of all read the docs about laravel relationships:
https://laravel.com/docs/5.7/eloquent-relationships
The reason your current code is not working is because in your route you ask for parameters:
Route::get('{Brand}/{Category}', 'ProductsController#index');
But in your index() method on your ProductsController you have not included these parameters.
public function index(Request $request, Brand $brand, Category $category)
The second problem in your code is that you are not using your relationships at all. Your current controller just makes a new eloquent query.
Example of getting all the products for the given category using the method you have defined on your Category Model:
public function index(Request $request, Brand $brand, Category $category)
{
$products = $category->products;
return view('products.index', compact('products'));
}
Example of extending this with the given brand:
public function index(Request $request, Brand $brand, Category $category)
{
$products = $category->products()->where('brand_id', $brand->id)->get();
return view('products.index', compact('products'));
}
UPDATE
As noted in the comments, the URL parameters are slugs and not ids, so auto route-model-binding will not work. An updated solution with slugs:
public function index(Request $request, $brand, $category)
{
$categoryModel = Category::where('slug', $category)->firstOrFail();
$brandModel = Brand::where('slug', $brand)->firstOrFail();
$products = $categoryModel->products()->where('brand_id', $brandModel->id)->get();
return view('products.index', compact('products'));
}
Further improving your code would be to add a scope or helper method so you can do something like Brand::FindBySlug($slug);
I think you are using get method at last that will give you array not only one value. Could you please try with below code. This might help
use App\Product;
use App\Brand;
use App\Category;
class ProductsController extends Controller
{
public function index(Request $request)
{
$category = $request->Category;
$cat_id = Category::where('slug',$category)->value('id);
$brand = $request->Brand;
$br_id = Brand::where('slug', $brand)->value('id);
$products = Product::select('id','name','slug')
->where('category_id', $cat_id)
->where('brand_id', $br_id)
->get();
return view('products.index', compact('products'));
}
}
You should try this:
public function index($brand, $category,Request $request)
{
$products = Product::select('id','name','slug')
->where('category_id', $category)
->where('brand_id', $brand)
->get();
return view('products.index', compact('products'));
}

Relationships in Laravel Models

How can I write this without a join for a scope in a Laravel model as the 'id' field becomes ambiguous
/**
* Return events that social category name
*/
public function scopeWithSocialEvents($query)
{
return $query->join('categories', 'events.event_type_id', '=', 'categories.id')
->where('categories.name', 'social');
}
Use this:
public function eventType()
{
return $this->belongsTo(Category::class);
}
public function scopeWithSocialEvents($query)
{
return $query->whereHas('eventType', function($query) {
$query->where('name', 'social');
});
}

Nested "with()" laravel

I'm having issues with some relationships. I have the following situation
Product:
public function catalogues()
{
return $this->belongsToMany('App\Catalogue');
}
public function category()
{
return $this->belongsTo('App\Category');
}
Category:
public function products()
{
return $this->hasMany('App\Product');
}
Catalogue:
public function products()
{
return $this->belongsToMany('App\Product');
}
With a single query, I need to get all the categories that have products belonging to a certain catalogue. How can I achieve it?
Use whereHas():
Category::whereHas('products.catalogues', function($q) use($catalogueId) {
$q->where('catalogues.id', $catalogueId);
})
->get();
Or:
Category::whereHas('products', function($q) use($catalogueId) {
$q->whereHas('catalogues', function($q) use($catalogueId) {
$q->where('id', $catalogueId);
})
})
->get();
You need whereHas and
Category::whereHas('products')
->with(['products' => function($query) use ($id){
$query->with('catalogues' => function($query) use ($id){
$query->where('catalogues.id',$id);
});
}])
->get();
Hope this helps.

Resources