How to get the count of Belongsto in Laravel? - php

I want to get the count of the elements of materials count.
SubCategory:
public function materials(){
return $this->hasMany('App\Material');
}
Materials:
public function subcategories(){
$this->belongsTo('App\SubCategory','SubCategoria_id');
}
I want to get the count of the elements that have the subcategory_id
'quantidade' => $subcategory->material->count()
I'm getting error in 1054 Unknown column 'material.subcategory_id'

You should use the relationship to count. This will count the items using the DB. You should use the function like this:
'quantidade' => $subcategory->materials()->count()
And in the model, you have to inform the id in hasMany too:
public function materials(){
return $this->hasMany('App\Material' ,'SubCategoria_id');
}
You should also notice that it would be better if you name yours classes and variables according to Laravel patterns.

Does your material table have a subcategory_id column? This error could indicate it doesn't exist, therefore it's failing when you try the relationship.
As long as the column exists, the relationship should be valid and you should be able to count the results.

Since you're using a custom foreign key, you need to specify it. So, change the relation to:
public function materials()
{
return $this->hasMany('App\Material', 'SubCategoria_id');
}
And then use the proper relationship name:
$subcategory->materials()->count()

Related

Laravel Where Clause To Search In Columns Which Are Not In The Database

I have a table organisations with a number of columns, namely id, name, created_at and updated_at.
In my Organisation model, I added a custom attribute by adding the following code in the model:
// Add custom attributes
protected $appends = [
'device_count',
];
and:
public function getDeviceCountAttribute()
{
// Count organisation's devices
$device_count = Device::where('organisation_id', '=', $this->id)->count();
return $device_count;
}
In my controller, I am trying to search (using the where clause) by the device_count attribute, but I'm getting an error since this is not a real column in my database table.
This is how I'm searching:
$organisations = Organisation::query();
$organisations = $organisations->where('device_count', '=', 0);
$organisations = $organisations->get();
This is the error:
[2020-10-14 12:29:27] local.ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'device_count' in 'field list'...
Is there an alternative to the where clause in order to search by device_count please?
You can't query against attributes like that, they only exist on the model and do not exist in the database. However, you don't need to create a getter for that.
Laravel has a withCount() method you can use instead of that attribute - which is the correct approach of obtaining relational counts.
So a query with that attribute would look like
$organisations = Organisation::withCount('devices')->get();
The resulting models will now have a device_count attribute on them, that you can use in your views.
Then in your query, to filter those records that has at least a certain relational count, you can do
$organisations = Organisation::has('devices', '=', 0)->get();
Since you're looking for those that do not have any relation, you can replace it with doesntHave(). The above snippet is included to show how you can query against a specific set of relational counts.
To query only those that don't have any related devices, simply do
$organisations = Organisation::doesntHave('devices')->get();
This assumes that you have defined a devices relation on your Organisation class.
public function devices() {
return $this->hasMany(App\Models\Device::class); // Or App\Device::class if your models are not in the Models namespace/directory
}
The approaches above are the Laravel-way of doing it - and you should therefor remove your getDeviceCountAttribute() method and the corresponding device_count from $appends.
As per your requirement you want to get those Organisations which doesnot have any devices
For that, you need to use doesntHave method.
Make a relationship in the Organisation model.
public function devices() {
return $this->hasMany('App\Models\Device','organisation_id','id');
}
Now call the mothed in controller/
$organisations = Organisation::doesntHave('devices')->get();
it will return you those organisations which devices are not exists.

Pluck primaryKey from relationship between same table

Cursos has a many-to-many relationship with Cursos and i want to get only the primaryKey from the related Cursos.
$curso = Curso::with(['thumb','interna','area','cursos_relacionados' => function($query){
$query->pluck('curso_id');
}])->find($curso_id);
The problem: Column 'curso_id' in field list is ambiguous.
I could do this:
DB::table('cursos_has_cursos_relacionados')->select('curso_relacionado_id')
->where('curso_id','=',$curso_id)->pluck('curso_relacionado_id')->toArray();
But i would like to know if its possible and how to add a alias to the with() method and use the first sample of code.
UPDATE
This is the relation
public function cursos_relacionados(){
return $this->belongsToMany('App\Model\Curso','cursos_has_cursos_relacionados','curso_id','curso_relacionado_id');
}
The problem: Column 'curso_id' in field list is ambiguous.
You need to specify table: 'thumb.curso_id' or the table you want.
Unfortunately, i couldn't find anything about setting a alias on the with() method. But, if anyone finds himself here, loking for the same anwser. Try the following code, it should work just fine
$curso = Curso::with(['thumb.media_root','interna.media_root','objetivos_media.media_root','area'])->find($curso_id);
$curso->cursos_relacionados = DB::table('cursos_has_cursos_relacionados')->select('curso_relacionado_id')->where('curso_id','=',$curso_id)->pluck('curso_relacionado_id')->toArray();

