Query through a relationship - laravel DB - laravel

how do I get the same result for this when I use Query Builder DB
$categories = Category::with(['subcategory' => function ($query) {
return $query->where('status', true);
}])->where('status', true)->get();
Relationships
category
public function subcategory()
{
return $this->hasMany(Subcategory::class);
}
subcategory
public function category()
{
return $this->belongsTo(Category::class);
}
tables
categories
$table->id();
$table->string('name')->nullable();
subcategories
$table->id();
$table->foreignId('category_id')->constrained()->onDelete('cascade')-> onUpdate('cascade');
$table->string('name')->nullable();
I want to do a loop like this
foreach ($categories as $ctaegory){
$ctaegory->name
foreach ($ctaegory->subcategory as $subcategory){
$subcategory->name
}
}
My code works (Eloquent), but I want to use DB

Something like that:
DB::table('categories')
->join('subcategories', 'categories.id', '=', 'subcategories.category_id')
->where('subcategories.status', true)
->get();
I don't tested.
OR
Category::select("categories.*, subcategories.*")
->join("subcategories", "subcategories.category_id","=","categories.id")
->where('subcategories.status', true)
->get();

Related

Laravel pass value from query to with() function

Here is my query:
$fix = Fixture::select('fixtures.*')
->whereDate('kickoff', '<', $date)
->with('competition')
->with('teamA')
->with(['teamA.standing' => function ($q) {
$q->whereColumn('standings.competition_id', '=', {{here i want the competition_id from competitions or fixtures table}} );
}])
->with('teamB')
->with(['teamB.standing' => function ($q) {
$q->whereColumn('standings.competition_id', '=', {{here i want the competition_id from competitions table or fixtures table}});
}])->get();
Code from Fixture model:
public function teamA()
{
return $this->belongsTo(Team::class,'team_a','id');;
}
public function teamB()
{
return $this->belongsTo(Team::class,'team_b','id');;
}
Code from Team model:
public function standing()
{
return $this->hasOne(Standing::class);;
}
Code from Standing model:
public function team(){
return $this->belongsTo(Team::class);
}
public function competition()
{
return $this->belongsTo(Competition::class);
}
Can someone help me to get this done or if I am doing it wrong what's the correct way?
->with(['teamA.standing' => function ($q) {
$q->whereColumn('standings.competition_id', '=', {{here i want the competition_id from competition table or fixtures table}} );
}])
Example:
Category::select('id', 'name')->whereHas('statuses', function($query) { $query(); })->with('courses')->get();

Property [columns] does not exist on the Eloquent builder instance

i'm getting this error while trying to add a subquery select to a query builder. this error occurs when i try to get the product count for a given category.
addSubSelect Macro
Builder::macro('addSubSelect', function ($column, $query) {
if (is_null($this->columns)) {
$this->select($this->from.'.*');
}
return $this->selectSub($query, $column);
});
Category.php
public function scopeWithProductCount($query){
$query->addSubSelect('products_count', function($query) {
$query->whereHas('product', function ($query) {
$query->select('id')
->from('products')
->whereColumn('category_id', 'category.id')
->count();
});
});
}
Category Controller
public function index()
{
$categories = $this->user()->store->categories()
->withProductsSum()
->get();
return response()->json($categories);
}
i changed the scopedWithProductCount method to this to try and get more debugging options but i end up with the same error
public function scopeWithProductCount($query){
$query->addSubSelect('', function($query) {
});
}
The columns property is in the Illuminate\Database\Query\Builder Class and not Illuminate\Database\Eloquent\Builder. Your $this will refer to the Eloquent\Builder reference and not the Query\Builder.
So try changing your macro like this:
addSubSelect Macro
Builder::macro('addSubSelect', function ($column, $query) {
if (is_null($this->getQuery()->columns)) {
$this->select($this->from.'.*');
}
return $this->selectSub($query, $column);
});
Write join and the name of the table before the field:
public function scopeWithProductCount($query){
$query->addSubSelect('products_count', function($query) {
$query->whereHas('product', function ($query) {
$query->select('products.id')
->from('products')
->join('categories', 'categories.id', '=', 'products.category_id')
->count();
});
});
}

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'));
}

DB query to relationship

My query:
$data = DB::table('countries')
->leftJoin('matches', function ($join) {
$join->on('matches.hometeam', '=', 'countries.id')
->orOn('matches.awayteam', '=' ,'countries.id');
})
->where('countries.id', $id)->get();
return dd($data);
How can I get same results using relationship?
In your Model (You need a matches model aswell):
<?php
class Country extends Model {
public function matches() {
return $this->hasMany(App\Matches::class, ['hometeam', 'awayteam'], 'id');
}
}
In your controller:
$countrys = Countrys::where('id', $id)->get()
foreach($countrys as $country) {
var_dump($country->matches);
}
die();

Laravel Search Relations whereHas

I am trying to do a search on products but it does not return any results. I suspect it has something to do with the whereHas function but I just cannot figure it out. Here is my code:
My Relations:
Categories Model:
class Categories extends Eloquent {
public function product()
{
return $this->hasMany('Products')->orderBy('name');
}
}
Products Model:
class Products extends Eloquent {
public function category()
{
return $this->belongsTo('Category')->orderBy('name');
}
}
My search function:
public function search()
{
$search = Input::get('search');
$result = Products::where('name', 'LIKE', '%'. $search .'%')->get();
if ($result->first()) {
return View::make('groceries.index')
->with('categories', Categories::with('product')->orderBy('name', 'asc')
->whereHas('product', function($query) use ($search)
{
$query->where('name', 'LIKE', '%'.$search.'%');
}));
}
}
In the view:
#foreach ($categories as $category)
//do stuff
#foreach ($category->product as $products)
//Show results
#endforeach
#endforeach
You have to call get() to get the data.
And I think this will be more readable code.
public function search()
{
$search = Input::get('search');
$result = Products::where('name', 'LIKE', '%'. $search .'%')->get();
if ($result->first()) {
$categories = Categories::with('product')->orderBy('name', 'asc')
->whereHas('product', function($query) use ($search){
$query->where('name', 'LIKE', '%'.$search.'%');
})->get();
return View::make('groceries.index')
->with('categories', $categories);
}
}

Resources