I am pretty new to the Laravel Eloquent ORM and am having difficulty building a dynamic query to query products of a category.
I parse the request object and return products according to what vars have been passed through. This is easy enough when I am querying a single Model but I want to know how to build a query dynamically if a category is passed through to. This is easy enough using standard MYSQL and PHP but I am unsure as to how this is achieved in LAravel.
Here is my code:
Product Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $primaryKey = 'id',
$table = 'products',
$fillable = array('title', 'SKU', 'description', 'created_at', 'updated_at');
public $timestamps = true;
/**
* Get the categories assoicated with the product
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*
*/
public function categories() {
return $this->belongsToMany('App\Category')->withTimestamps();
}
}
Category model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
/**
* Returns all products related to a category
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products() {
return $this->belongsToMany('App\Product')->withTimestamps();
}
}
Inside my product controller I have this function to get products which calls a method 'filterProduct' in a class called 'filtervars':
public function index(Request $request)
{
return FilterVars::filterProduct($request->all());
}
And here is the filterProduct method:
public static function filterProduct($vars) {
$query = Product::query();
if((array_key_exists('order_by', $vars)) && (array_key_exists('order', $vars))) {
$query = $query->orderBy($vars['order_by'], $vars['order']);
}
if(array_key_exists('cat', $vars)) {
$query = $query->whereHas('categories', function($q) use ($vars){
return $q->where('category_id', $vars['cat']);
});
}
return $query->get();
The product database migration:
class CreateProductsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('products', function(Blueprint $table) {
$table->increments('id');
$table->string('title', 75);
$table->string('SKU')->unique();
$table->text('description')->nullable();
$table->timestamps();
});
}
And the migration which shows the structure of the categories table, the pivot table and foreign keys etc:
class CreateCategoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('description');
$table->timestamps();
});
Schema::create('category_product', function(Blueprint $table) {
$table->integer('product_id')->unsigned()->index();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
}
I had a go at trying to incorporate the 'has' method on the query but this doesn't seem to work. can anyone advise as to where I am going wrong?
Thanks!
May be you need whereHas
method
$query = $query->whereHas('categories', function($q) use ($vars) {
$q->where('id', $vars['cat']);
});
EDIT
You should use id column in whereHas
method because you apply where condition to categories table, which hasn't category_id column
public static function filterProduct($vars) {
$query = Product::query();
if((array_key_exists('order_by', $vars)) && (array_key_exists('order', $vars))) {
$query = $query->orderBy($vars['order_by'], $vars['order']);
}
if(array_key_exists('cat', $vars)) {
$query = $query->whereHas('categories', function($q) use ($vars){
$q->where('id', $vars['cat']);
});
}
return $query->get();
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments