Laravel different use of where clause - laravel

I want to ask about some feature in Laravel, I'm working with some old code written by someone else and I want to understand why it is written this way:
$users = Users::all();
$results = $users->where('age', '>','30')->get();
My question is how can 'where' clause be used with the '$users' variable? This works fine and no error is given and it returns the required results. But as far as i know, 'where' clause can be used like:
Classname::where()->get()
Does the User model implements some feature or use something to be able to call 'where' clause this way? When i try to do the same but with a new model i'm creating I get
"Type error: Too few arguments to function Illuminate\\Support\\Collection::get()

How can 'where' clause be used with the '$users' variable?
The where clause can be used because the all() method returns a Collection, and the where() and get() methods are available on the Collection class.
Does the User model implements some feature or use something to be able to call 'where' clause this way?
Each Eloquent model serves as a query builder which will make you able to add constraints and receive the results with the get() method afterwards.

// Collection::get() is diferent with QueryBuilder::get()
$builder = Users::query(); // you got QueryBuilder object
$builder->where('age', '>','30'); // you got QueryBuilder object
$list = $builder->get(); // you got Collection object
$list->where('age', '>','30'); // you got Collection object
// Collection object has 'get', but it require argument.
// QueryBuilder object has 'get' too, but do not require argument.

Related

Call to a member function first() on null

When I try to fetch my user data, I receive the error
Call to a member function first() on null
public function show($id) {
$user=User::findOrFail($id);
$employee = $user->employees->first();
return view('admin.profile')
->with(['employee' => $employee , 'user' => $user]);
}
The problem is probably in your User model.
Check that you have declared the employees relationship:
public function employees()
{
return $this->hasMany(Employee::class); // I'm assuming you have a Employee model with expected column names, but feel free to replace everything with what you actually have in your app
}
If the problem persists, edit your question with your tables structure and your models.
It's very useful to understand the difference between $user->employees and $user->employees().
$user->employees: returns a Collection of employee models, or null if none are found.
$user->employees(): returns a query builder instance that you can chain additional conditions to (where's, etc).
Both options have a first() option available to them, but one is using a Collection method, where the other is using the query builder method.
Some have already suggested this, and I will as well - the safer and simplest solution to your problem is to use the query builder version of the relationship, since there is no risk of the employees() result being null. It also has the added benefit of not needing to load the entire relationship into a collection just to get the first result.
In short: $user->employees()->first(); is the best way to go.

Can I send a variable into laravel model?

So I'm trying to add get a specific data from a related table using the below method, but I don't know if that is the correct way to do it. here is what it looks like.
public function transspecific($lid){
return $this->belongsTo('raplet\Keepertrans')->where("lang_id", $lid);
}
and then I try to get data from it
dd($akeeper->transspecific($akeeper->id));
it doesn't act like there is anything but when I type dd("hello") inside the model, it works. so clearly I have something wrong with my relationship context
What are you are trying to do is adding a [dynamic scope in laravel][1] model, which is totally fine. Except you need to declare the scope seperated from relationship method.
Relationship:
public function keepertrans(){
return $this->belongsTo('raplet\Keepertrans');
}
Scoped:
public function transspecific($lid){
return $this->keepertrans()->where("lang_id", $lid);
}
Then you can call the scope with a get() to execute the query builder:
(SomeOtherRelatedModel::first())->transspecific($someId)->get();
The methods available in Eloquent model for relationship are different than what you need. Whenever you need to add a custom function which internally adds some filters to your query (builder), you need to use scopes
The generic rule of scope function is scope + yourfunction
In your case you will need to create scopeTranspecific function.
Each scope gets the first argument as builder which you update inside the function. The later arguments are optional.
public function scopeTranspecific($query, $lid){
return $query->keepertrans()->where("lang_id", $lid);
}
And then you can use it :
Model::where('column1' , 'value')->transpecific($id)->get()
If you just dump it without ->get() you will get the query builder instance. You will have to do ->get() to get the data

What is the meaning of Eloquent's Model::query()?

Can anyone please explain in detail what Eloquent's Model::query() means?
Any time you're querying a Model in Eloquent, you're using the Eloquent Query Builder. Eloquent models pass calls to the query builder using magic methods (__call, __callStatic). Model::query() returns an instance of this query builder.
Therefore, since where() and other query calls are passed to the query builder:
Model::where()->get();
Is the same as:
Model::query()->where()->get();
Where I've found myself using Model::query() in the past is when I need to instantiate a query and then build up conditions based on request variables.
$query = Model::query();
if ($request->color) {
$query->where('color', $request->color);
}

Eloquent find() with joins and eager loading

I want to retrieve one record via the time-tested method of this URL:
public/api/laptop/1
hitting this route:
Route::get('laptop/{id}', 'LaptopController#getLaptop');
then this controller method:
$laptop = Laptop::find($id)->addJoins()->selectListCols()->with('earmarks', 'movements')->get();
return $laptop;
Problem is this doesn't work (it returns every record). To make it work I have to do this:
$laptop = Laptop::where('laptops.id', $id)->addJoins()->selectListCols()->with('earmarks', 'movements')->get();
return $laptop;
But I'm just wondering why find() doesn't work? earmarks and movements are Many-To-One models, by the way.
find() is just a shortcut for where()->first() so it will return an object and Query Builder methods will not work with it:
User::find(1); // Will return User object with ID = 1.
That's why you need to use where(), which returns Query Builder object, so you can use with() and other builder methods to build your query.

Instance the query builder directly from model

When I do something like SomeModel::with('user') it returns a Query\Builder instance. How can I get this instance without need call the with() (or similar)?
For instance, I tried it: new SomeModel, but it'll returns obviously the instance of my model, not the query builder (not worked to me). The SomeModel::getQuery not works too, because it returns a Query\Builder not related to my model.
I need it to I setup based on some conditionals. So initially it need be empty, like it:
$someBuilder = SomeModel::getQueryBuilder(); // eg.
if(condition()) {
$someBuilder->where(...);
}
$someResults = $someBuilder->get();
Use the static query method:
$query = User::query();
Additionally, you can use the when method to chain these conditionals directly onto the query builder itself:
$results = SomeModel::query()->when(condition(), function ($query) {
$query->where(...);
})->get();
This is functionally equivalent to the imperative if clause.

Resources