Laravel 5.4 - how to find specific record in relation

I have some eloquent models named Client and Company. And my Client may belong to multiple Company:
public function companies()
{
return $this->belongsToMany(Company::class);
}
I'd like to check if provided Client belongs to given Company. This is what I ended up with:
$client->companies
->filter(
function ($value, $key) use ($company) {
return $company->getKey() === $value->getKey();
}
)
->count() > 0;
Is there any shorter way?
Using models and the relationship collection:
$client->companies->contains($company);
Using relationship query to check existence:
$client->companies()->where('company_id', $company->id)->exists();
// even shorter, and don't need to know about the key yourself
$client->companies()->whereKey($company)->exists();
Going form the other direction:
$company->clients->contains($client); // if setup
$company->clients()->where(....)->exists();
You can always use your relationship method to query the relation:
$client->companies()->where('company_id', $company->id)->exists();
This uses the query builder to actually query the relation at the database level, unlike when you treat companies as a property which gets a collection of all of the related rows from the database.
Try
$myArray = $client->companies->comp_id;
where comp_id can be any column name. This should return an array. Then check if the array is empty by doing:
if (empty($myArray))

Laravel/Eloquent Relationship Inconsistent

I'm trying to get information associated with an application in my database.
Each application has 1 applicant.
Each application has 1 puppy.
I'm returning a view with an eloquent query like this:
$active_applications = Application::with('applicant', 'puppy')->where('kennel_id', '=', $user_kennel->id)->get();
And I have some relationships defined in my application model like so:
public function puppy(){
return $this->belongsTo('App\Puppy');
}
public function applicant(){
return $this->belongsTo('App\User');
}
When the view loads, I'm able to get the information associated with 'puppy'. It retrieves properly. The applicant, however stays null.
I have, in my applications table, a column named "user_id", which I was hoping it would use value in that column to search the users table 'id', and retrieve information on the user. It stays null, however. The following is a dd() of the variable in question:
Am I missing something obvious? Why would it retrieve one and not the other?
EDIT: the puppy table
Your relation is wrong -
public function applicant(){
return $this->belongsTo('App\User');
}
When you don't pass the foreign key as a parameter, laravel looks for the method name + '_id'. Therefore in your case laravel is looking for the column applicant_id in your application table.
So, to get results there are two ways -
1) You need to either change your method name -
public function user(){
return $this->belongsTo('App\User');
}
**2) Pass foreign key as the second parameter - **
public function applicant(){
return $this->belongsTo('App\User', 'user_id');
}
Laravel 5.6 doc - belongsTo
If its a One to Many(Inverse) Relation -
Eloquent determines the default foreign key name by examining the name
of the relationship method and suffixing the method name with a _
followed by the name of the primary key column.
If its a One to One Relation -
Eloquent determines the default foreign key name by examining the name
of the relationship method and suffixing the method name with _id.
Review Laravel doc for more details
Try the following line instead:
$active_applications = Application::with(['applicant', 'puppy'])->where('kennel_id', '=', $user_kennel->id)->get();
As far as I know, multiple "with" should be passed as array.
Adjust the relationship as well
public function applicant(){
return $this->belongsTo('App\User', 'user_id');
}

Laravel only delete a model if no related model exist

Lets say i have a model called 'manufacturer' and this model has one to many relation with another model 'vehicle'. Now i dont want to let users delete a manufacturer if there are any vehicles associated with this model.
//In Manufacturer model
public function vehicles()
{
return $this->hasMany('Vehicle');
}
And in the repository/controller i have another method to check for it.
public function checkAssociatedVehicles($id)
{
return Manufacturer::with('vehicles')->find($id)->toJson();
}
This does outputs the manufacturer data with all the associated vehicles. but this is not efficient, so i just want to check that if there is even one vehicle then dont delete the manufacturer.
I believe you'd want to use the has method to make sure the manufacture has some vehicles.
$manufacture = Manufacturer::has('vehicles')->find($id);
Then you'd just want to make sure !is_null($manufacture)
As you have a vehicles() method in your Manufacturer model, you may just do this:
Use the whereDoesntHave method to filter all Manufacturers without vehicles before deleting them:
Manufacturer::whereDoesntHave('vehicles')->get();
From the API:
Add a relationship count condition to the query with where clauses.
You can return the count of total vehicles like this:
return [
'count' => Manufacturer::with('vehicles')->find($id)->count()
];
Now you can just check the count.
This will return boolean on whether there is an vehicles on the manufacturer.
return (Manufacturer::with([
'vehicles'=> function($query){
return $query->limit(1);
}])->find($id)->vehicles);
You can add foreign key and prima key on the vehicles to reduce the number of column being query for performance concern.
return $query->limit(1)->select('id','manufacturer_id');

Categories