I have a laravel model
class Project extends Eloquent {
public static $timestamps = true;
public $includes = array('members','members.memberdata');
public function tasks() {
return $this->has_many('Usertask','project_id');
}
public function members() {
return $this->has_many('Projectmember','project_id');
}
}
and a related models
class Projectmember extends Eloquent {
public static $table = "project_members";
public static $timestamps = true;
public function project() {
return $this->belongs_to('Project');
}
public function memberdata() {
return $this->has_one('Usermetadata','user_id');
}
}
class Usermetadata extends Eloquent {
public static $table = "users_metadata";
public function user() {
return $this->belongs_to('User');
}
public function member() {
return $this->belongs_to('Projectmember','user_id');
}
}
When i attempt to retrieve a single project model like so
$project = Project::find($id);
return Response::eloquent($project);
my json output looks like this
{"id":1,"user_id":1,"name":"UberWork","description":"Web based project management \/ task management app","target_date":"2013-11-15 00:00:00","budget":null,"status":0,"created_at":"2013-04-16 20:13:59","updated_at":"2013-04-16 20:13:59","members":[{"id":1,"project_id":1,"user_id":1,"created_at":"2013-04-16 20:13:59","updated_at":"2013-04-16 20:13:59","memberdata":{"user_id":1,"first_name":"Tamarakuro","last_name":"Foh","photo":"","company_name":null,"phone":null,"package":"free","subscription_start":"0000-00-00 00:00:00","subscription_end":"0000-00-00 00:00:00","api_key":"12b14a7d3ca48c53bb5b1a88fa3eca3b"}},{"id":3,"project_id":1,"user_id":3,"created_at":"2013-04-16 20:13:59","updated_at":"2013-04-16 20:13:59","memberdata":{"user_id":3,"first_name":"Ebere","last_name":"Uche","photo":"","company_name":"Chronotech Labs","phone":null,"package":"free","subscription_start":"0000-00-00 00:00:00","subscription_end":"0000-00-00 00:00:00","api_key":"ab446bd9ffbb898e818a892c7401e0f6"}},{"id":4,"project_id":1,"user_id":2,"created_at":"2013-04-17 08:13:00","updated_at":"2013-04-17 08:13:00","memberdata":null}]}
My database look like this;
Users
id
email
password
ip_address
active
...
users_metadata
id
user_id
first_name
last_name
profile_photo
...
Projects
id
user_id
name
description
status
...
project_members
id
project_id
user_id
My question is why is the last member of the project having its memberdata as "null", while the others are not null. Am i doing something wrong?
Relationships in Eloquent always link a primary key (pk) with a foreign key (fk). However, you're trying to base a relationship on two foreign keys, skipping out a relationship. The only Eloquent solution is to include the extra relationship step. Here are some models (I've ommited the relationships we don't need for this example)...
class Project extends Eloquent {
public static $timestamps = true;
public $includes = array('members','members.user', 'members.user.metadata');
public function members()
{
return $this->has_many('Projectmember','project_id');
}
}
class Projectmember extends Eloquent {
public static $table = "project_members";
public static $timestamps = true;
public function user()
{
return $this->belongs_to('User');
}
}
class User extends Eloquent {
public static $timestamps = true;
public $hidden = array('password', 'ip_address');
public function metadata()
{
return $this->has_one('Usermetadata');
}
}
class Usermetadata extends Eloquent {
public static $table = "users_metadata";
public function user() {
return $this->belongs_to('User');
}
}
I can see why you'd want to skip the relationship, but sadly it's not possible with relationships.
Related
I've read many posts about this issue but none of them works for me. I have a 'ISA' relationship in my database. A person can be either a Patient or a Nurse:
class Person extends Model
{
protected $table = 'persons';
public function commentable()
{
return $this->morphTo();
}
}
class Patient extends Model
{
public function persons()
{
return $this->morphMany('App\Person', 'commentable');
}
}
class Nurse extends Model
{
public function persons()
{
return $this->morphMany('App\Person', 'commentable');
}
}
This is my tables and the data inside them:
And this is my Route:
Route::get('person', function () {
$person = Person::find(1)->commentable();
return json_decode(json_encode($person), true);
});
I get an empty array!
You have to access the relationship as a property:
$person = Person::find(1)->commentable;
I'm making a poll system and I have two tables :
polls table : Has those fields (id,question,created_at,updated_at).
choices table : Has those fields (id,poll_id,choice).
And a pivot table named choice_poll : Has those fields (id,choice_id,poll_id,ip,name,phone, comment ,created_at,updated_at)
Poll Model :
class Poll extends Model
{
protected $table = 'polls';
protected $fillable = ['question'];
public $timestamps = true;
public function choices()
{
return $this->BelongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}
}
Choice Model :
class Choice extends Model
{
protected $table = 'choices';
protected $fillable = ['poll_id','choice'];
public $timestamps = false;
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
}
Now when I try to build this query it doesn't return the choices :
$poll->first()->choices()->get()
PS: There is many choices in the choices table associated with the first poll.
In this case you have Many To Many relationship so try to change belongsTo in :
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
To belongsToMany, and it will be :
public function poll()
{
return $this->belongsToMany('App\Poll')->withPivot('ip','name','phone','comment');
}
NOTE 1: You have to change BelongsToMany to belongsToMany note the B should be in lower case.
NOTE 2: You want the pivot table with timestapms create_at,updated_at as you mentioned in th OP so you have to use withTimestamps(); :
return $this->belongsToMany('App\Poll')
->withPivot('ip','name','phone','comment')
->withTimestamps();
//AND in the other side also
return $this->belongsToMany('App\Choice')
->withPivot('ip','name','phone','comment')
->withTimestamps();
Hope this helps.
This:
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
and
public function choices()
{
return $this->BelongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}
should be:
public function poll()
{
return $this->belongsToMany('App\Poll')->withPivot('ip','name','phone','comment');
}
and
public function choices()
{
return $this->belongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}
Consider the following table structure:
user table
id
name
lang_region_id
lang_region table
id
lang_id
region_id
lang table
id
name
region table
id
name
Fairly new to the Laravel framework, but trying to setup Eloquent models and relationships to an existing database. I want to establish the relationship between my user model and the lang and region models. The lang_region table defines what language and region combinations are available and then we can link each user to a valid combination.
I have read through the Laravel documentation several times looking for the proper relationship type, but is seems that the Many to Many and Has Many Through relationships are close, but since our user.id isn't used in the intermediate table I may be out of luck.
Sorry for the amateur question, but just getting used to Laravel and ORMs in general.
I would use the lang_region table as both a pivot table and a regular table with its own model.
class LangRegion extends model
{
protected $table = 'lang_region';
public function language()
{
return $this->belongsTo(Language::class, 'lang_id');
}
public function region()
{
return $this->belongsTo(Region::class);
}
public function users()
{
return $this->hasMany(User::class);
}
}
class User extends model
{
protected $table = 'user';
public function langRegion()
{
return $this->belongsTo(LangRegion::class);
}
}
class Language extends model
{
protected $table = 'lang';
public function regions()
{
$this->belongsToMany(Region::class, 'lang_region', 'lang_id', 'region_id');
}
public function users()
{
$this->hasManyThrough(User::class, LangRegion::class, 'lang_id', 'lang_region_id');
}
}
class Region extends model
{
protected $table = 'region';
public function languages()
{
$this->belongsToMany(Language::class, 'lang_region', 'region_id', 'lang_id');
}
public function users()
{
$this->hasManyThrough(User::class, LangRegion::class, 'region_id', 'lang_region_id');
}
}
If I understand what you want correctly:
class User extends Model {
private function lang_region() {
return $this->hasOne(LangRegion::class)
}
public function lang() {
return $this->lang_region()->lang();
}
public function region() {
return $this->lang_region()->region();
}
}
class LangRegion extends Model {
public function lang() {
return $this->belongsTo(Lang::class);
}
public function region() {
return $this->belongsTo(Region::class);
}
}
For some reason, I cannot chain model objects. I'm trying to eager load 'Location' for an 'Order' and would prefer the logic to be contained in the models themselves. But past one chain, it does not work.
class Order extends Eloquent {
protected $table = 'orders';
public function customer() {
return $this->belongsTo('Customer');
public function location() {
return $this->customer()->location(); // this does not work
}
}
class Customer extends Eloquent {
protected $table = 'customers';
public function user() {
return $this->belongsTo('User');
}
public function orders() {
return $this->hasMany('Order');
}
public function location() {
return $this->user()->location();
// return $this->user(); // WORKS!!
}
}
class User extends Eloquent {
protected $table = 'users';
public function locations() {
return $this->hasMany('Location');
}
public function location() {
return $this->locations()->first();
}
}
I eventually want to do this:
class ChefController extends BaseController {
public function get_orders() {
$chef = $this->get_user_chef(); // this already works
return $chef->orders()->with('location')->get(); // does not work
}
}
Try to reference relation (user table) by adding user_id as second argument, like this:
public function user() {
return $this->belongsTo('User',"user_id");
}
Maybe you called that id field different, but you know what I mean.
I'm having trouble figuring out how to access a nested relationship within Laravel. The specific example I have is a Movie that has many entires in my Cast table which has one entry in my People table. These are my models:
MOVIE
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
MOVIECAST
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public function person()
{
return $this->hasOne('Person', 'person_id');
}
public function netflix()
{
return $this->belongsTo('Movie', 'movie_id');
}
}
PERSON
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}
In my controller I can access the cast (containing person_id and role_id) like so:
public function movie($id)
{
$movie = Movie::find($id);
$cast = $movie->cast();
return View::make('movie')->with(array(
'movie' => $movie,
'cast' => $cast
));
}
...but I don't know how to access the corresponding name field in my People table.
EDIT 1:
Using the classes exactly as defined below in #msturdy's answer, with the controller method above I try to render the person names like so inside my view:
#foreach($cast->person as $cast_member)
{{$cast_member->person->name}}
#endforeach
Doing this i get the error:
Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$person
I don't know if it makes a difference or not but I have no id field on my People table. person_id is the primary key.
It should be simple, once you have accessed the cast...
Route::get('movies', function()
{
$movie = Movie::find(1);
$cast = $movie->cast;
return View::make('movies')->with(array(
'movie' => $movie,
'cast' => $cast));
});
Note: at this point, $cast is an instance of the Collection class, not a single object of the MovieCast class, as the
relationship is defined with hasMany()
you can iterate over it in the View (in my case /app/views/movies.blade.php
#foreach($cast as $cast_member)
<p>{{ $cast_member->person->name }}</p>
#endforeach
Class definitions used for testing:
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
public $timestamps = false;
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public $timestamps = false;
public function person()
{
return $this->hasOne('Person', 'person_id');
}
}
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public $timestamps = false;
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}