I have a scope function for my user table (User.php):
public function scopeWherePaidSubscriber(Builder $query)
{
return $query->where(....)->where(...);
}
I am trying to access this scope from a subquery looking like this:
$count = UserCalendar::whereIn('user_id', function($que) {
$que->select('id')->from('user')->wherePaidSubscriber();
})->distinct('user_id')->count();
But then I noticed than I couldn't access the scope because I am not using User::wherePaidSubscriber().
The error message looks like the following:
Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'paid_subscriber'
Eloquent probably tried to find a column named paid_subscriber since it cannot access the scope for the User table.
Is there a way for me to access the scope without having to copy paste it?
Instead of function just pass the data containing the id list of user table as an array.
User::wherePaidSubscriber()->pluck('id')->toArray();
Related
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.
I have my class "Product_reviews", which is binded to the class "Products" like this:
Products.php:
public function product_reviews()
{
return $this->hasMany('App\Product_reviews');
}
Product_reviews.php:
public function products()
{
return $this->belongsTo('App\Products');
}
Foreign key for table "Product_reviews" is 'product_id'.
So, in the controller I'm trying to get all data:
$products = Products::with('product_reviews')->get();
And... I have an error saying that product_id can't be found:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'product_reviews.products_id' in 'where clause' (SQL: select * from `product_reviews` where `product_reviews`.`products_id` in (1, 2))
Correct me if I'm wrong, but I think the query builder is adding '_id' to the class' name. It can be fixed by going to the table "product_reviews" and changing 'product_id' by 'products_id'... Or maybe I could pass all classes' and tables' names to singular.
So my question is: What other options do I have in order to make the query builder know the proper column's name?
Your models should be named in the singular form, and then Laravel will not attempt to use the plural form of the column name in the generated SQL query.
In your case, the Products model should be called Product. Remember that a model represents one record in your database, so the singular form is correct.
You overwrote this behaviour by manually setting the foreign field in your $this->hasMany(..) relationship, which skirted around the issue, but didn't fix the underlying cause.
Additionally, you should avoid using snake_cased class names, as it violates PSR. Your Product_reviews model should be called ProductReview.
Ok, I got it:
In Products.php:
return $this->hasMany('App\Product_reviews');
I added 2 more parameters to the function hasMany, like this:
return $this->hasMany('App\Product_reviews','product_id','id');
These parameters specify the id's names.
This post really helped:
laravel-hasmany-and-belongsto-parameters
Anyhow I think it may be good in long terms to do what Davit and hktang say and rename my classes with singular names. Thanks for your answers.
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()
I have a users table and a permissions table. It's a many-to-many relationship so I also have a users_permissions table with a user_id & module_permission_id column.
The user model has the following relationship:
public function permissions()
{
return $this->belongsToMany(Permission::class, 'users_permissions', 'user_id', 'module_permission_id');
}
When I run my query, the result contains an empty permissions array.
User::with('permissions');
If I echo the query in the with, I get the error: Call to undefined relationship [] on model [App\Models\User]
User::with(['permissions', function($q) {
echo $q->toSql();
die();
}]);
The rest of the query works, it's just trying to get permissions which is failing.
In my case it was a coding convention issue related to camelCase vs. snake_case:
In the Model there was
public function getPermissions()
and in the query there was
User::with(['get_permissions'])
When I changed this to
User::with(['getPermissions'])
it started to work, although I'd say the Laravel way would be to use snake_case instead.
This confused me for a couple of days since frameworks like Symfony and AngularJs has a mixed conventions that somewhere you need to write parameters in snake_case and somewhere else in camelCase. I didn't find any documentation on Laravel site how they handle this, so I tried it the Straight Way and it seemed to be the case here :)
Maybe you just forgot the ->get() after User::with('permissions')->get() ?
https://laravel.com/docs/5.0/eloquent#eager-loading
Slapping this here for anyone who may be trying to refactor from an eager load that selects columns to an eager load with a scoped query.
You HAVE to move the selecting of columns into the scoped query, trying to select columns with the usual colon notation will fail and throw the undefined relationship error.
For example going from this eager load that selects a pivot table column, and a column from the permissions table User:with('permissions:permission_tag:tag_set_id,permission_name') to a scoped query that selects the same columns but also orders the results looks like this
User::with([
'permissions' => function ($query) {
$query->select('permission_tag:tag_set_id', 'permission_name');
$query->orderBy('permission_name');
},
]);
Notice I pulled out the : notation and it lives right in the scoped query.
I have a model class named Car => $car = new Car; attached to a MySQL table.
and I'm fetching all table rows using Car::All();
further, I'm also writing a query scope for fetching "diesel" engine cars only, as below
public function scopeGetDieselEngineCars($query){
$query->where("engine_type","=","Diesel");
}
But, on running Car::All()->getDieselEngineCars() . This gives a function not found error.
What am i doing wrong?
Your scope setup is right. However, you need to first apply the scope, then get the results:
Car::getDieselEngineCars()->get();
It should work for your case.