How can I use whereHas in the morphTo relation laravel? - laravel

My product model like this :
<?php
...
class Product extends Model
{
...
protected $fillable = ['name','photo','description',...];
public function favorites(){
return $this->morphMany(Favorite::class, 'favoritable');
}
}
My favorite model like this :
<?php
...
class Favorite extends Model
{
...
protected $fillable = ['user_id', 'favoritable_id', 'favoritable_type'];
public function favoritable()
{
return $this->morphTo();
}
}
My laravel eloquent like this :
$q = $param['q'];
$query = Favorite->where('user_id', auth()->user()->id)
->with('favoritable');
if($q) {
$query->whereHas('favoritable', function ($query) use ($q) {
$query->where('name', 'like', "%$q%");
});
}
$query = $query->paginate(5);
return $query
If the script executed, there exist error like this :
Unknown column 'name'
How can I solve this problem?

Laravel 5.8 include new features for querying polymorphic relations.
The whereHasMorph() make it possible to query polymorphic relationships with something like the following:
Comment::whereHasMorph('commentable', [Post::class, Video::class], function($query){
$query->where('title', 'foo');
})->get();
Which produces following query:
select * from "comments"
where (
(
"commentable_type" = 'App\Post' and exists (
select * from "posts"
where "comments"."commentable_id" = "posts"."id" and "title" = 'foo'
)
) or (
"commentable_type" = 'App\Video' and exists (
select * from "videos"
where "comments"."commentable_id" = "videos"."id" and "title" = 'foo'
)
)
)

Solved
I add this method :
public function product()
{
return $this->belongsTo(Product::class, 'favoritable_id')
->where('favorites.favoritable_type', Product::class);
}
in favorite model
And I change the laravel eloquent to be like this :
$query->whereHas('product', function ($query) use ($q) {
$query->where('name', 'like', "%$q%");
});
It works

Related

issue in laravel relationship search data

I want to search for usernames from the user's table.
I have used the Laravel relationship(eloquent). I don't search for usernames from users' tables. My code is Below and here I Explain the relationship with All Tablets
I have a query write inside the group controller
public function getGroupsData(Request $request){
$group = Group::with(['memberscount', 'getusername'])->where('groupName', "like", "%" . $request->searchText . "%")
->whereHas('getusername.user', function ($query) use ($request) {
return $query->where('name', 'like', '%'. $request->searchText . '%');
})
->get();
}
memberscount and getusername relationship write-in group model my group model is below
class Group extends Model
{
public function memberscount(){
return $this->hasMany('App\Models\Members', 'group_id', 'id')->where('memberStatus', 'Joined');
}
public function getusername(){
return $this->hasOne('App\Models\Members', 'group_id', 'id')->where('isOwner', 0);
}
}
And user's table relationship in members models. members model is below
class Members extends Model
{
public function user(){
return $this->hasOne('App\User', 'id', 'user_id');
}
/**get group name */
public function group(){
return $this->hasOne('App\Models\Group', 'id', 'group_id');
}
}
I have search user's data this(user) relationship. But I can't search data in a multilevel relationship.
OK, I'm the first step is to rename name relationships in class Group
I think it was more logical names
memberscount -> members
getusername -> owner
And the second step is to search. I write like this:
$group = Group::whereHas('owner', function ($query) use ($request) {
return $query->where('groupName', 'like', '%'. $request->searchText . '%');
})->get();
or more effective and clear code we can save in scope us query like that:
$group = Group::whereHas('owner', function ($query) use ($request) {
return $query->haveGroupName($request->searchText);
})->get();
In the Group model class write code like that:
/**
* Scope a query to only have groupName.
*
* #param \Illuminate\Database\Eloquent\Builder $query
* #param string $param
* #return \Illuminate\Database\Eloquent\Builder
*/
public function scopeHaveGroupName($query, $param)
{
return $query->where('groupName', 'like', '%' . $param . '%');
}

Laravel Eloquent pass Attribute to Relationship

