Access model attributes in Laravel update query - laravel

I have an UPDATE query that I'm struggling with, basically want to access its column during update.
I have a users table (with existing data) with a column address where a string value is added. To make things cleaner I created a separate table locations to store all the addresses and set up foreignId('location_id') on the users table.
locations table is then filled by getting unique address values from users table.
Now I need to update the location_id of existing users.
**This is what I tried:**
$locations = Location::get(); // only about 100 results are there
User::query()
->whereNotNull('address')
->update([
'location_id' => $locations->firstWhere('street', DB::raw('address'))->id
]);
But the above query is not updating the column "location_id" on users table.
Model Relationships
// On Location Model
public function users()
{
return $this->hasMany(\App\Models\User::class);
}
// On User model
public function location()
{
return $this->belongsTo(\App\Models\Location::class);
}

You issue is that DB::raw('address') probably does not return anything so my suggestion is to update the whole query.
$locations = Location::all();
User::whereNotNull('address')->each(function($user){
$locations = $locations->where('name', $user->address)->pluck('id');
$user->attach($locations);
})
The above query will get all the locations first, then we get all the users who have an address and for each of those users we first find all the locations with that address, get the ids of those locations, add attach those locations to the user.

Related

Return a json file of only the latest records per each foreign key in laravel

I am new to laravel and working through my first project. I have 2 tables a payments table and tenants table
payments Table => id, amount, rent_from, rent_to, created_at, updated_at , tenant_id
tenants table => .......
The tenants table has a one to many relationship with the payments table.
I need to return a json file of only the latest payments per each tenant_id.
The code
public function getPaymentsList(Request $request)
{
$payments= DB::table("payments")
->where("tenant_id",$request->tenant_id)
->pluck("rent_to")
;
return response()->json($payments);
}
**Returns all the 'rent_to' records per tenant_id.
How can i return only the most recent 'rent_to' record for each tenant_id as json file?
You might consider using Eloquent instead of the Query Builder for the full Laravel experience. But you would probably want to set up a special relationship in your Tenant model to make things easier.
Tenant.php
public function latestPayment()
{
return $this->hasOne(Payment::class)->latest();
}
Then you can use the relationship to obtain the results.
YourController.php
public function getPaymentsList(Request $request)
{
$payments = Tenant::with('latestPayment')->get()->pluck('latestPayment.rent_to','id');
return response()->json($payments);
}
// "tenant_id": "rent_to"
//
// {
// "101": "rent_to value...",
// "102": "rent_to value...",
// ...
// }

Laravel, How to retrieve parent records with certain Pivot table values belongsToMany

How can I retrieve all records of my model based on certain ID's in my pivot table?
I have the following 3 tables
users;
id,
name
stats;
id,
name
stats_selected;
user_id,
stats_id
Model
User.php
public function stats()
{
return $this->belongsToMany('App\stats', 'stats_selected', 'user_id', 'stats_id')->withTimestamps();
}
Controller
// Get all users with example of stats ID's
$aFilterWithStatsIDs = [1,10,13];
$oUser = User::with(['stats' => function ($query) use($aFilterWithStatsIDs ) {
$query->whereIn('stats_id', $aFilterWithStatsIDs);
}])
->orderBy('name', 'desc')
->get()
This outputs just all the users. Btw, fetching users with there stats and saving those selected stats into the DB is not a problem. That works fine with the above lines.
But how do I retrieve only the users which has certain stats_id's within them?
But how do I retrieve only the users which has certain stats_id's within them?
Use a whereHas conditional.
User::whereHas('stats', function ($stats) use ($aFilterWithStatsIDs) {
$stats->whereIn('id', $aFilterWithStatsIDs);
});

Laravel: return multiple relationships

