I'm having trouble retrieving data through relationships.
My database structure (simplified):
orders:
id
user_id
product_id
order_items:
order_id
product_id
I need to get using relationships, all orders along with the items in the array.
Order model:
public function items()
{
return $this->hasMany(OrderItem::class, 'order_id', 'id');
}
Test controller:
public function test()
{
return Order::with('items')->get();
}
Result I got when accessing test():
[
{
"id": "d7baaae9-b925-4ff0-8bba-13e8e88d429b",
"user_id": "fa2a5f73-379d-4ab7-9bc5-81cdbd47f3b0",
"subtotal": "0.00",
"discount": "0.00",
"coupon_code": "0",
"total": "0.00",
"paid": false,
"refunded": false,
"created_at": "2022-07-26T16:41:50.000000Z",
"updated_at": "2022-07-26T17:51:45.000000Z",
"items": [
]
}
]
The "items" array does not exist in the orders table, it is coming through the relationship, but it comes empty. There is a record in the database relating orders with order_items, the OrderItem model is correctly accessing the database when I test. I don't know what the problem could be.
[EDIT_01]: I just found out that the problem is in the id I'm using, I'm using type Uuid (Ramsey\Uuid\Uuid\Uuid::uuid4()) for the keys of my tables, somehow it's not working, but when I testo with conventional ID works. Help-me.
I have the same issue, my fix is I add
protected $keyType = 'string';
to the table which has string id (uuid). Hope it can help
hope you found a solution, if not testing out your code sample here, and everything works fine for me,
public function items()
{
return $this->hasMany(OrderItem::class);
}
use this instead, should give you a better result
Try removing the third parameter and just use this:
return $this->hasMany(OrderItem::class, 'order_id');
This should work given your Database setup example, make sure you actually have items in your database that belong to that order you are debugging as well.
Related
I am working with laravel 8 and have the following table with their models structure
Orders
Id, store_id,client_id,delivery_date,created_at
order_details
Id,order_id,product_id,quantity,total_price
Products,
Id,product_name,product_image
users
id,name,phone,address
I want to retrieve data from 4 tables according to order id to display order with it's details as following json format for example
{
"id":1,
"delivery_date":"20-06-2021",
"created_at":"10-06-2021",
"order_details":[
{
"id":1,
"product_name":"TV",
"product_image":"http://xxxx.com/images/tv.jpg",
"quantity":1,
"total_price":3000
},
{
"id":1,
"product_name":"playstation",
"product_image":"http://xxxx.com/images/playstation.jpg",
"quantity":3,
"total_price":5000
}
],
"client":{
"id":1,
"name":"john",
"address":"somewhere"
}
}
but I don't know how to get these data write code using relations and eloquent in laravel
Some basic idea to help you.
Orders Model
public function products(){
$this->belongsToMany(Product::class,'order_details')->withPivot('quantity', 'total_price')->withTimestamps();;
}
public function client(){
return $this->belongsTo(User::class,'client_id','id');
}
So you can do some think like below to access it
Order::with(['products','client'])->find($orderId);
Similar question but on relationship insert
Ref:Attempt to read property "price" on null in laravel?
In the current application, there is a model Part and a model Supplier. Every Part has a Supplier.
public function supplier()
{
return $this->belongsTo(Supplier::class);
}
I added an accessor to get the name of the supplier.
If i return the whole dataset, i get the supplier:
public function getSupplierNameAttribute()
{
return $this->supplier;
}
"supplierName": {
"id": 1,
"uuid": "37e3a715-09d3-4fac-ae88-8f12e63fe79c",
"name": "Laserteam",
"street": "8602 Dessie Tunnel",
"zip": "15869",
"city": "New Clementview",
"email_send_type": null,
"active": 0,
"created_at": "2020-01-09 09:46:02",
"updated_at": "2020-01-09 09:46:02",
"deleted_at": null,
"action": "",
"activeLabel": "<span class='badge badge-secondary'>Inaktiv<\/span>"
},
If i try to get only the name (what I need finally), there is an error:
public function getSupplierNameAttribute()
{
return $this->supplier->name;
}
ErrorException: Trying to get property 'name' of non-object in file /gopanel/sites/7industry_net/public/7time/app/Models/Part/PartAttribute.php on line 48
If i try in this way, it works:
public function getSupplierNameAttribute()
{
return $this->supplier['name'];
}
Why does return $this->supplier->name; not work?
It's hard to say what could be the problem here, but:
Make sure you don't have supplier in casts for your model
Make sure you don't use supplier for database column name or you don't make somewhere something this
$this->supplier = $this->supplier->toArray();
It seems supplier property somewhere becomes array that's why one notation works but the other doesn't.
I’m not really sure what’s going on there; if you have a supplier relation then accessing the property should lazy-load the relationship.
Alternatively, you could try this syntax:
public function getSupplierNameAttribute()
{
$this->loadMissing('supplier');
return $this->getRelation('supplier')->name;
}
However, I’d avoid defining accessors like this. It can lead to N+1 problems if you say, retrieve a collection of parts and then call $part->supplier_name on each one without eager-loading the supplier relationship.
Personally, if I’m accessing attributing on relations that I prefer to do it through the relation (i.e. $part->supplier->name) so any relations I need to eager load are shown to me.
Try this code
public function getSupplierNameAttribute()
{
return $this->supplier->name ?? 'supplier not exists';
}
I have two tables: statuses and status_logs.
The statuses table has 3 columns: id, name, duration
The status_logs table has 3 columns: id, status_id, created_at
I have two models that look like this:
class Status extends Model{
// Name of our database table
protected $table = 'statuses';
// Defines the relationship between this table and the status_logs table
public function status_logs(){
return $this->hasMany('App\Models\Status', 'status_id');
}
}
class StatusLog extends Model{
// Name of our database table
protected $table = 'status_logs';
// Defines the relationship between this table and the statuses table
public function statuses(){
return $this->belongsTo('App\Models\Status', 'status_id');
}
}
I can get data from both tables by using:
StatusLog::with('status')->get();
The result would look something like:
"status_logs": [{
"id": 1,
"status_id": 1,
"created_at": "02:34:53 10/5/2017",
"statuses": {
"id": 1,
"name": "started"
"duration": 48
}
}]
I would like to add a column called finish_at to each object inside of the status_logs array. This datetime will be the created_at value plus whatever the integer value of duration is. Duration is the number of hours that we need to add to created_at to get the value of finish_at.
The result should look like:
"status_logs": [{
"id": 1,
"status_id": 1,
"created_at": "02:34:53 10/5/2017",
"finish_at": "02:34:53 10/7/2017",
"statuses": {
"id": 1,
"name": "started"
"duration": 48
}
}]
How would I do this?
Use Eloquent appends would solve this.
Add additional attribute and define the value. It would be look something like below.
class StatusLog extends Model
{
protected $appends = ['finish_at'];
public function getFinishedAtAttribute()
{
// carbon to add hours
$dt = Carbon::instance($this->attributes['created_at']);
$dt->addHours($this->statuses->duration);
return $dt->toDateTimeString(); // change to your desire format
}
}
Using Carbon (http://carbon.nesbot.com/docs/#api-addsub), does something like this work for you:
$log->finished_at = $log->created_at->addHours($log->statuses()->duration);
First step is devide the duration in 24.
then add the devided duration in created_at value using using carbon
like this one.
$log->finished_at = $log->created_at->addDays($log->statuses()->duration/24);
$log->save();
I'm having the following problem, I'm using scope in Laravel and I have the following relationship:
Enquiry
pickup_address
dropoff_address
Notes
This is referenced in the model:
public function pickup_address() {
return $this->belongsTo('App\Address', 'pickup_address', 'id');
}
I want to return the enquiry, as well as postcode which is stored in the Address table. I just want this column from this table and I have done the following:
return $query->with(['pickup_address' => function ($query) {
$query->select('postcode');
}])->get();
This gives the following (json):
{
"id":1,
"pickup_address":null
"notes":"hello world",
"created_at":"2017-06-08 09:56:52",
"updated_at":"2017-06-08 09:56:52"
}
This is not giving the postcode and just gives the pickup_address as null. However, removing the $query->select('postcode') gives:
{
"id":1,
"pickup_address": {
"id":140,
"house_number":null,
"address_1":"Address 1",
"address_2":null,
"postcode":"POSTCODE",
"city":"CITY",
"county":"C0UNTY",
"created_at":"2017-06-08 09:56:23",
"updated_at":"2017-06 0}",
"notes":"Hello world","
"created_at":"2017-06-08 09:56:52",
"updated_at":"2017-06-08 09:56:52"
}
However, I'm using Vue and using a table, so I just need the particular field to be returned that matches the column, rather than the entire object being returned.
Can anyone suggest a solution, please? I have followed some examples online and they suggest the $query->select('postcode')
how can i merge laravel relationship results in to one object?
MyController.php
public function getUser($id) {
return TournamentUser::where('customer_id','=', $id)->with('user')->get();
}
MyModel.php
public function user() {
return $this->hasOne('App\Models\Customer','customer_id', 'customer_id');
}
returning result :
[{
"id":1,
"tournament_id":3,
"customer_id":2016827550,
"point":0,
"user":{
"id":1,
"customer_id":2016827550,
"nickname":"OMahoooo"
}
}]
as expected query returns user section as array but i expect result like this :
[{
"id":1,
"tournament_id":3,
"customer_id":2016827550,
"point":0,
"nickname":"OMahoooo"
}]
only get nickname section without user array. I hope you understand me.
Sorry for my english , have a nice day
You can load the data and remap it manually using map() method. I've just tested this code and it works perfectly with hasOne() relationship:
$users = TournamentUser::where('customer_id', $id)->with('user')->get();
$users->map(function ($i) {
$i->nickname = $i->user->nickname; // Set related nickname.
unset($i->user); // Delete user data from the collection.
return $i;
});
Alternatively, you could use an accessor, but in this case, you'll meet the N+1 problem.