laravel: odd behavior when query is empty - laravel

I have a model
I call it this way:
Sight::filter(['type'=>'menu']);
and in model:
public function scopeFilter($query,$params)
{
return $query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
}
when there is one or more records, it works normally.
but when database is empty I get an odd behavior:
with dd(Sight::filter(['type'=>'menu']))
or
$query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
dd($query);
I got this result:
But with
dd(
$query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
)
I got Null so it is right!
how can I return Null? what is my wrong?

You shouldn't be calling first() inside of a scope - you are only meant to adjust the query by constraining it. You should call first() in your chain after applying the filter() scope. If you want to use the same syntax rather than chaining like that you would be best to define a custom static method.
public static function filter($params)
{
return self::wherePublish(1)
->whereIn_special(1)
->latest()
->first();
]
Also note that in your example your scope accepts an argument (and you pass it one) but it isn't actually used in your code.

Related

Argument 1 passed to Illuminate\Database\Connection::prepareBindings() must be of the type array, null given

public function search(Request $request)
{
$search = $request->get('search');
$image = DB::select(`produits.id`, `produits.name`, `categories.name`, `produits.description`, `produits.volume`, `produits.poids`, `users.name`, `users.numtel`)
->from(`produits`)
->from(`users`)
->from(`categories`)
->where(`produits.category_id`, `=`, `categories.id`)
->where(`users.id`, `=`, `produits.user_id`)
->where(`produits.description`, `=`, [$search])
->get();
return view('home', ['produits' => $image]);
}
This is the error I'm getting:
Argument 1 passed to Illuminate\Database\Connection::prepareBindings() must be of the type array, null given
There a quite a few issues with the code you've shown above.
Firstly, use single or double quotes(' or ") not back ticks (`).
When calling select() straight from the DB facade is going to call the select() method on Connection which is different to the select() method from the Builder class. The select on the Connection instance is essentially for performing raw queries.
To get the Builder instance you can either start your chain with query() or table() (which is essentially the from() method) e.g.
DB::table('table_name)
or
DB::query()->from('table_name')
AFAIK, you can't specify multiple tables with the query builder so you will need to join the tables instead.
Ultimately, you query should look something like:
DB::table('produits')
->select('produits.id', 'produits.name', 'categories.name', 'produits.description', 'produits.volume', 'produits.poids', 'users.name', 'users.numtel')
->join('users', 'users.id', 'produits.user_id')
->join('categories', 'produits.category_id', 'categories.id')
->where('produits.description', $search)
->get();

Return keyword in query callback

Is it necessary to write return keyword while using whereHas in laravel.
For eg. return $query->where('status', 1);
$posts = App\Post::whereHas('comments', function ($query) {
$query->whereHas('content', function ($query){
$query->where('status', 1);
});
})->get();
Do we need to write return in every query callback?
No, you're modifying the query builder instance passed to your closure by calling $query->where('status', 1);. Since objects are passed by reference and where() mutates this instance, there's no need to return anything.
There is no need. Also you can use whereHas with nested relationship.
Example:
$posts = App\Post::whereHas('comments.content', function ($query) {
$query->where('status', 1);
})->get();
No. Because you have the same object (and modify it) inside every function. No need to return.

Laravel 5 Eager Loading with parameters

I'm working on a project with a bit of a complex model that has joins in its relations and also requires a parameter. It all works pretty well, except for when I need to eager load the relationship, as I couldn't figure out if there is a way to pass a parameter/variable to it.
The Controller
$template = Template::find($request->input('id'));
$this->output = $template->zones()->with('widgets_with_selected')->get();
The Model
public function widgets_with_selected($banner_id)
{
return $this->belongsToMany('App\Models\Widget', 'zone_has_widgets')
->leftJoin('banner_has_widgets', function($join) use($banner_id) {
$join->on('widgets.id', '=', 'banner_has_widgets.widget_id')
->where('banner_has_widgets.banner_id', '=', $banner_id);
})
->select('widgets.*', 'banner_has_widgets.banner_id');
}
This is returning a Missing argument error as the variable is not being passed.
I have resolved the issue by moving the logic to the controller, but I want to know if there is a way to keep the relationship in the model and just call it with a parameter.
Looking at the laravel code I dont think this is possible as you'd like to do it. You simply cant pass parameters to a with() call.
A possible workaround is to have an attribute on your model for $banner_id.
$template = Template::find($request->input('id'));
$template->banner_id = 1;
$this->output = $template->zones()->with('widgets_with_selected')->get();
Then change your relationship
public function widgets_with_selected()
{
return $this>belongsToMany('App\Models\Widget','zone_has_widgets')
->leftJoin('banner_has_widgets', function($join) use($this->banner_id) {
$join->on('widgets.id', '=', 'banner_has_widgets.widget_id')
->where('banner_has_widgets.banner_id', '=', $banner_id);
})
->select('widgets.*', 'banner_has_widgets.banner_id');
}
You could perhaps alter it a bit by passing the banner_id through a method. Sortof like this in your model:
public function setBanner($id) {
$this->banner_id = $id;
return $this;
}
Then you can do:
$template->setBanner($banner_id)->zones()->with('widgets_with_selected')->get();
Not sure if this works, and it's not really a clean solution but a hack.

Laravel - Trying to get property of non-object in chained view

Having a small problem with retrieving a new object on my view. I keep getting the error 'Trying to get property of non-object'.
The field I am trying to display 'oil_gas_skillsgap' is a valid field and when I do a simple return it spits out...
[{"oil_gas_job_id":"4","industry_job_id":"43","oil_gas_skillsgap":"test text here"}]
CONTROLLER
public function showjob($slug)
{
$job = OilGasJob::where("slug", "=", $slug)->first();
if (is_null($job))
{
return Redirect::to('/');
} else {
$jobId = $job->id;
$roleId = Session::get('industryrole');
$skills = DB::table('industry_job_oil_gas_job')
->where('oil_gas_job_id', '=', $jobId)
->where('industry_job_id', '=', $roleId)
->get();
return View::make('job')
->with('job', $job)
->with('skills', $skills);
}
}
VIEW
{{ $job->job_title}}
{{ $skills->oil_gas_skillsgap }}
$skills is probably an array, not an object, even if the query has only one result.
If you know for a fact that your query will return one result, use first() and you'll get it as an object directly.
$skills = DB::table('industry_job_oil_gas_job')
->where('oil_gas_job_id', '=', $jobId)
->where('industry_job_id', '=', $roleId)
->first();
Otherwise, remember the following: when using the DB class for queries, Laravel will always return an array. If you use an Eloquent model, it will return an Illuminate\Support\Collection object. In both cases that is true even if no row is found (the array or Collection will be empty). The first() method, on the other hand, will either return an object (stdClass when using DB, or a model when using Eloquent) or null.
#user3189734,
job_title is not a part of $job collection, that is why it is throwing 'Trying to get property of non-object'.

Active Record and queries with CodeIgniter

I am using codeigniter for my application and i am a bit confused, I wrote some queries like that:
public function checkemail($email) {
$this->db->select('email')->from('user')->where('email', $email);
}
But in the manual of codeigniter ( http://codeigniter.com/user_guide/database/active_record.html ) they talk about $this->db->get();
Should I add it after the $this->db->select query?
My function works fine...
When should I use get() ?
Thanks you!
Yes, you'll need to run get() after the other methods. select(), from() and where() add their respective statements to the query, and get() actually runs the query and returns the result as an object.
In this case, you could just add it on to the end of the chain.
public function checkemail($email) {
$this->db
->select('email')
->from('user')
->where('email', $email)
->get();
}
If you want to work with the result afterwards, make sure that you are assigning it to a variable.
$user = $this->db
->select('email')
->from('user')
->where('email', $email)
->get();
If you use get("table_name") then you don't need to use from("table_name"). It's just an alternative syntax it seems.
From the user guide, all the way at the bottom it says: As shown earlier, the FROM portion of your query can be specified in the $this->db->get() function, so use whichever method you prefer.

Resources