Laravel belongsTo & hasMany relation not working - php

I have a table called champ_sales which contains champions that belong to table champions. I've set up my models properly, and I'm trying to query in the exact same way the documentation here: http://laravel.com/docs/eloquent#querying-relations states, but it's not working.
class ChampSales extends Eloquent {
protected $table = 'champ_sales';
public function champ(){
return $this->belongsTo('Champion');
}
}
class Champion extends Eloquent {
protected $table = 'champions';
public function skins(){
return $this->hasMany('Skin');
}
//relevent relation here:
public function championOnSale(){
return $this->hasMany('ChampSales');
}
public function skinOnSale(){
return $this->hasMany('SkinSales');
}
}
My query: Find start_date in table champions for id=2
$champsales = ChampSales::find(2);
echo $champsales->champ->start_date;
Running this gives me a vague error that says "Trying to get property of non-object". I'm not really sure what I've done wrong, followed the documentation to the dot.

I just fixed it. I defined the local key and foreign key in champ(). I thought the laravel naming convention would pick that up fine, but I guess not.
class ChampSales extends Eloquent {
protected $table = 'champ_sales';
public function champ(){
return $this->belongsTo('Champion', 'champion_id', 'id');
}
}

Related

Laravel 5 – get particular many to many relation based on model and related model ID

I've got Tag and Attendee Eloquent models, they are in many-to-many relation. Pivot table has also two more attributes – value_int and value_string. My Attendee model looks like this:
class Attendee extends Model
{
public $timestamps = false;
protected $fillable = [
'event_id'
];
public function tags() {
return $this->belongsToMany('App\Models\Tag', 'attendee_tag', 'attendee_id', 'tag_id')
->withPivot(['value_string', 'value_int']);
}
public function scoreTagValue($tag_id) {
return $this->tags->where('tag_id', '=', $tag_id)->first();
}
}
What I want is to obtain pivot values based on Attendee model and variable tag_id, so I've written scoreTagValue function, but it always returns null and I don't know why :( I'm calling it this way:
$attendee->scoreTagValue($tag_id). Thanks for your help :)
You need to access the relation, not the property:
public function scoreTagValue($tag_id) {
return $this->tags()->where('tag_id', '=', $tag_id)->first();
}
Also, according to the docs, withPivot() does not take an array, so:
->withPivot('value_string', 'value_int');

use relationship in model accessor in laravel

Suppose I have a Course model like this :
class Course extends Model
{
public $primaryKey = 'course_id';
protected $appends = ['teacher_name'];
public function getTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
}
public function teacher ()
{
return $this->belongsTo('App\User', 'teacher', 'user_id');
}
}
And in the other hand there is a User model like this :
class User extends Authenticatable
{
public $primaryKey = 'user_id';
protected $appends = ['full_name'];
public function getFullNameAttribute ()
{
return $this->name . ' ' . $this->family;
}
public function course ()
{
return $this->hasMany('App\Course', 'teacher', 'user_id');
}
}
As you can see there is a hasMany relationship between those.
There is an full_name accessor in User model.
Now I want to add a teacher_name accessor to Course model that uses it's teacher relations and gets full_name of teacher and appends to Course always.
In fact I want whenever call a Course model, it's related teacher name included like other properties.
But every time , when call a Course model , I got this error :
exception 'ErrorException' with message 'Trying to get property of non-object' in D:\wamp\www\lms-api\app\Course.php:166
That refers to this line of Course model :
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
I do not know how can I solve that and what is problem exactly.
Yikes some interesting answers here.
FYI to those coming after me- getFooAttribute() should return the data, and not modify the internal attributes array.
If you set a new value in the attributes array (that doesnt exist in this model's db schema) and then attempt to save the model, you'll hit a query exception.
It's worth reading up the laravel docs on attribute accessors/mutators for more info.
Furthermore, if you need to access a related object from within the model (like in an accessor) you ought to call $related = $this->getRelation('foo'); - note that if the relation isnt loaded (e.g., if you didnt fetch this object/collection with eager loaded relations) then $this->getRelation() could return null, but crucially if it is loaded, it won't run the same query(ies) to fetch the data again. So couple that with if (!$this->relationLoaded('foo')) { $this->loadRelation('foo'); }. You can then interact with the related object/collection as normal.
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
Should be
$this->attributes['teacher_name'] = $this->teacher->full_name;
First thing is that you want to reference the relationship, so loose the brackets (), and because the relationship is belongsTo, you will have one user / teacher returned. So you don't need the first().
We haven't seen your fields but probably you will have to change:
return $this->belongsTo('App\User', 'teacher', 'user_id');
to
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
where foreign_key and other_key are the primary keys that you need to make the join on.
Check this link from the documentation for reference:
https://laravel.com/docs/5.4/eloquent-relationships#one-to-many-inverse
the right way to do this is:
COURSE
public function setTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher->full_name;
}
100% working for me.
I have one to one relationship between Order and Shipment. I have to add the accessor of shipments table column from orders table.
function getOrderNoAttribute()
{
$appendText = "OR100";
if($this->orderShipment()->first()) {
$appendText = $this->orderShipment()->first()->is_shipping === 1 ? "ORE100" : "OR100";
}
return $appendText . $this->attributes['id'];
}
This error is only object data to array use or array data to object data use.
example::
$var->feild insted of $var[feild]
$var[feild] insted of $var->feild
You should use return for accessors . something like this :
public function getTeacherNameAttribute ()
{
return $this->teacher()->first()->full_name ?? '';
}
maybe a course hasn't teacher.

