I'v use below function to select the last id from schedul table but it not cocrrected
'loan'=>function($s) {
$s->with(['schedule'=>function($schedule){
$schedule->select(DB::raw('loan_id, schedule_date, principal as schedule_principal','max(id) as id'));
}]);
}]);
Change the select to:
DB::raw('loan_id, schedule_date, principal as schedule_principal, max(id) as id')
Related
I would like to check a limit in number of user payment where a limit is set on user table.
So i have the following database structure
table user
id,name,...,pay_limit
and payment table
table payment
id, user_id, payment_ref
So i have created the following code
$query = User::query();
//other stuff
$query->leftJoin('payment','payment.user_id','=','user.id')
//stuck
Am stuck on how to check if the totals of payments on a user is not greater than the user pay_limit
How can i check the above in a query
Simple with relations. Suppose payment model is Payment and payment amount in payment_amount column
class User extends Model{
public function payments()
{
return $this->hasMany(Payment::class);
}
public function getIsOverLimitedAttribute(): bool
{
//if you check amount
return $this->payments()->sum('payment_amount') > $this->pay_limit;
//or if you check count of payments
return $this->payments()->count() > $this->pay_limit;
}
public function scopeNoOverLimited($query){
return $query->withCount('payments')->having('payments_count', '<', $this->pay_limit);
}
}
And use
if($user->isOverLimited){
//do stuff
}
Or get not over limited users:
User::noOverLimited()->get();
In terms of performance (since you want to be able to return all such users), the best approach is to store a summary column in your users table... total_payment
You can update all current users maybe via a migration file as such:
$table->integer('total_payment')->unsigned()->nullable();
DB::update("update users set total_payment = ('select count(id) from payments where user_id = id')");
Then to get all such users, you can do:
User::whereRaw('total_payment > pay_limit')->get();
Then add a PaymentObserver to increase the total_payment on new successful payments.
If you don't have access to modify the table, you can still use a scope like, but this can be performance intensive if being run all the time such as on user login without caching:
public function scopeAboveLimit($query)
{
$id = $this->id;//user id
return $query->whereRaw("pay_limit < ('select count(id) from payments where user_id = $id')");
}
I have 2 table and 1 pivot table which I use as table Historical, the column 'dateChange' indicated the store where is the employee, because I use Orderby ('dateChange','DESC'). All is ok, however how can I FILTER the results in my controller? without REPEAT records?.
I need to show all the employees that belong to a unique store. I repeat again: I use 'dateChange' for I know the last store. help me, please. Thanks
Pivot Table (employee_store)
FK_idStore
FK_idEmployee
dateChange
Table Employee
idEmployee
Name
Table Store
idStore
nameStore
direction
Model
public function employee(){
return $this->belongsToMany(employee::class,'employee_store', 'fk_idStore','fk_idEmployee')
->withPivot('dateChange')->orderBy('dateChange','DESC');
Controller
$store= Store::findOrFail($id)->employee
return $store
You have to change
public function employee(){
return $this->belongsToMany(employee::class,..
to
public function employees(){
return $this->belongsToMany(Employee::class,..
you should use eager loading:
in your Controller
$store= Store::findOrFail($id)->with('employee')->get();
return $store;
more details in:
https://laravel.com/docs/7.x/eloquent-relationships#eager-loading
To get the last record of each employee in each store, use:
public function employee(){
return Employe_Store::all()->groupBy('fk_idEmployee')->max('dateChange');
}
I am very confused with this relationship, i tried video tutorial but couldn't get how to solve this relationship. Thanks in Advance If someone can explain me.
I tried in mysql that's working fine but i am learning laravel and want to do like this.
User
---------
id
email
name
address1
address2
country
Product
-------
id
internal_name
display_name
Licence
------
id
product_id
key
Linked_licence
--------
licence_id
user_id
User has many licences through linked_licence
I am using like this but getting error :
public function licences()
{
return $this->hasManyThrough(Licence::class, UserLicence::class, 'licences.id', 'user_id', 'licence_id');
}
User has many products through licence
public function licences()
{
return $this->hasManyThrough(Product::class, Licences::class, 'licences.id', 'user_id', 'licence_id');
}
Product belongs to licence
public function licences()
{
return $this->belogsTo(Product::class);
}
This is error :
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'licences_user.licences.id' in 'field list' (SQL: select `licences`.*, `licences_user`.`licences`.`id` from `licences` inner join `licences_user` on `licenscs_user`.`id` = `licences`.`user_id` where `licences_user`.`licences`.`id` is null)
But problem is i don't know about laravel relationship how to create these kind of queries.
Updated :
SELECT
`users`.*,
`licences`.*,
`licenses_user`.`license_id`
FROM `licences`
INNER JOIN `licenses_user` ON `licenses_user`.`license_id` = `licences`.`id`
INNER JOIN users ON licenses_user.user_id = users.id
WHERE `licenses_user`.`license_id` = 1
Above query working but how to use with laravel ?
Your problem seems to be to do with this line of code
Licences::class, 'licences.id', 'user_id', 'licence_id');
it appears that the column does not exist in the table from looking at your error.
double check your spelling, it looks like it's looking inside the table called licences_user for a column named lincences.id
I am trying to
1. select `DOS`,`name`,`fin`,`ins_type` from events table.
2. site_name from sites table
3. client_name from clients table
but unable to access site_name, client_name column in select statement
->select('DOS','name','fin','ins_type')
How to add these columns site.site_name, client.client_name in above select statement.
Eloquent query is
$events = Event::with([
'site'=>function($q){
$q->select('site_id','site_name','client_id');
},
'site.client'=>function($q2){
$q2->select('client_id','client_name');
}])
->select('DOS','name','fin','ins_type')
->get();
How about this?
$events = Event::with([
'site'=>function($q){
$q->with(['client'=>function($qq){
$qq->select('client_id','client_name');
}])->select('site_id','site_name','client_id');
}])
->select('DOS','name','fin','ins_type')
->get();
I found a simple solution from the comment section in here. It is possible to put the column selection in the model. So in your case, your Event model could be something like this.
public function site()
{
return $this->belongsTo('App\Site')->select('id', 'name', 'client_id');
}
Then, in your controller you simply call the function.
$events = Event::with('site')->get();
I haven't tried how this goes with the nested eager loading though.
I myself got a little problem with these also until i discover that you need to add the foreign key to the select statement inside the "with" closure.
the column that relates "client" to "site" and "site" to "Event"
I have a pivot table set up with the following columns:
table - contributions
=====================
id - int, pk
user_id - int, fk
resource_id - int, fk
linked_id - int, fk
...
This basically creates a many-to-many relationship between users and resources. Now, the thing is, linked_id is also a foreign key which points to the ID in the resources table. In most cases, linked_id will just be null and won't be a problem. But sometimes, I want a contribution to be linked to a user, a resource, and one other resource.
In my Resource model I have the following code:
public function contributions()
{
return $this->hasMany('Contribution');
}
But this won't return anything if I'm calling this on a Resource which has its ID in the linked_id column. Is there some way to return all the rows/relations when the resource's ID is found in either the resource_id or the linked_id column? (Somehow has a second $foreignKey value).
Hm, options:
1) create a custom query where you retrieve the Resource, join the contributions table where you match resource_id or linked_id on the current id from the Resource object.
something like:
SELECT R.*
FROM resources AS R
INNER JOIN contributions AS C ON (
C.`resource_id` = R.`resource_id`
OR C.`linked_id` = R.`resource_id`
)
WHERE R.`id` = {$Resource->id}
GROUP BY R.`id`
2) create a second relation method, linkedContributions, which matches the linked_id column.
public function linkedContributions()
{
return $this->hasMany('Contribution', 'linked_id');
}
and retrieve the data:
$Resource = Resource::with(['contributions', 'linkedContributions'])->find(1);
3) other idea; you are currently able to link only 1 resource to another resource. If you create an extra table + hasMany 'linkedResources' relation, you will be able to link multiple resource back to the current Resource. (and skip this problem here altogether)
I modified my contributions function inside my Resource model like so:
public function contributions()
{
return DB::table('contributions')
->where('resource_id', '=', $this->id)->orWhere('linked_id', '=', $this->id)
->join('resources', function($join) {
$join
->on('resources.id', '=', 'contributions.resource_id')
->orOn('resources.id', '=', 'contributions.linked_id');
})
->groupBy('contributions.id')
->select(
'contributions.id', 'contributions.description', 'contributions.created_at', 'resources.id AS tileId', 'resources.name AS tileName',
'users.id AS userId', 'users.username')
->get();
}
The linked contributions will now show up in both models without having to create two entries for each link.