Laravel error: Property [name] does not exist on this collection instance - php

I'm trying to get a partner for each order using Laravel resource collections. But this throws up an error:
Property [name] does not exist on this collection instance
I get partners this way
Order_product.php
//...
class Order_product extends Model
{
protected $fillable = ['order_id', 'product_id', 'quantity', 'price'];
public function partner()
{
return $this->hasManyThrough(
'App\Partner', 'App\Order',
'partner_id', 'id', 'order_id');
//orders partners order_products
}
//...
Resources\Order_product.php
class Order_product extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'order_id' => $this->order_id,
'product_id' => $this->product_id,
'quantity' => $this->quantity,
'price' => $this->price,
'status' => $this->order->status,
'product_name' => $this->prod->name,
//return error
'partner_name' => $this->partner->name,
];
/*
//this method return:
//Invalid argument supplied for foreach() {"exception":"[object]...
$partners = [];
foreach($this->collection as $partner) {
array_push($partners, [
// 'partner_name' => $this->partner->name
]);
}
return $partners;
*/
}
}
Each order has one partner name. In the future, I will group them, but now I just need to output the partner_name

is relations when you use hasMany or hasManyThrough it returns you a collection, so you should use it in foreach or use with index
return [
'product_name' => $this->prod->first()->name, //first array in collection using first()
];
OR
return [
'product_name' => $this->prod[0]->name, //first array in collection using index
];
or you can write this code in foreach!

As you are using hasManyThrough or hasMany laravel relationship returns Illuminate\Database\Eloquent\Collection Instance.
If you want to get name you have to have one Model instance.
Solution 1: $this->parthner->first()->name
Solution 2: See this hasOneThough
public function partner(){
return $this->hasOneThrough(
'App\Partner', 'App\Order',
'partner_id', 'id', 'order_id');
}
Depens on your app logic
Hope this helps you

Related

how to retrieve data using relationship in laravel

