Reputation: 97
I am trying to search multiple data from two related tables. To be specific I want to get only "name column" from the users table and the rest of the columns from the posts table. But whenever I tried to search it prints the following error "Trying to get property 'name' of non-object"
Below is my user model
<?php
namespace App;
use App\Mail\NewUserWelcomeMail;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Facades\Mail;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email','phone', 'username', 'password',
'admin', 'address', 'description', 'approved_at',
];
protected $hidden = [
'password', 'remember_token',
];
public function posts()
{
return $this->hasMany(Post::class)->orderBy('created_at', 'DESC');
}
}
And post model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
}
And my Controller
public function showcampaign(User $user) {
$q = Input::get( 'q' );
if( !empty( $q ) ) {
$showcampaign = User::join('posts','posts.user_id','users.id')
->where('name','LIKE','%'.$q.'%')
->orWhere('caption','LIKE','%'.$q.'%')
->orWhere('description','LIKE','%'.$q.'%')
->orWhere('duration','LIKE','%'.$q.'%')
->orWhere('amount','LIKE','%'.$q.'%')
->get();
if(count($showcampaign) > 0) {
return view('admin.campaignreport', ['show' => $showcampaign]);
} else {
return redirect('/campaignreport')->with('status', 'No Details found. Try to search again !');
}
} else {
$showcampaign = Post::all();
return view('admin.campaignreport')->with('show', $showcampaign);
}
}
Please help thanks
Upvotes: 8
Views: 14079
Reputation: 267
I use scope query to create search functions. It makes my code more flexible and easy to understand. Here is how you can do this.
In your "user" Model, you have to write "scopeFunctionName". you can write any functionName with scope. And in your Controller, you can simply call this function whenever you need as functionName(). and pass here your search term from request as functionName(request(['search']))
And now as you have declared relations for these tables to search data from related tables, try using this code in your user Model
public function scopeFilter($query, array $filters)
{
/*
Hey $query! whenever u get 'search term' in URL, call the function.
If ['search'] exists or != null, then pass its value to the function
else return false and don't execute the $query. If value exists,
Then the function will execute the query and returns a result.
*/
$query->when(
$filters['search'] ?? false,
fn ($query, $search) =>
$query
->whereHas('users', function ($query) use ($search) {
return $query
->where('name', 'like', '%' . $search . '%')
})
->where('name', 'like', '%' . $search . '%')
->orWhere('caption', 'like', '%', . $search . '%')
->orWhere('description', 'like', '%', . $search . '%')
->orWhere('id', $search)
);
}
And in Controller, you can pass the value to the scope function as:
public function index()
{
return view('posts.index', [
'show' => Post::all()->filter(request(['search']))->with('user')
]);
}
Note: The code above has not been tested but it might solve your problem.
Upvotes: 0
Reputation: 2945
I think you need to use a reference table for where clause.
$showcampaign = User::join('posts','posts.user_id', '=', 'users.id')
->where('users.name','LIKE', '%'.$q.'%')
->orWhere('posts.caption', 'LIKE','%'.$q.'%')
->orWhere('posts.description', 'LIKE','%'.$q.'%')
->orWhere('posts.duration', 'LIKE','%'.$q.'%')
->orWhere('posts.amount', 'LIKE','%'.$q.'%')
->get();
If you define relationship correctly then use:
$showcampaign = SampleReception::with(['posts' => function($query) use($q) {
return $query->where('caption', 'LIKE','%'.$q.'%')
->orWhere('description', 'LIKE','%'.$q.'%')
->orWhere('duration', 'LIKE','%'.$q.'%')
->orWhere('amount', 'LIKE','%'.$q.'%');
}])
->orWhere('name','LIKE','%'.$q.'%')
->get();
Upvotes: 2
Reputation: 6341
As you have already declared the relations within the Model So you can use whereHas and also orWhereHas
So
$showcampaign = SampleReception::query()
->whereHas('posts',function(\Illuminate\Database\Eloquent\Builder $query) use ($q){
return $query->where('caption', 'LIKE','%'.$q.'%')
->orWhere('description', 'LIKE','%'.$q.'%')
->orWhere('duration', 'LIKE','%'.$q.'%')
->orWhere('amount', 'LIKE','%'.$q.'%');
})
->orWhere('name','LIKE','%'.$q.'%')
->get();
For any issues leave a comment
Upvotes: 5
Reputation: 6005
Try.. use where
instead of orwhere
$showcampaign = User::join('posts','posts.user_id','users.id')
->where('name','LIKE','%'.$q.'%')
->Where('caption','LIKE','%'.$q.'%')
->Where('description','LIKE','%'.$q.'%')
->Where('duration','LIKE','%'.$q.'%')
->Where('amount','LIKE','%'.$q.'%')->get();
Upvotes: 2