I have the following problem:
I have three tables:
contacts (people)
departments
contact_types (e.g. IT-Contact)
All of them are many-to-many types; One person can be a responsible for 0-n departments as 0-n Contact_types (even for the same department as multiple types). And so on.
In addition i have to have a history all over the project, so each of the tables stores "valid_start" and "valid_end" timestamps as well.
Therefore i now have this relation table:
contact_contact_type_department
id
contact_id
contact_type_id
department_id
valid_start
valid_end
What i ended up doing is creating a Model for the intermediate table:
class DepartmentResponsible extends Model {
protected $table = 'contact_contact_type_department';
protected $fillable = [...];
protected $dates = [
'valid_start',
'valid_end',
];
protected static function boot(){
parent::boot();
static::addGlobalScope(new ValidScope());
}
public function contact() {
return $this->belongsTo('cap\Contact');
}
public function department() {
return $this->belongsTo('cap\Department');
}
public function type() {
return $this->belongsTo('cap\ContactType');
}
}
Contact Model:
class Contact extends CustomModel{
protected $dates = [...];
protected $fillable = [...];
protected static function boot(){
parent::boot();
static::addGlobalScope(new ValidScope());
}
public function departmentResponsibles() {
return $this->hasMany('cap\DepartmentResponsible');
}
}
ContactType Model:
class ContactType extends CustomModel {
protected $dates = [...];
protected $fillable = [...];
protected static function boot() {
parent::boot();
static::addGlobalScope(new ValidScope());
}
public function responsible() {
return $this->hasMany('cap\DepartmentResponsible');
}
}
Department Model:
class Department extends CustomModel {
protected $fillable = [...];
protected $dates = [...];
protected static function boot(){
parent::boot();
static::addGlobalScope(new ValidScope());
}
public function responsibles(){
return $this->hasMany('cap\DepartmentResponsible');
}
//other methods down here, which have no immpact on this issue
}
I can now do things like
Department::first()->responsibles
Regarding the issue with the timestamps on the pivot table i assume i will have to make it a custom pivot table again (already had to do that once, in another case, where i had a "regular" 2-way pivot table)
So my 2 Questions now are:
1. Is this even the right way to do it? I mean the whole thing with the intermediate model and so on. I tried other ways as well, but I couldn't get anything like department->attach(contact) to work since i always need the third id as well...
2. How can i get something like Department::first()->contacts to work? (In a way, where i can access the intermediate "responsibles (=contact_contact_type_department)" table and filter based on the validity dates;eg. with a scope or with wherepivot functions)
well i finally went with the approach that i have an intermediate model called responsible. So for example if i want to print all the contacts and their contact_types for a department then i can do something like this:
$department = Department::first();
<ul>
foreach($department->responsible as $responsible){
<li>{{$responsible->contact->name}} as {{$responsible->type->name}}</li>
}
</ul>
Related
I'm working on a subtitles bot where:
A Movie has multiple subtitles (depending on quality and language)
A Series has multiple seasons with multiple episodes that have multiple subtitles (same as a movie)
These are my tables (Thanks to DaveRandom):
The problem is, as far as I know associative tables are for many-to-many relationships (correct me if I'm wrong), I'm kinda stuck here, especially with Eloquent's belongsToMany method:
class Subtitle extends Model {
public $guarded = [];
public $timestamps = false;
public function SeriesEpisodes()
{
return $this->belongsToMany('SeriesEpisode', null, null, 'series_episodes_subtitle');
}
public function Movie()
{
return $this->belongsToMany('Movie');
}
}
But the problem is, A Subtitle belongsToOne Episode, whereas an Episode might have many subtitles.
I was wondering how one could use associative tables for such structure.
Or should I change the structure?
So what I was trying to achieve is possible with polymorphic relationships,
2 associative tables are removed and instead 2 fields are added to subtitles table:
ex: parent_type, parent_id
then I can use:
subtitles:
class Subtitle extends Model {
public $guarded = [];
public $timestamps = false;
public function Parent()
{
return $this->morphTo();
}
}
series_episodes:
class SeriesEpisode extends Model {
public $timestamps = false;
public $guarded = [];
public function Subtitles()
{
return $this->morphMany('Subtitle', 'Owner');
}
}
movies:
class Movie extends Model {
public $timestamps = false;
public $guarded = [];
public function Subtitles()
{
return $this->morphMany('Subtitle', 'Owner');
}
}
Hope it helps others.
I have a User-Roles model, using Laravel 4 where a user can have many roles, using Eloquent. I can access all roles linked to a user easily using this code :
class User extends Model {
protected $table = 'user';
protected $fillable = array('name');
public function rolesLinked() {
return $this->hasMany('App\UserRoleLink', 'user_id');
}
}
I've been trying to obtain the roles that are not linked to a user, to display on the specific user's page in a select box. Using this function, included in the User class.
public function rolesNotLinked() {
$user = this
$roles = Roles::whereDoesntHave('App\UserRoleLink',function($query) use ($user){
$query->where('user_id',$user->id);
});
}
The problem is, calling this function gives me the following error.
Call to undefined method Illuminate\Database\Query\Builder::App\UserRoleLink()
I've tried using has with < 1 to see if the function was problematic, but after reading this and the online source code, the function call pretty much does what I've tried.
Is something wrong in my function call, or have I messed up configurations somewhere?
For reference, here are my other Model classes:
class UserRoleLink extends Model{
protected $table = 'user_role_link';
protected $fillable = array('role_id','user_id);
public function role() {
return $this->hasOne('App\Role', 'role_id');
}
}
class Role extends Model{
protected $table = 'role';
protected $fillable = array('name');
}
EDIT: I've found out that I messed up by fillables when I copy-pasted. It didn't fix the issue, but I guess that's one step closer.
To use whereDoesntHave method, you must add the relation in your Role Model.
class Role extends Model{
protected $table = 'role';
protected $fillable = array('name');
public function UserRoles() {
return $this->hasMany('App\UserRoleLink', 'id');
}
}
Also, the whereDoesntHave method first parameter is not thte model but the function of the relation:
public function rolesNotLinked() {
$user = this
$roles = Roles::whereDoesntHave('UserRoles',function($query) use ($user){
$query->where('user_id',$user->id);
});
}
I have a very simple Eloquent Model:
class HelpdeskComment extends Model
{
protected $table = 'helpdesk_comment';
protected $guarded = ['id', 'helpdesk_topic_id'];
public function topic () {
return $this->belongsTo ('\\App\\Model\\HelpdeskTopic');
}
public function user () {
return $this->belongsTo ('\\App\\Model\\User');
}
}
This all works quite well when doing stuff like
$user = $helpdeskComment->user;
However, I would like to change the model so that the User table (specifically the "username" field) is always left-joined against the HelpdeskComment table, regardless of the query function called. Is there a simple/central way to achieve this or do I have to override each function (all(), etc.)?
Thanks for any ideas & pointers.
I'm new to laravel. I have 2 table
class Client extends Model
{
protected $fillable = ['name'];
public function clientmoreinfo()
{
return $this->hasMany('App\Moreinfoclient');
}
}
class Moreinfoclient extends Model
{
protected $table = 'clients_additionalfield';
protected $fillable = ['client_id', 'nameinput', 'valueinput'];
public function clients()
{
return $this->belongsTo('App\Client');
}
}
and i need to be able to add many additional fields at once as seen here:
this is how I add any number of entries, and more importantly, how do I update or remove them later?
thank you all in advance !
Hi there i'm trying to sort a collection by attribute of the relation.
This is my model
class Song extends \Eloquent {
protected $fillable = ['title', 'year'];
public function artist(){
return $this->hasOne('Artist','id', 'artist_id');
}
}
class SongDance extends \Eloquent {
protected $table = 'song_dances';
protected $fillable = ['rating'];
public function dance(){
return $this->belongsTo('Dance', 'dance_id');
}
public function song(){
return $this->belongsTo('Song', 'song_id');
}
}
class Dance extends \Eloquent {
protected $fillable = ['name'];
public function song_dances(){
return $this->hasMany('SongDance','dance_id','id');
}
public function songs(){
return $this->belongsToMany('Song', 'song_dances', 'dance_id', 'song_id');
}
}
this is how far i'm by now:
$dance = Dance::find(1);
$songs = $dance->songs()
->with('artist')->whereHas('artist', function ($query) {
$query->where('urlName','LIKE','%robbie%');})
->where('song_dances.rating', '=', $rating)
->orderBy('songs.title','asc')
->where('songs.year', '=', 2012)
->get();
Yeah i just could add a ->sortBy('artist.name'); to the query, but he result-collection can be quite big (about 6000 items) therefore i would prefer a databased sorting.
is there a possibility to do this?
Since Eloquent's relations are all queried separately (not with JOINs), there's no way to achieve what you want in the database layer. The only thing you can do is sort the collection in your app code, which you've already dismissed.
If you feel you must sort it in the database then you should write your own join queries instead of relying on Eloquent's relations.