Laravel 'hasMany' relationship not working, no idea why - laravel

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

how to retrieve data from 4 table with Eloquent relations in laravel

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?

Laravel attribute not working as expected

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';
}

Laravel 5 / Eloquent - Return a Date Based on the created_on Column Plus Variable Hours

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();

Laravel - Eloquent with select not returning values

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')

Laravel - How to merge relationship results?

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.

Resources