I'm trying to retrieve data using relationship in laravel and I'm getting this error all the time.
Column not found: 1054 Unknown column 'orders.customers_id'
in 'where clause' (SQL: select * from orders where
orders.customers_id in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
before this I was using these codes:
$data = DB::table('customers')
->join('orders', 'orders.customer_id', 'customers.id')
->get();
// convert to json string
$data = json_decode(json_encode($data), true);
return $data;
and it return the exactly result I want which is:
Here is my customers table:
orders table
Orders
class Orders extends Model
{
public function customer(){
return $this->belongsTo(Customers::class);
}
}
Customers
class Customers extends Model
{
public function order(){
return $this->hasMany(Orders::class);
}
DataController
class DataController extends Controller
{
public function all()
{
$All = Customers::with('order','order.customer_id')->paginate(10);
return response()->json([
'code' => 0,
'success' => true,
'data' => $All,
'pagination' => [
'current_page' => $All->currentPage(),
'last_page' => $All->lastPage(),
'prev_page_url' => $All->previousPageUrl(),
'next_page_url' => $All->nextPageUrl(),
'per_page' => $All->perPage(),
'total' => $All->total(),
'count' => $All->count(),
]
], 200);
Could you try this one
Order Model
class Orders extends Model
{
public function customer(){
return $this->belongsTo(Customers::class, 'customer_id');
}
}
DataController
class DataController extends Controller
{
public function all()
{
$All = Customers::order()->paginate(10);
return response()->json([
'code' => 0,
'success' => true,
'data' => $All,
'pagination' => [
'current_page' => $All->currentPage(),
'last_page' => $All->lastPage(),
'prev_page_url' => $All->previousPageUrl(),
'next_page_url' => $All->nextPageUrl(),
'per_page' => $All->perPage(),
'total' => $All->total(),
'count' => $All->count(),
]
], 200);
I just put the foreign key in the model already. I'm not entirely sure if its supposed to be in Order Model or in Customer Model either way try those both.
Hope it helps!
Remove order.customer_id from Customers::with('order','order.customer_id')->paginate(10);
So it should be
Customers::with('orders')->paginate(10);
Also as a customer can have many orders it is best to name your relation as orders
class Customers extends Model
{
public function orders()
{
return $this->hasMany(Orders::class);
}
}
In my controller
$All = Customers::with('order')->paginate(10);
return response()->json([
'code' => 0,
'success' => true,
'data' =>$All
], 200);
Customers model
class Customers extends Model
{
public function order(){
return $this->hasMany(Orders::class,'customer_id','id');
}
}
Orders model
class Orders extends Model
{
public function customers(){
return $this->belongsTo(Customers::class,'customer_id','id');
}
}
and its works.
But there is still got one thing which I'm not understand. Its works either I define the relationship in Customers model or Orders model or define the relationship in both

how to use laravel eloquent to get and display data from other tables

I was using these codes in my controller to get all the data from my 2 tables and it works fine
$All = Customers::with('order')->paginate(10);
return response()->json([
'code' => 0,
'success' => true,
'data' => $All
], 200);
Here is how I define the relationship between these 2 tables
class Customers extends Model
{
public function order()
{
return $this->hasMany(Orders::class, 'customer_id', 'id');
}
}
class Orders extends Model
{
public function customers()
{
return $this->belongsTo(Customers::class, 'customer_id', 'id');
}
}
Now my desire output is to hide the order id, order timestamps and change the customer_id to customer's name (the customer's name is not in my orders db table).
I'm using 'data' => DataResource::collection($All) in my controller and this is my DataResource
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => $this->order
];
}
and of course the output is same with the image above.
My database structure:
orders table:
customer table:
Can anyone help me with that?
The answer is simple and basically a copy of the official documentation. You simply need to wrap your orders in an OrderResource as well.
// DataResource
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => OrderResource::collection($this->order)
];
}
// OrderResource
public function toArray($request)
{
return [
'items' => $this->items,
'quantity' => $this->quantity
];
}
I don't really understand why you would want to include the customer_name in your orders when it is already present on the customers object one hierarchy above. But if you really want to add it, you should be able to do so with: 'customer_name' => $this->customers->name.
As a side note: you really should be more consistent with your naming. Why is the resource called DataResource when it is about Customers? Why is your model called Customers in plural form rather than Customer in singular, which is the convention (and more logical if you consider that one model represents one customer). Why is your belongsTo relation called customers() in plural when it returns one customer, while your hasMany relation is called order whereas it returns one or more orders?

Return many object in my json response using resource

I'm kinda new to Laravel and I hope someone we'll be able to give me some help.
I apologize for my english
So I'm trying to develop an application with some friends to manage our food by sending alert when the peremption date is near.
I'm developing the API, the actual structure is this way:
A user,
A product,
A basket containing the user_id, the product_id and of course the peremption date.
So now when I make a call to get the User 'stock' on my API I wish I could get something like this:
{
'id' : 1,
'peremption_date': XX-XX-XX,
'product' : {
'id' : 3,
'name': bblablabala,
'brand' : blablabala
},
'id' : 2,
'peremption_date': XX-XX-XX,
'product' : {
'id' : 4,
'name': bblablabala,
'brand' : blablabala
},
}
So I took a look on resources and saw that if I define the right relations, this could do the stuff for my output.
I'll link you my actual class declarations and their resources:
User:
//user.php
class User extends Authenticatable
{
use Notifiable, HasApiTokens;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function baskets()
{
return $this->hasMany(Basket::class);
}
}
Product:
//Product.php
class Product extends Model
{
protected $table = 'products';
protected $fillable = ['code_barre', 'product_name', 'generic_name', 'brand', 'quantity'];
public function basket()
{
return $this->belongsToMany(Basket::class);
}
}
//productResource.php
class ProductResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'code_barre' => $this->code_barre,
'product_name' => $this->product_name,
'generic_name' => $this->generic_name,
'brand' => $this->brand,
'quantity' => $this->quantity,
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
];
}
}
Basket:
//Basket.php
class Basket extends Model
{
protected $table = 'baskets';
protected $fillable = ['user_id', 'product_id', 'dlc_date'];
public function user()
{
return $this->belongsTo(User::class);
}
public function product()
{
return $this->hasOne(Product::class);
}
}
//BasketResource.php
class BasketResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'dlc_date' => (string) $this->dlc_date,
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
'product' => $this->product
];
}
}
So when I try to store a new basket in my store method:
//BasketController.php
public function store(Request $request)
{
$this->product->storeProduct($request->input('code_barre'));
$att = DB::table('products')
->where('code_barre', '=', $request->input('code_barre'))
->first();
$basket = Basket::create([
'user_id' => $request->user()->id,
'product_id' => $att->id,
'dlc_date' => $request->input('dlc_date')
]);
return new BasketResource($basket);
}
I get the following error (this one)
saying than products.id_basket does not exist and its right, it's not supposed to exist. This is Basket who have a product_id. so I know this is coming from the relationship I declared but I can't figure how to do it right.
Can someone come and save me ???
Thanks a lot, I hope you understood me !
Wish you a good day
As I look at your Basket model, it seems you have to change your:
public function product()
{
return $this->hasOne(Product::class);
}
to:
public function product()
{
return $this->belongsTo(Product::class);
}
Because you have product_id in your baskets table. To use hasOne() relation, you will need to remove product_id from baskets table and add basket_id to products table, because hasOne() relation is something like hasMany(), only calling ->first() instead of ->get()

