PHP error: Undefined property: Illuminate\Database\Eloquent\Collection::$retails - php

Hello I'm trying get my objects on laravel like this.
But I'm getting this error.
PHP error: Undefined property: Illuminate\Database\Eloquent\Collection::$retails on line 18
Also this is my code.
public function index(){
$retails = Auth::user()->companies->retails->all();
return view('retails/retails', compact('retails'));
}
Company Model
class Company extends Model
{
public function retails(){
$this->hasMany(Retail::class);
}
}
Retail Model
class Retail extends Model
{
public function company(){
return $this->belongsTo(Company::class);
}
}

You have many companies. That is why you get a collection from
Auth::user()->companies
When you call ->retails from the collection instance, you get the exception you wrote.
You have to eager load the companies with retails and then loop through them.
Like:
$u = auth()->user();
$u->load('companies.retails');
$userRetails = [];
$u->companies->each(function($company) use (&$userRetails) {
$userRetails = array_merge($userRetails, $company->retails->toArray());
});
$userRetails = collect($userRetails);
return view('retails/retails', compact('userRetails'));

According to your code, you're trying to access collection from a collection which is impossible, you should individually fetch a collection first and do your process
public function index(){
$companies = Auth::user()->companies;
foreach($companies as $company) {
$retails_arr[] = $company->retails;
}
$retails = collect($retails_arr); // Gives Collection or
// Or if you want to send array, try this
$retails = $retails_arr; // Gives Array
return view('retails/retails', compact('retails'));
}
Try this out hope this helps..

Related

Laravel - can't save morphToMany relation in foreach loop

I have the following 2 models in a morphToMany relationship: Company and Tag
public function tags(){
return $this->morphToMany(Tag::class, 'taggable');
}
public function companies(){
return $this->morphedByMany(Company::class, 'taggable');
}
and I have the following working action to save 1 tag to 1 company:
public function addTag($request){
$company = Company::find($request->company_id);
$company->tags()->syncWithoutDetaching($request->tag_id);
return response()->json($company->tags, 201);
}
now I'm trying to do the same thing with many companies and many tags and it is not working. I've tried "syncWithoutDetaching", "saveMany", passing in an array of integers or strings, I keep getting this error:
BadMethodCallException: Method Illuminate\Database\Eloquent\Collection::tags does not exist. in file /home/vagrant/.../vendor/laravel/framework/src/Illuminate/Support/Traits/Macroable.php on line 100
This is the function I am using:
public function multiCompanyAddTags($request){
$tags = $this->createManyRecords('App\AppSections\CRM\Models\Tag', $request->new_tags);
$tagIDs = $tags->map(function ($item, $key) { return $item->id;
});
foreach ($request->companies as $key=>$id)
{
$company = Company::with(['notes','tags','contacts','tasks'])->find($id);
$company->tags()->syncWithoutDetaching($tagIDs);
return response()->json($company, 201);
}
}
Someone pointed me to the answer: When calling $company = Company::with... in my loop, the call returns a collection and not the company.
I then need to call the first item of the collection to access the company, like so:
$company[0]->tags()->syncWithoutDetaching($tagIDs);

Laravel Accessor on demand on relationship

Problem: I have accessor in Size.php model which is called in relationship with Item.php Model, in API i need the accessor to work, but in other controllers i want to disable the accessor. I have removed unnecessary/unrelated code from all files.
What i want to do:
In ItemControllerAPI i need accessor to work, but i want to disable accessor in other controllers.
I have already seen:
I have already seen these links but didn't work for me.
1: https://laracasts.com/discuss/channels/eloquent/accessor-on-demand-but-not-on-every-results
2: Create dynamic Laravel accessor
3: https://laracasts.com/discuss/channels/general-discussion/eager-load-accessors
Size.php (Model)
class Size extends Model
{
protected $appends = ['addons'];
public function items()
{
return $this->belongsToMany('App\Item', 'items_sizes')->withPivot('price');//->withTimestamps();
}
public function getAddonsAttribute($value)
{
$addon = Addon::where('addons.category_id', $this->category_id)
->where('size_id', $this->id)
->get();
return $addon;
}
}
Item.php (Model)
class Item extends Model
{
public function options()
{
return $this->belongsToMany('App\Option', 'items_options')->withTimestamps();
}
public function sizes()
{
return $this->belongsToMany('App\Size', 'items_sizes')->withPivot('price');//->withTimestamps();
}
}
ItemControllerAPI.php (Controller)
class ItemControllerAPI extends BaseControllerAPI
{
public function show($id)
{
// If i call the Size model directly by using setAppends([]) its working fine,
// its removing the appended array from Size model
// $size = Size::all();
// $size->each->setAppends([]);
// return $size;
// If i use it with relationship it won't work.
// $itemSingleQuery = Item::with(['sizes' => function($query)
// {
// Doesn't work
// $query->setAppends([]);
// Doesn't work
// $query->each->setAppends([]);
// }])
// ->with('options')
// ->where('id', $id)
// ->get();
// query for getting data with relationships
$itemSingleQuery = Item::with('sizes')
->with('options')
->where('id', $id)
->get();
return $this->respondSuccess('content found', $itemSingleQuery);
}
}
I've found out how to do this:
After getting the entire collection we need to call setAppends() in each model, which contains appends, to add or remove them before serialization to array or JSON.
$itemSingleQuery = Item::with('sizes')->get();
$itemSingleQuery->each(function ($item) {
$item->sizes->each->setAppends(['addons']);
});
I would suggest that you set $appends when you need it:
$itemSingleQuery->pluck('sizes')->collapse()->each->setAppends(['addons']);

