Laravel, property not found - laravel

Trying to get property from a object in laravel. I have this:
public function index()
{
$firmen = Companies::all();
$allcountcompanies = Companies::count();
$agent = Agent::find($firmen->agent_firma_id);
return view('companies',compact(['firmen'],['allcountcompanies'],['agent']));
}
The Exeption gives me that:
Property [agent_firma_id] does not exist on this collection instance.
But when i put the id eg 1001 it shows corrent entry in db field.
What i0'm doing wrong?
Info:
CompaniesController.php (table: br_firma)
AgentController.php (table: br_firma_agents)
Table "br_firma_agents" contains a foreign_key from table "br_firma".

You are getting id from collection.
$firmens = Companies::all();
it return collection you may be use it useing loop and get one by one data as
for($firmens as $firmen){
$agent = Agent::find($firmen->agent_firma_id);
}
Or you create relation between Company and agent as,
In company model define relation as
public function agents(){
return $this->hasMany(Agent::class);
}
and in agent model define relation as
public function company(){
return $this->belongsTo(Companies::class);
}
and then call it as in controller,
$data = Companies::with('agents')->get();

You are trying to access an agent_firma_id from a collection of companies, you could first use a loop on that collection,or use an index on that collection,
you could try
$firmens = Companies::all();
foreach($firmens as $firmen){
$agent = Agent::find($firmen->agent_firma_id);
}

Related

Laravel returns a Collection with duplicates of the first model