Laravel array instead of collection

In my Laravel application, I have this model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Division extends Model
{
protected $fillable = [
'name','company_id', 'location_id'
];
protected $casts = [
'name' => 'string',
'company_id' => 'integer',
'location_id' => 'integer'
];
public function company()
{
return $this->belongsTo(Company::class);
}
public function location()
{
return $this->belongsTo(Location::class);
}
}
$division->company returns a collection
$division->location returns an array
Why this two relations has different results? (Sorry for bad formating....)
As you've just shown in the comments (and then edited), you're using it with get(). That's why you're getting a collection and not an object.
$division->company returns an object. Then you're running another query with $division->company->anotherRelationship()->get() which returns a collection of related objects.

Using Fractal's $defaultIncludes

I am trying to use a $defaultIncludes() and am getting an exception --
ErrorException in ViewoptionTransformer.php line 8:
Argument 1 passed to App\Transformers\ViewoptionTransformer::transform() must be an instance of App\Viewoption, boolean given
Following the tutorial (http://laravelista.com/build-an-api-with-lumen-and-fractal/) except I am using Laravel 5.1 not Lumen:
in User model, I have the hasOne relationship with Viewoption called viewoptions
In the UsersController, I eager load viewoptions
public function index(Manager $fractal, UserTransformer $userTransformer)
{
$records = User::with(['locations', 'viewoptions'])->get();
$collection = new Collection($records, $userTransformer);
$data = $fractal->createData($collection)->toArray();
return $this->respondWithCORS($data);
}
In the UserTransformer, I have the $defaultInclude and the includes method
protected $defaultIncludes = ['viewoptions'];
`public function transform(User $user)
{
return [
'id' => $user->id,
'name' => $user->name,
'is_active' => (boolean)$user->is_active,
'is_admin' => (boolean)$user->is_admin,
'is_manager' => (boolean)$user->is_manager,
'role_id' => (integer) $user->role_id,
'email' => $user->email,
'phone' => $user->phone,
'full_sidebar' => (boolean)$user->full_sidebar
];
}
public function includeViewoptions(User $user)
{
$viewoptions = $user->viewoptions;
return $this->collection($viewoptions, new ViewoptionTransformer);
}`
Have a ViewoptionTransformer
`
use App\Viewoption;
use League\Fractal\Resource\Collection;
use League\Fractal\TransformerAbstract;
class ViewoptionTransformer extends TransformerAbstract {
public function transform(Viewoption $item)
{
//return $item;
return [
'id' => $item->id,
'user_id' => $item->user_id,
'voAgency' => (boolean)$item->voAgency,
'voBalanceDue' => (boolean)$item->voBalanceDue,
'voCloseDate' => (boolean)$item->voCloseDate,
'voCommitTotal' => (boolean)$item->voCommitTotal,
'voDistributor' => (boolean)$item->voDistributor,
'voDueDate' => (boolean)$item->voDueDate,
'voFeePercentage' => (boolean)$item->voFeePercentage,
'voRegion' => (boolean)$item->voRegion,
'voSeason' => (boolean)$item->voSeason,
];
}
}`
Worked with these and slight variations of these throughout the day yesterday and I can't rid myself of that exception.
Not all of your users.id corresponds to some viewoptions.user_id.
Just check it:
$records = User::with(['locations', 'viewoptions'])->get();
dd($records);
some viewoptions will be null or false or just undefined
Instead of using collection use item like so
public function includeViewoptions(User $user){
$viewoptions = $user->viewoptions;
return $this->item($viewoptions, new ViewoptionTransformer);
}`
I had a similar issue today, all my other uses of transformers had been with hasMany relationships. I was always instantiating the transformer with a collection of objects.
However, when using a transformer with a belongsTo relationship and instantiating the transformer with only one object (similar to how you are passing only one object from a hasOne relationship) I would get the same boolean given error.
In the end I solved the issue by using 'item' instead of 'collection' when instantiating the transformer.
Within your includeViewoptions function
Instead of using
return $this->collection($viewoptions, new ViewoptionTransformer);
try
return $this->item($viewoptions, new ViewoptionTransformer);

Categories