I have the following table:
The table is called user_eggs and it stores the user eggs.
eggs are items with additional data (hatch_time)
As you can see, user 2 has 2 eggs, which are items 46 and 47.
My items table stores the item general information such as name, image, description, etc...
How I can return the user eggs using $user->eggs() including the item data in my items table of the egg item_id?
I tried:
User Model:
/**
* Get the eggs
*/
public function eggs()
{
return $this->belongsToMany(Egg::Class, 'user_eggs','user_id','item_id')
->withPivot('id','hatch_time');
}
but $user->eggs() returns an empty array.
Any ideas?
A simple approach will be:
in your UserEgg model define:
/**
* Get the user associated with egg.
*/
public function _user()
{
return $this->belongsTo('App\User','user_id');
}
/**
* Get the item associated with egg.
*/
public function item()
{
return $this->belongsTo('App\Item','item_id');
}
then in your controller:
use the model to extract everything like this:
$userEggs = UserEgg::where('user_id',2)->get();
foreach($userEggs as $userEgg){
$associateduser = $userEgg->_user;
$associatedItem = $userEgg->item;
}
Short answer
If you loop through the user's eggs:
foreach($user->eggs as $egg){
$item = Item::find($egg->pivot->item_id);
}
If you want to query:
$user->eggs()->wherePivot('item_id', 1)->get();
Long answer
From the Laravel Documentation
Retrieving Intermediate Table Columns
As you have already learned, working with many-to-many relations requires the presence of an intermediate table. Eloquent provides some very helpful ways of interacting with this table. For example, let's assume our User object has many Role objects that it is related to. After accessing this relationship, we may access the intermediate table using the pivot attribute on the models:
$user = App\User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
Notice that each Role model we retrieve is automatically assigned a pivot attribute. This attribute contains a model representing the intermediate table, and may be used like any other Eloquent model.
By default, only the model keys will be present on the pivot object. If your pivot table contains extra attributes, you must specify them when defining the relationship:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
If you want your pivot table to have automatically maintained created_at and updated_at timestamps, use the withTimestamps method on the relationship definition:
return $this->belongsToMany('App\Role')->withTimestamps();
Filtering Relationships Via Intermediate Table Columns
You can also filter the results returned by belongsToMany using the wherePivot and wherePivotIn methods when defining the relationship:
return $this->belongsToMany('App\Role')->wherePivot('approved', 1);
return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);

laravel one-to-many get data without inner join

I am trying to get a feel around the laravel ORM and I have the following models.
I have a:
user table with- id, firstname, lastname
city table with - id, name
usercity table with - user_id, city_id
The usercity table tracks the cities the user has visited.
I added the following in city model:
public function usercity()
{
return $this->hasMany('App\UserCity');
}
And another function in user model
public function usercity()
{
return $this->hasMany('App\UserCity');
}
I also added a model for UserCity and added following function there.
public function city()
{
return $this->belongsTo('App\City');
}
public function user()
{
return $this->belongsTo('App\User');
}
Now, the goal is to retrieve all the cities a user has visited. I used the following function.
$usercities = User::where('id','=',1)->first()->usercity()->get();
This works in the sense that it retrieves the user_id and city_id.
What would i need to do to get all the fields in the city table also?
Current response:
[[{"user_id":"1","city_id":"1"},{"user_id":"1","city_id":"2"},{"user_id":"1","city_id":"3"},{"user_id":"1","city_id":"4"}]]
I might be able to use inner join but I wanted to see if there was another way to retrieve the data which safely populates the data for me.
What you really have is a many-to-many relationship between users and cities, with the usercity table being the pivot table. Laravel uses the BelongsToMany relationship to implement this. You'll need to make a few changes to get this to work.
In your city model:
public function users() {
return $this->belongsToMany('App\User', 'usercity');
}
In your user model:
public function cities() {
return $this->belongsToMany('App\City', 'usercity');
}
You can get rid of the UserCity model. There is usually no reason to need a model for the pivot table.
The usercity table may need to be updated to add an id field as the primary key. I've not tried it without one, however, so it may work as you have it. Also, if you wanted, you could rename the table to city_user to conform to Laravel conventions, and then you wouldn't need to specify the table name in the relationship definitions.
Once your relationships are setup correctly, you can access a user's cities via the cities relationship on the user, and you can access a city's users via the users relationship on the city. For example:
// all of the cities visited by user 1
$user = User::find(1);
$usercities = $user->cities;
// all of the users that have visited city 1
$city = City::find(1);
$cityusers = $city->users;
You can find more information about the relationships in the documentation here.

laravel - eloquent - get sum of related model specific column

assuming that I have the table
orders
with fields
id, userId, amount, description
and the table
user
with various fields
how if I wand to get all the users (with all its fields) and also the sum of the "amount" column of the orders related to that user?
assuming that I have:
user:{id:15,firstName:jim,lastName:morrison,gender:male}
and
order:{id:1,userId:15,amount:10,description:"order xxx"},
order:{id:3,userId:15,amount:40,description:"order yyy"}
I would like to receive:
user:{id:15,firstName:jim,lastName:morrison,gender:male,orderAmount:50}
Of course I would like to avoid the foreach statement.
I've setted this on my user model
public function userOrder (){
return $this->hasMany('Order', 'userId');
}
And I've tryed this:
return $this->hasMany('Order', 'userId')->sum('amount');
without any luck...
Some thaughts and hopefully an answer to your question:
I would rename the user table to users to stick to laravel conventions.
http://laravel.com/docs/4.2/eloquent#basic-usage
I would name the method in the User model orders
public function orders()
{
return $this->hasMany('Order', 'userId');
}
To query a user, his orders and sum afterwards his orders amount values:
$userdata = User::with( 'orders' )->where( 'userId', 15 )->first();
$sum = $userdata[ 'orders' ]->sum( 'amount' );

Resources