I'm developing a Laravel 5.7 (API) application with a PostgreSQL database behind it. The relevant Models are: User (customers and employees), Car, and Request.
An employee User creates a Request for a Car, that belongs to a customer User.
The relationships are:
Car (as customer) : User = n:m
Car : Request = 1:n
User : Request (as employee) = 1:n
(The data design is suboptimal, to put it mildly, but anyway, it's the given reality for now.)
Now to the actual issue. I want to display all Requests of a customer User:
Request::query()
->join('user_car', 'user_car.car_id', '=', 'request.car_id')
->join('user', 'user.id', '=', 'user_car.user_id')
->where('user.id', '=', $customer->id)
->select()
->get();
The customer with the given $customer->id has n Requests. And the length of the result Collection of the call above is correct. But all these n entries are duplicates of the first one. Means: I'm getting a list with n instances of Request#1.
Why does the first call return a list of references to the same Model object? Is it a (known) bug?
ADDITIONAL INFORMATION
Relationships:
class User extends \Illuminate\Foundation\Auth\User
{
// ...
public function cars()
{
return $this->belongsToMany('App\Car', 'user_car')->withTimestamps();
}
public function requests()
{
return $this->hasMany(Request::class, 'user_id');
}
}
class Car extends Model
{
// ...
public function users()
{
return $this->belongsToMany('App\User', 'user_car')->withTimestamps();
}
public function requests()
{
return $this->hasMany(Request::class);
}
}
class Request extends Model
{
// ...
public function car()
{
return $this->belongsTo(Car::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
The query is correct.
I logged the database requests, got the generated statement
SELECT *
FROM "request"
INNER JOIN "user_car" ON "user_car"."car_id" = "request"."car_id"
INNER JOIN "user" ON "user"."id" = "user_car"."user_id"
WHERE "user"."id" = 1;
..., and executed it manually. The result table contains as expected n different entries.
NOT just references
The result Collection's entries instances references to the different objects:
$test1 = $resultCollection->first();
$test2 = $resultCollection->last();
$test3 = spl_object_hash($test1);
$test4 = spl_object_hash($test2);
Xdebug output:
$test3 = "0000000077505ccd000000007964e0a8" <-- ccd0
$test4 = "0000000077505c33000000007964e0a8" <-- c330
Workaround
I found a workaround. This call
Request::whereIn('car_id', $customer->cars()->pluck('id')->toArray())->get();
... retrieves the correct/expected set of model.
First, note that your object hashes are not actually identical, and you're likely dealing with two separate instances.
What you're likely experiencing is an issue with ambiguous column names. When you JOIN together multiple tables, any matching/duplicate column names will contain the value of the last matching column. Your SQL GUI/client usually separates these. Unfortunately Laravel doesn't have a prefixing mechanism, and just uses an associative array.
Assuming all of your tables have a primary key column of id, every Request object in your result set will likely have the same ID - the User's ID you pass in the WHERE condition.
You can fix this in your existing query by explicitly selecting the columns you need to prevent ambiguity. Use ->select(['request.*']) to limit the returned info to the Request object data.

Get all badges with user progress if any

I have a many to many relationship between users and achievements. Table layout is similar to this.
users
-id
-first_name
-last_name
-email
acheivements
-id
-type-name
-description
achievement_user
-id
-acievement_id
-user_id
-is_complete (boolean)
-percentage_complete (integer)
-completed_at
I can get the bulk of the stuff I want such as all achievements with type = badge for a user that are in the pivot table. I can also get a list of all the achievements that have type = badge. Where I am stuck is trying to get all achievements with type = badge along with is_complete, percentage_complete, completed_at for that given user. So if there are 8 total badges and they have started 3 of them I would want to return 8 records where 3 of them would have the information from the pivot table. I know I could grab all badges and loop through them to add on additional information but I know there is a eloquent way that would be easier.
Thank for any help.
This is in response to you recent comment.
To achieve what you want, I have introduced a new method on the User model called achievementsblock, which uses php array_map method.
I have not tested the code, but you should get the idea.
//in User model
public function achievements()
{
return $this->belongsToMany('App\Achievements')->withPivot('is_complete', 'percentage_complete', 'completed_at');
}
//in User model
public function achievementsblock()
{
$all_achievements = Achievement::all();
return array_map(function($temp_achievement){
$achievement_ids = $this->achievements()->pluck('id');
$new_temp = new \stdClass();
$new_temp->type_name = $temp_achievement->type_name;
$new_temp->description = $temp_achievement->description;
if(in_array($temp_achievement->id, $achievement_ids)){
$user_achievement = $this->achievements()->where("achievements.id","=",$temp_achievement->id)->first();
$new_temp->is_complete = $user_achievement->is_complete;
$new_temp->percentage_complete = $user_achievement->percentage_complete;
$new_temp->completed_at = $user_achievement->completed_at;
}
else {
$new_temp->is_complete = 0;
$new_temp->percentage_complete = 0;
$new_temp->completed_at = null;
}
return $new_temp;
}, $all_achievements);
}
In your controllers, you can get the achievementsblock for a user as follows:
$user_achievement_blocks = User::first()->achievementsblock();
On your belongsToMany relationship, use the withPivot function as follows:
//in User model
public function acheivements()
{
return $this->belongsToMany('App\Acheivement')->withPivot('is_complete', 'percentage_complete', 'completed_at');
}
//in Acheivement model
public function users()
{
return $this->belongsToMany('App\User')->withPivot('is_complete', 'percentage_complete', 'completed_at');
}
You need to learn about whereHas method which lets you query on relationship while getting results
In User model
// create achievements relationship
public function achievements()
{
return $this->belongsToMany(Achievement::class)
->withPivot('is_complete', 'percentage_complete', 'completed_at');
}
//then query it like shown below.
$achievements= $user->achievements;
Read more here

Laravel Eloquent Nested Relationships. Storing rows in controller variable

I have some working queries that are not ideal and I'd like to try perform them the Eloquent way to tidy it up.
I think I've got the relationships defined correctly but I can't figure out how to write the queries and store them in variables in the controller. I need to return these variables back to the view because I json encode them for use in JavaScript.
Here's what I have in my controller:
public function show($idProject)
{
$project = ProjectsModel::with('user')->where('idProjects','=',$idProject)->first();
$objsettings = ObjSettingsModel::where('idObjSettings','=',$project['ObjSettingsID1'])->first();
$obj = ObjModel::where('idObjs','=',$objsettings['Objs_idObjs'])->first();
return view('project')->with('project',$project)->with('obj',$obj)->with('objsettings',$objsettings);
}
The naming conventions are a bit off so here's what this does.
I pass the $idProject to the controller from a link on my index page where I've looped through and paginated all rows from the Projects table.
The first query finds the project row where it's id (idProjects) matches the variable passed from the index page via the link (idProject). I've also successfully pulled the related user row from the user table using an eloquent relationship.
The next query pulls from an ObjSettings table which stores a number of settings values for an object which is shown on the page. I match the idObjSettings column of the ObjSettings table to the previously pulled $project['ObjSettingsID1'] which is essentially the foreign key in the projects table. There can be several ObjSettings for each Project.
The 3rd query pulls from the Obj table which stores details about an object. These are static details on objects such as name or size for example. I match the idObjs column to the previously pulled $objsettings['Objs_idObjs'] which is the foreign key in the ObjSettings table. One Obj can have many ObjSettings which are used in other Projects.
Here's how I'm passing the php variables to JS:
<script>var obj = #json($obj);</script>
<script>var objsettings = #json($objsettings);</script>
Here are my relationships
ProjectsModel
public function user()
{
return $this->belongsTo('App\User', 'Username', 'id');
}
public function objsettings()
{
return $this->hasMany('App\ObjSettingsModel', 'idObjSettings', 'ObjSettingsID1' );
}
ObjSettingsModel
public function objs()
{
return $this->belongsTo('App\ObjsModel', 'Objs_idObjs', 'idObjs');
}
public function projects()
{
return $this->belongsTo('App\ProjectsModel', 'ObjSettingsID1', 'idObjSettings' );
}
ObjModel
public function objsettings()
{
return $this->hasMany('App\ObjSettingsModel', 'idObjs', 'Objs_idObjs');
}
I've tried a whole range of queries such as:
$project = ProjectsModel::with('user')->with('objsettings.objs')->where('idProjects','=',$idProject)->first();
$objsettings = $project->objsettings;
$obj = $project->objsettings->objs;
but I keep running into issues such as "Property [objs] does not exist on this collection instance." I suppose I'm returning multiple rows in this case? Any help would be appreciated.
You need to loop through objsettings
$project = ProjectsModel::with('user')->with('objsettings.objs')->where('idProjects','=',$idProject)->first();
$objsettings = $project->objsettings;
foreach($objsettings as $objsetting){
$objs = $objsetting->objs;
}

How to implement this relationship in laravel?

i have 4 table
inst
id
subject
report
id
subject
object
id
type
container
id
obj_id
i want with obj_id of container table, achieve the The corresponding object record.
then if type of object = 1, fetch data from inst table or type = 2, fetch data from report table
based on your information,
you can do like #Mahfuz Shishir answer
or
create new appends attribute inside Object Model
protected $appends = ['data'];
public function getDataAttribute()
{
if($this->attributes['type'] == 1) {
return Inst::where('inst_column', $this->attributes['object_column_to_match']); //this just sample
} else {
return Report::where('inst_column', $this->attributes['object_column_to_match']); //this just sample
}
}
The relation looks like.
In your Object.php Model
public function containers()
{
return $this->hasMany('App\Container', 'foreign_id');
}
And in your Container.php Model
public function object()
{
return $this->belongsTo('App\Object', 'foreign_id');
}
You provide little information. Implement rest of the controller code in your own sense. Or put some code that you have tried.

Many to many relationship returns empty set

I have a following table structure in my existing database :
tbl_Grzyby (ID, Nazwa, ...) - main table,
tblk_TypGrzyba (ID, TypGrzyba, OrderNo) - lookup table,
tblm_TypGrzyba (ID_Grzyb, ID_TypGrzyba) (many-to-many table).
I've created a grzyby Eloquent model class, which has a custom property, defined as:
class grzyby extends Model
{
protected $table = 'tbl_Grzyby';
public function typ_grzyba() {
return $this->belongsToMany('\App\Lookups\typ_grzyba', 'tblm_TypGrzyba','ID_Grzyb', 'ID_TypGrzyba');
}
}
I've also created the lookup table model, defined as:
class typ_grzyba extends Model {
protected $table = 'tblk_TypGrzyba';
public function grzyby() {
return $this->belongsToMany('\App\grzyby', 'tblm_TypGrzyba','ID_Grzyb', 'ID_TypGrzyba');
}
}
When I try with tinker to get record from main with ID=67, like:
$main_record=\App\grzyby::where('ID',67)->first();
it returns me all the details for that record fine. Returning all lookups runs also fine:
$types = \App\Lookups\typ_grzyba::all();
However, if I try to do the following:
$main_record_types = $main_record->typ_grzyba;
tinker returns me an empty collection, despite record existing in the many to many table:
When I run the query log it outputs me following SQL query:
select `tblk_TypGrzyba`.*, `tblm_TypGrzyba`.`ID_Grzyb` as `pivot_ID_Grzyb`, `tblm_TypGrzyba`.`ID_TypGrzyba` as `pivot_ID_TypGrzyba` from `tblk_TypGrzyba` inner join `tblm_TypGrzyba` on `tblk_TypGrzyba`.`id` = `tblm_TypGrzyba`.`ID_TypGrzyba` where `tblm_TypGrzyba`.`ID_Grzyb` is null
If I run that query against the database it returns me empty result, however, if I change the where clause manually to
where `tblm_TypGrzyba`.`ID_Grzyb` = 67
I'm getting the expected results in phpMyAdmin.
What's the reason of it and how I can fix that?
The solution was to add the primaryKey overrride because I was using uppercase for the ID field and then restart tinker.
You mixed up your foreign key defintion in your relationships. You wrote this twice:
return $this->belongsToMany('\App\grzyby', 'tblm_TypGrzyba','ID_Grzyb', 'ID_TypGrzyba');
I assume copy pasting? in the second model, justt swap the foreign key. Foreign key of the current model comes first.
In typ_grzyba model, do
public function grzyby() {
return $this->belongsToMany('\App\grzyby', 'tblm_TypGrzyba', 'ID_TypGrzyba', 'ID_Grzyb');
}

Resources