I have a question about models structure.
I created a model called User.php
Than I would like after get a record from DB initialize another class which extends User class based on the value from DB. I.e. there is a record from DB users
id = 1
name = John
type = 1
If type = 1 I would like to init some other class, i.g. Admin
And folders structure will be
Models
- User.php
- UserTypes
- Admin.php
How it's possible to realize this?
Thanks
You can achieve that by using for polymorphic relation. Let's say a user can be extended by two models "Admin" and "Marketer", they will look something like that:
class Admin extends Model
{
public function user() {
return $this->morphOne('App\User', 'extendable');
}
}
And the User model:
class User extends Model
{
public function extendable() {
return $this->morphTo();
}
}
Of course you will also need to add two columns to your User model extendable_id and extendable_type to hold the relation.
To read more you can check laravel documentation https://laravel.com/docs/5.5/eloquent-relationships#polymorphic-relations
Related
I have default user model. Now I have another table for Administrators. Is there a way to return user fields (since admin is extending user) from admin model ? I found this example but its when admin_id is present in user model. I have one-to-one relation here.
class Admin extends User
{
protected $table = 'users';
public static function boot()
{
parent::boot();
static::addGlobalScope(function ($query) {
$query->where('is_admin', true);
});
}
}
This is the example I found. I'm not sure how can I return user fields from my admin model when its on different table.
The point is I want to be able to do something like this (call methods from users):
Admin::first()->posts()
Where posts method is not on Admin class but on user class.
Edit:
To explain it better. I have two tables, users and admins. They are connected in one-to-one relationship so I can do something like this:
$admin = Admin::first();
$posts = $admin->user()->posts();
but since Admin should have all fields from users table and one more field from admins table I'm looking for a way to do this:
$admin = Admin::first();
$posts = $admin->posts();
I don't want to add admin or something to users table, I still want to use admins table since I will need more fields there later.
If both tables have an equal id, use a trait to define your relationships:
trait UserRelationships {
public function posts() {
return $this->hasMany(Post::class, 'user_id');
}
}
class Admin {
use UserRelationships;
}
class User {
use UserRelationships;
}
You'll just have to be sure to explicitly declare the foreign key name in the relationship.
You could also extend the User model and override the $table property but this may present problems for various reasons since User properties exist on the user relationship and not on the Admin model.
I'm playing with laravel for the first time and i'm a little confused on how to achieve a link table relationship. I have 3 tables: Tank, TankContent and Content
I have the following models:
Tank:
class Tank extends Model
{
public function getTankContent()
{
return $this->hasMany('App\TankContent', 'tankID', 'tankID');
}
}
TankContent:
class TankContent extends Model
{
public function getTank()
{
return $this->belongsTo('App\Tank', 'tankID', 'tankID');
}
public function getContent()
{
return $this->belongsTo('App\Content', 'contentID', 'contentID');
}
}
Content:
class Content extends Model
{
public function getContentTanks()
{
return $this->hasMany('App\ContentTank', 'contentID', 'contentID');
}
}
Now im trying to call say tankID 2 and get all the content details inside of that
$content = Tank::find(2);
$items = $content->getTankContent;
This will list me the content. But then how do i go about linking the results to getContent() from the TankContent model?
Thanks in advance. Hopefully I just need it explaining and then it will all click.
p.s i have tried reading the https://laravel.com/docs/5.5/eloquent-relationships#many-to-many and im still stumped!
TankContent isn't required, the belongsToMany relationship methods belong on the Tank and Content models.
https://laravel.com/docs/5.5/eloquent-relationships#many-to-many
From here you can see there is no RoleUser model, the models are only Role and User. The belongsToMany relationship on those models defines that the intermediate, or pivot, table is role_user.
You can additionally define other fields on that relationship with withPivot() chained onto the belongsToMany method. (read "Retrieving Intermediate Table Columns"). Therefore, there is likely no reason to have a separate model for the intermediate/pivot table.
Can any body tell me what is the main difference between
the BelongsTo and HasOne relationship in eloquent.
The main difference is which side of the relation holds relationship's foreign key. The model that calls $this->belongsTo() is the owned model in one-to-one and many-to-one relationships and holds the key of the owning model.
Example one-to-one relationship:
class User extends Model {
public function car() {
// user has at maximum one car,
// so $user->car will return a single model
return $this->hasOne('Car');
}
}
class Car extends Model {
public function owner() {
// cars table has owner_id field that stores id of related user model
return $this->belongsTo('User');
}
}
Example one-to-many relationship:
class User extends Model {
public function phoneNumbers() {
// user can have multiple phone numbers,
// so $user->phoneNumbers will return a collection of models
return $this->hasMany('PhoneNumber');
}
}
class PhoneNumber extends Model {
public function owner() {
// phone_numbers table has owner_id field that stores id of related user model
return $this->belongsTo('User');
}
}
BelongsTo is a inverse of HasOne.
We can define the inverse of a hasOne relationship using the belongsTo method.
Take simple example with User and Phone models.
I'm giving hasOne relation from User to Phone.
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
Using this relation, I'm able to get Phone model data using User model.
But it is not possible with Inverse process using HasOne. Like Access User model using Phone model.
If I want to access User model using Phone, then it is necessary to add BelongsTo in Phone model.
class Phone extends Model
{
/**
* Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
You can refer this link for more detail.
One-to-one relationship: You, as a User, can have one (hasOne) Profile. And of course the inverse also applies. Profile (belongsTo) a User. A user can't have more than one profile and a profile can't belong to multiple users.
If you want to make One TO one relationship between two table then first you have to make "hasOne" Relation and If you want to make inversely table relationship then you make " "Belongs to"... IT is a simple difference between HasOne and Belongs to the relationship if you want to know about this
One To Many (Inverse)
Now that we can access all of a post's comments, let's define a relationship to allow a comment to access its parent post. To define the inverse of a hasMany relationship, define a relationship function on the child model which calls the belongsTo method:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
Here you can see a good example and see what the difference is between BelongsTo and HasOne relationship in eloquent.
Eloquent Relationships Cheat Sheet by Mahmoud Zalt https://link.medium.com/9lj9BAG8lR
Is there any way I can get Yii to work with models that have a prefix or postfix in their class name?
For example, I have a table user, which corresponds to the model User. Now, I want this model to have a prefix, say, EmulatedUser. Is there any way to achieve that without renaming my table?
The table and class name don't have to be the same. You can override the tableName in your model:
<?php
class EmulatedUser extends CActiveRecord {
public function tableName() {
return 'user';
}
}
I have already checked this official example http://laravel.com/docs/eloquent#many-to-many-polymorphic-relations
but I still confused because I may have a different case.
I have a DetailsAttribute model which deals with details_attribute table.
I have a Action model witch deals with action table.
The relationship between them is many to many.
So I created a new table details_attribute_action with model DetailsAttributeAction
My DetailsAttribute model should have:
public function actions(){}
My Actions model should have:
public function detailsAttributes(){}
and my DetailsAttributeAction model should have functions but I don't know what they are.
My question is what is the code inside the previous functions please? and should really the DetailsAttributeAction have functions of not?
What you're looking for is a Many-to-Many relation, not one that is polymorphic.
http://laravel.com/docs/eloquent#many-to-many
Your code should look something like this:
class DetailsAttribute extends Eloquent {
// ...
public function actions()
{
// Replace action_id and details_attribute_id with the proper
// column names in the details_attribute_action table
return $this->belongsToMany('Action', 'details_attribute_action', 'details_attribute_id', 'action_id');
}
}
class Action extends Eloquent {
// ...
public function detailsAttributes()
{
return $this->belongsToMany('DetailsAttribute', 'details_attribute_action', 'action_id', 'details_attribute_id');
}
}
You won't have to worry about how to create the DetailsAttributeAction model in Laravel. It's simply a table to map the Many-to-Many relationships you've created.