I'm trying to load a relationship with eager loading. But, would like to pass an attribute to the relationship function.
(Laravel 6.x)
Model - taxChildren() requires an ID
public function taxChildren($moduleId)
{
return $this->hasMany($this, 'parent')->where('module', '=', $moduleId')->orderBy('created_at', 'asc');
}
Controller
$departments = tax::where([
['module', '=', $this->departmentsModuleId],
])
->whereNull('parent')
->with([
'taxChildren' => ['moduleId', '2']
])
->get();
Now , i know that i can pass a query to my relationship like so:
$departments = tax::where([
['module', '=', $this->departmentsModuleId],
])
->whereNull('parent')
->with([
'taxChildren' => function($query){
$query->where('module', '=', $this->departmentsModuleId);
},
])
->get();
but i will be using this often with multiple relations that are similar. Anyone have an idea how to achieve this? Thanks!
You can't pass argument direcly to the relationship function but this can be done with model properties
Mymodel.php
class MyModel extends Model {
protected $moduleId = null;
public function taxChildren(){
return $this->hasMany($this, 'parent')->where('module', '=', $this->moduleId)->orderBy('created_at', 'asc');
}
}
MyController.php
use App\MyModel;
...
class MyController extends Controller {
public function controllerMethod(){
$query = new MyModel;
$query->moduleId = 1;
$departments = $query::where([
['module', '=', $this->departmentsModuleId],
])
->whereNull('parent')
->with(['taxChildren'])
->get();
}
}
Also you can use laravel query scopes to set modelId property . I think that is much cleaner code
Mymodel.php
class MyModel extends Model {
protected $moduleId = null;
public function scopeMudule($q, $module_id){
$this->moduleId = $module_id;
return $q;
}
public function taxChildren(){
return $this->hasMany($this, 'parent')->where('module', '=', $this->moduleId)->orderBy('created_at', 'asc');
}
}
MyController.php
use App\MyModel;
...
class MyController extends Controller {
public function controllerMethod(){
$departments = $query::module(1)->where([
['module', '=', $this->departmentsModuleId],
])
->whereNull('parent')
->with(['taxChildren'])
->get();
}
}

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

How can I add, delete and get a favorite from product with polymorphic relationship, in Laravel 5.6?

My product model like this :
<?php
...
class Product extends Model
{
...
protected $fillable = ['name','photo','description',...];
public function favorites(){
return $this->morphMany(Favorite::class, 'favoritable');
}
}
My favorite model like this :
<?php
...
class Favorite extends Model
{
...
protected $fillable = ['user_id', 'favoritable_id', 'favoritable_type'];
public function favoritable()
{
return $this->morphTo();
}
}
My eloquent query laravel to add, delete and get like this :
public function addWishlist($product_id)
{
$result = Favorite::create([
'user_id' => auth()->user()->id,
'favoritable_id' => $product_id,
'favoritable_type' => 'App\Models\Product',
'created_at' => Carbon::now()
]);
return $result;
}
public function deleteWishlist($product_id)
{
$result = Favorite::where('user_id', auth()->user()->id)
->where('favoritable_id', $product_id)
->delete();
return $result;
}
public function getWishlist($product_id)
{
$result = Favorite::where('user_id', auth()->user()->id)
->where('favoritable_id', $product_id)
->get();
return $result;
}
From the code above, I'm using parameter product_id to add, delete and get data favorite
What I want to ask here is : Whether the above is the correct way to add, delete and get data using polymorphic relationship?
Or is there a better way to do that?

How to use Eager Loading and Join in Eloquent at a same time in laravel 4

Models
class WPModel extends Eloquent
{
protected $table = 'work_processes';
protected $guarded = array('id');
protected $softDelete = true;
// declaring one-to-many relationship
public function relatedWPAQs()
{
return $this->hasMany('WPAQModel', 'wp_id');
}
public function relatedUsers()
{
return $this->belongsTo('UserModel', 'wp_owner_id');
}
}
class UserModel extends Eloquent
{
protected $table = 'users';
protected $softDelete = true;
public function relatedWPs()
{
return $this->hasMany('WPModel', 'wp_owner_id');
}
}
class WPAQModel extends Eloquent
{
protected $table = 'wp_audit_questions';
protected $fillable = array('wp_id', 'wp_audit_question');
// declaring one-to-many relationship - the inverse way
public function relatedWP()
{
return $this->belongsTo('WPModel', 'wp_id');
}
public function scopeWpParent($query, $id)
{
return $query->where('wp_id', '=' ,$id);
}
}
Controller
class WPAQController extends BaseController
{
public function showWPAQ($wpid)
{
$workprocess = WPModel::where('id', $wpid)
->join('users', 'users.id', '=', 'work_processes.wp_owner_id')
->select('users.user_name', 'work_processes.*')
->with(array(
'relatedWPAQs' => function($query) use ($wpid)
{
$query->where('wp_id', '=',$wpid);
}
))
->get();
return View::make('wpaqshow')->with(compact('workprocess'));
}
}
when I run this code, I get following error
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in
where clause is ambiguous (SQL: select users.user_name,
work_processes.* from work_processes inner join users on
users.id = work_processes.wp_owner_id where
work_processes.deleted_at is null and id = ?) (Bindings: array (
0 => '1', ))
Try the following:
$workprocess = WPModel::where('work_processes.id', $wpid)
->join('users', 'users.id', '=', 'work_processes.wp_owner_id')
->select('users.user_name', 'work_processes.*')
->with(array(
'relatedWPAQs' => function($query) use ($wpid)
{
$query->where('wp_id', '=',$wpid);
}
))
->get();
You have joined few tables. Now laravel has many Ids. You have to tell Laravel which id in where clause Laravel should use..
WPModel::where('id', $wpid)

Resources