How to define eloquent relationship without using model in Laravel? - laravel

Following the official documentation it is very easy to define a relationship between two models. However, One of my models just need to access data from 4 different table in a one to one basis. Those tables will have no functionality. So, I don't want to build a model for them.
For example I can do this,
class User extends Model
{
public function phone()
{
return $this->hasOne('App\Phone');
}
}
Here to complete this relationship successfully I need to have a Phone model. However, if I don't have a model can I use just the table name to define relationship? I want to use something like, return $this->hasOne(DB::table('phones');.
I reckon, if I can somehow use this I will have less models to work with which will make my code more manageable. Is it a good practice?

Related

Eloquent - Multiple belongsTo?

I can't seem to find a straight answer on whether Eloquent models can have multiple belongsTo relationships.
Just in terms of normalized DB relationships, this is perfectly valid. Let's take the hypothetical example of a CMS page that belongs to one and only one author, and also belongs to one and only one category. The author and category have no relation to or bearing on one another. In the DB, we'd simply expect a page to have an author_id and a category_id field, each with a foreign key to a different table.
Seems like it would be valid to do:
class Page extends Model
{
public function author()
{
return $this->belongsTo(Author::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
}
The scenario seems valid ... EXCEPT that this seems to break the convention and automagic of the associate and dissociate methods, which expect there to be only a single "belongs to" relationship.
So is it proper to use multiple belongsTo relationships on the same model? And if not, how would you express a common scenario like this instead? (I should note right off the bat that this is not the same scenario as polymorphic relationships, where one model belongs to one other, which may be this OR that type.)
Eloquent Model's can have multiple same relationship. Means you can have belongsToMany() as many as you need, you can have a belongsTo(), hasOne(), hasMany() etc. It will not affect the other relationship since they have a different method name. which is the main identification for the relationship.
The scenario seems valid ... EXCEPT that this seems to break the convention and automagic of the associate and dissociate methods, which expect there to be only a single "belongs to" relationship.
If you understand the documentation Updating BelongsTo Relationship you will use the associate() or dissociate() after the relationship method. There's no "except there to be only a single belongs to relationship". in the documentation.
$page->author()->dissociate(); // it will set the "author_id" on the page as null and will not affect the `category()` at all.
$page->category()->associate($category); // it will add a the "category_id" of the given category to the page and will not affect the `author()` at all.

Which relation to use in Laravel?

Which relation to use in Laravel to bind two table through third?
When Doctors can be assigned to some Centers. The intermediate table will be as:
doctor_id | center_id
How to create model in Laravel for this case?
You don't need a model for the intermediate table, simply use attach
Example:
$center = Center::create();
$doctor = Doctor::find(1);
$doctor->centers()->attach($doctor->id);
This is a very simple example but should give you the idea, of how to approach it.
All of it of course requires you have set up your Center and Doctor model with the correct many to many relations
Doctor.php model:
public function centers()
{
return $this->belongsToMany(Doctor::class);
}
See the documentation, for more information.
You could obviously create a model called DoctorsCenter and create it manually by doing this, whenever you want to attach a relation.
DoctorsCenter::create(['center_id' => $center->id, 'doctor_id' => $doctor->id]);
I don't see any good reason for doing this, and would not recommend it.
You can use hasMany or belongsTo relationship of Laravel.
See the laravel documentation, for more information

Laravel: Polymorphic types table vs many types tables

I am trying to determine what the best way to many a relationship describing a type would be using Laravel. For example, I might have a user model that can be of many types. Everything I have ever been taught would suggest I need to make a users_types. However, if I wanted to use Eloquent to reference this relationship, I would also need to make a UserType model and an IdentificationType model. For example:
// User Class
public function type() {
return $this->belongsTo('App\UserType');
}
// User Type Class
public function users(){
return $this->hasMany('App\User');
}
$user->type->description; // Could return 'casual'
This seems like it could quickly become ridiculous if I have a bunch of models and each one could potentially have a "type" or maybe a "status".
Would it be better to make a single types table or a single status table and manage everything with a polymorphic relationship, or is that bad database design? Is there a better way to accomplish this using Query Builder instead of Eloquent?
If it makes semantic sense then using a polymorphic relationship is reasonable. The example Laravel sets is with commentable entities. A commentable entity can either be a video or a post (both allow comments).
In your case you'd need to do something like these tables:
typable_type
type_id | typable_id | typable_type
type
id | name
and use:
public function type() {
return $this->morphToMany(Type::class,"type");
}
There's no practical reason why you can't do this anyway, in your case. There is however a semantic reason. Example:
A User can be of type primary , a Product can be of type primary however does that mean the same thing? For example does it make sense to say : "Everything primary can be accessed through this page" in short when you say primary user and primary product, does the word primary carry the same meaning? If the answer is yes then polymorphism is something you should use.

Laravel relations with composite, non-standard foreign keys

I unfortunately need to import data from a third-party vendor and use their non-standard database schema with my laravel project. In addition, I need to store multiple "firms," each with their own set of users in my database.
I'm trying to figure out the best way (if it can be done) to use Eloquent to handle the relationships between these tables. So for instance, with my table structure like this:
BmPerson
'id',
'firmId',
'personId'
BmCoverage
'id',
'firmId',
'personId',
'securityId'
BmSecurity
'id',
'firmId',
'securityId'
... for instance, I need to associate a "BmPerson" with many "BmSecurity" through the "BmCoverage" table.
But I need to somehow use composite keys, because I am storing multiple "firms" in each table (per the 3rd party vendor's database schema).
One approach I've used so far is scoping, e.g.: for my BmCoverage model:
public function scopeFromFirm($query,$firmId){
return $query->where('firmId','=',$firmId);//->where('personId','=',$personId);}
public function scopeFromPerson($query,$personId){
return $query->where('personId','=',$personId);//->where('personId','=',$personId);}
Then I can retrieve the coverage list for an individual person, but I still need to somehow be able to associate the "BmCoverage" with the "BmSecurities." I suppose I could just add a scope the BmSecurities class too, but it would be nicer to just use Eloquent.
Has anyone come up with a good way to use composite keys in laravel model relationships, or should I just stick with the scoping method?
There is a package here that seems to be perfect for your case:
Compoships offers the ability to specify relationships based on two
(or more) columns in Laravel 5's Eloquent. The need to match multiple
columns in the definition of an Eloquent relationship often arises
when working with third party or pre existing schema/database.
You would use it like this:
class BmPerson extends Model
{
use \Awobaz\Compoships\Compoships;
public function bmCoverages()
{
return $this->hasMany('App\BmCoverage', ['firmId', 'personId'], ['firmId', 'personId']);
}
}
If every BmSecurity belongs to exactly one BmCoverage, and every BmCoverage belongs to exactly one BmPerson its probably easier to replace 'firmId', 'personId' with bmperson_id in BmCoverage DB; and 'firmId', 'securityId' with bmcoverage_id in BmSecurity. Then you can use default hasMany relations with one key.
Everything you need for this can be found here https://laravel.com/docs/5.2/eloquent-relationships
You can easily define which cols sohuld be the referenced key.
Example:
public function bmCoverages() {
return $this->hasMany('App\BmCoverage', 'firmId', 'id');
}
This would probably belong to your App\Firm or whatever it is called.
In general the hasMany relations looks like this
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
As you can see you can specify the keys.
As the others have said, you need to use the HasMany and HasManyThrough relationship.
Here from your table definitions, you simply need access to:
Person->BmCoverage(s)
Person->BmSecurity(s) of an individual.
What I think is the major problem here is linking the BmSecurity with BmCoverage as apparently there's no coverage_id per BmSecurity but rather, a composite mapping through firmId and securityId.
In this case, Laravel does not officially support composite keys unfortunately, although you could use a trait like this... but you could also achieve the same with some tricky hasMany.
i.e. on BmCoverage
$this->hasMany('BmSecurity', 'securityId', 'securityId')
->andWhere('firmId', '=', $this->firmId);
Same applies for BmSecurity from BmPerson using HasManyThrough.
Hope that helps.
read laravel hasManyThrough relationship . it will help you to write this query more easily
https://laravel.com/docs/5.1/eloquent-relationships#has-many-through

Codeigniter Model

I have a question about Jamie Rumbelow's MY_Model and models generally. MY_Model provides a protected variable that holds the name of the table. I want to use it but I want my model to handle 3 tables. So I guess my question is can a model handle more than one table? is it good practice to do this or is it better to have a model per database table?
By default, MY_Model doesn't support multiple tables, however, you can very easily create methods - I like to call them scopes - to link to other tables in an efficient and elegant manner.
Let's say we have a post_model.php that needs to pull in data from the categories table. I'll assume that we want to bring in our category.name based on the post.category_id.
class Post_model extends MY_Model
{
public function with_category()
{
$this->db->join('categories', 'categories.id = post.category_id', 'left');
$this->db->select('categories.name AS category_name');
return $this;
}
}
We can then use our with_category() method (chained alongside all our built-in MY_Model methods) to pull out our category info:
$this->post_model->with_category()
->get_all();
Or with get_by():
$this->post_model->with_category()
->get_by('status', 'open');
Scoping is a cool way of introducing other tables into your models, while still getting to use all the cool stuff MY_Model provides.
If you wish to use Jamie Rumbelow's MY_Model untouched, you have to use only one table for each model, as it gets the table name from the model name. As he introduced it, this is a base CRUD model, you can extend it to fit your situation.
I think the best practice is to use one table per model (not including the join tables if there are any). Although I sometimes skip this in CodeIgniter if some stuff can be added to the same model logically and are not too big to need their own model. For example there is a comment model and you need votes only for the comments. I do this out of laziness - I hate the manual model loading in CI.

Resources