hasMany returns null

I'm on laravel 4.2, trying to get an objects associative relation yet for some reason I am getting null.
Models:
class Keg extends Eloquent {
protected $fillable = ['beer_distribution_id', 'status', 'keg_size'];
public function beer_distribution()
{
return $this->belongsTo('BeerDistribution');
}
}
class BeerDistribution extends Eloquent {
protected $fillable = ['beer_id', 'distributor_id'];
public function kegs()
{
return $this->hasMany('Keg');
}
}
My Query:
$distirbution = Keg::find($tap->keg_id)->beer_distribution
This query returns null: I know the keg object is found and I know that the object has the beer_distribution_id.
I tried specifying the foreign key in the model like so:
class Keg extends Eloquent {
protected $fillable = ['beer_distribution_id', 'status', 'keg_size'];
public function beer_distribution()
{
return $this->belongsTo('BeerDistribution', 'beer_distribution_id');
}
}
I thought that might be necessary since the Model is camel case.
I know this is super simple, and I am in fact querying many relations succesfully through out my application, but for some reason this one is not working. Any thoughts on what I might be missing?
The problem is the function name of the relationship. Laravel expects it to be in camel case: beerDistribution().
Change that and you should be good. (You don't have to specify the foreign key, Laravel will convert camelCase to snake_case)

Laravel Eloquent Joins

I have below query in core php:
SELECT DISTINCT device_tocken FROM push_details JOIN users ON users.id=push_details.user_id
I have to integrate it in laravel 4
Application already have User extends Eloquent class
I created Push_details class as below
class Push_details extends Eloquent {
public $table = 'push_details';
public function User() {
return $this->hasMany('\User','id');
}
}
Table : users
Primary key : id
Table: push_details
Primary key: id
Foreign key: user_id belongsTo('users.id');
But i m not able to get expected result.
One more thing i didn't write anything in User's model yet.
Only way to join table is.. to join it, as Eloquent relations don't work using joins but separate queries with WHERE IN clauses. So this will do:
DB::table('push_details')
->select('device_tocken')
->distinct()
->join('users','users.id','=','push_details.user_id')
->get();
Above will return array of stdObject's so or if you need Eloquent Collection with Eloquent models as a result replace DB::table('push_details')->select... with PushDetails::select...
Now, correct your relations, as they are wrong:
// PushDetails model (as previously stated, I suggest renaming it to StudlyCase)
public function user() {
return $this->belongsTo('\User','user_id'); // user_id is may be omitted here
}
// User model
public function pushDetails() {
return $this->hasMany('\PushDetails','user_id'); // user_id is may be omitted here as well
}
In your User model, you need to link back to the PushDetails model, like so
class User extends Eloquent {
public function push_details() {
return $this->belongsTo('PushDetails');
}
}
Use CamelCase for Class names, because laravel has several functions, in which CamelCase are changed to snake_case
Change
public function User() {
return $this->hasMany('\User','id');
}
to
public function users() {
return $this->hasMany('User');
}
See the docs 'Eloquent ORM' for more...

Laravel Eloquent ORM relationship naming conventions

When defining an inverse relation in Eloquent, do you have to name your dynamic property the same as your related model?
class Book extends Eloquent {
public function author()
{
return $this->belongsTo('Author');
}
}
$books = Book::all()
foreach ($books as $book) {
echo $book->author->firstname;
}
In the above example, do I have to call this method author or can I name it something else? I tried to name it to something else (just out of curiosity) but it then returns null hence the errors "Trying to get property of non-object".
EDIT: I got it to work by passing the foreign key to belongsTo, like this:
class Book extends Eloquent {
public function daauthor()
{
return $this->belongsTo('Author', 'author_id');
}
}
$book = Book::find(55);
dd($book->daauthor);
Can someone explain why?
The method belongsTo tries to determine the attribute which links to the Author model. To accomplish this Laravel uses the function name of the caller.
So in your code Laravel sees the daauthor function and tries to use the attribute daauthor_id in the books table to fully your request. As your books table does not have this attribute it fails.
By setting the $foreignKey on the method you can override the default behaviour:
public function daauthor()
{
return $this->belongsTo('Author', 'author_id');
}
For more details check out the source code of \Illuminate\Database\Eloquent\Model.

Categories