many to many attach() says trying to get property of non-object

I have two database tables journeys and stops that are related in a many-to-many relationship. There is also the third table journey_stop (the pivot table) for the relationship.
Models
Here is my Journey.php model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Journey extends Model
{
public function stops() {
return $this->belongsToMany('App\Stop');
}
}
and the Stop.php model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Stop extends Model
{
public function journeys(){
return $this->belongsToMany('App\Journey');
}
}
Controller
Now in my controller, I have written a method changeStop(stop, journey_id) which takes a particular journey_id and either assigns a stop to it.(that is, creates a relationship between that particular stop and the journey) or removes the stop from the journey if it already exists.
Here is the method:
public function changeStop(Request $request, $id)
{
$stop = $request->all();
$journey = Journey::find($id);
if ($journey->stops()->contains($stop->id)) {
$journey->stops()->detach($stop->id);
}else{
$journey->stops()->attach($stop->id);
}
return $journey->stops();
}
But the line with the if statement throws the error:
Trying to get property of non-object
I have also tried using DB to query the pivot table directly but it throws the same error. Here's the code with DB:
public function changeStop(Request $request, $id)
{
$stop = $request->all();
$journey = Journey::find($id);
if (
DB::table('journey_stop')->where(
'journey_id',
$id
)->where(
'stop_id',
$stop->id
)->count() > 0
) {
$journey->stops->detach($stop->id);
} else {
$journey->stops->attach($stop->id);
}
return $journey->stops();
}
Everything seems right for me. But it doesn't work. What am I doing wrong?
Thanks for your time :)
You may also use the sync method to construct many-to-many associations. The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table
$journey->stops()->sync([$stop_id])
And to work for your above code try this:
public function changeStop(Request $request, $id)
{
$stop = $request->all(); // returns an array
$journey = Journey::find($id);
if ($journey->stops->contains('id', $stop['id'])) {
$journey->stops()->detach($stop['id']);
} else {
$journey->stops()->attach($stop['id']);
}
return $journey->stops;
}

Get laravel data with relation between tables

I have the following data models:
class Cliente extends Model
{
public function sector()
{
return $this->belongsTo(Sector::class,'sectoresId');
}
}
class Sector extends Model
{
public function sectorLanguage()
{
return $this->hasMany(SectorLanguage::class,'sectoresId');
}
public function cliente()
{
return $this->hasMany(ClienteLanguage::class,'sectoresId');
}
}
class SectorLanguage extends Model
{
public function sector()
{
return $this->belongsTo(Sector::class,'sectoresId');
}
public function idioma()
{
return $this->belongsTo(Idioma::class,'idiomasId');
}
}
I want to recover all the active clients and the name of the sector to which it belongs, if I do something like this
$cliente = Cliente::where('active','1');
When I run $client I can not enter the attribute
foreach($cliente as $cli) {
$cli->sector->sectorLanguage->nombre;
}
Why? It only works for me when I find it by id
$cliente = Cliente::find(1);
echo $cliente->sector->sectorLanguage->nombre;
How can I get what I need without resorting to doing SQL with Query Builder.
Thank you very much, greetings.
According to your defined relations, the Sector has many sectorLanguage, it means you're receiving a collection, so you should work on an object like this:
$cliente->where('active', 1)
->first()
->sector
->sectorLanguage
->first()
->nombre;
Cliente::where('active', 1) and sectorLanguage gives you the collection, so you
should first get the first item from $cliente & sectorLanguage and then apply the
desired relationship
Hope it should work!

Trying to get the property of a non-object in laravel

I have two tables: user and student. The field username from user is a foreign key as login_id in student. I have created eloquent relationships in each model, but when I try to access Auth::user()->student->id it gives me:
Trying to get the property of a non-object.
Student Model:
public function user()
{
return $this->belongsTo('user','login_id');
}
User Model:
public function student(){
return $this->hasOne('student')
}
ProfileController.php
<?php
class ProfileController extends BaseController
{
public function showinfo()
{
if (Auth::check())
{
$user_id = Auth::user()->username;
$student_id = Auth::user()->student->id;
}
}
}
Above noted error occurs when I try to log in.
You should check first if the user who login has student, so i would suggest
$student = Auth::user()->student;
if($student) $student_id = $student->id;
$student_id = Auth::user()->student->id;
If it doesnt contain value, then you get that error. Try using isset, or empty, depends on what you like.
Only with many to many relations you use the ( ).
Example:
$user_companies = Auth::user()->companies();
foreach($user_companies as $company)

Categories