How to define and use a foreign key as primary key in Laravel? - laravel

I have a Users table that can store 8 different types of users. Depending on the user type, I have some other tables with the specific data set for it. So, I would like to use the ID from the Users table as a foreign key and primary key at the same time for those tables. But I am new at Laravel and I don't know how to do that to fit the conventions or, if it is not possible, how to do that when defining my models and one to one relations. Can someone help me? Thanks!
EDIT: Sorry, I think my explanation is not clear enough. Let's say I have 4 tables: users, user_types, customer_organzations, partners, and customers. I would like to use ID, that is PK of users, as a foreign key and primary key for tables customer_organizations, partners and customers, that have different information since they are different type of users in my application but all them login against users table. I don't care user_types table. I think I know how to deal with it.

You haven't given us much in terms of your table structure, so assuming you have a simple one-to-one relationship between a users table and a user_types table, the following would create the required relationship.
In your user_types table migration
$table->foreignId('user_id')->constrained();
The above will add your foreign key to the table and create the relationship back to the users table (this is done 'magically' using conventions so naming is important).
Then in your eloquent models, add the relationships between the models:
User.php
public function type()
{
return $this->hasOne(UserType::class);
}
UserType.php
public function user()
{
return $this->belongsTo(User::class);
}

Related

Accessing a secondary relationship from primary model without intermediate table with foreign keys

I have this structure:
model: OrderItem
belongsTo ProductInfo
model: ProductInfo
hasMany OrderItem
hasMany Barcode
model: Barcode
belongsTo ProductInfo
How can I make an easy accessible relationship in the OrderItem to get the Barcodes that match the same product_info_id? The product_infos table is of course not a classic intermediate table containing the foreign keys.
I know this is probably a very simple question since the relationship is also very basic, but I'm kind of confused with all the answers I find online and in the Laravel docs for slightly different situations. F.e. hasManyThrough is not working out in any way here.
This relationship is correct you can access barcode like
$order->ProductInfo->barcodes
This will return an array of barcodes
Instead of using the pivot model, try this.
OrderItem belongs to many Barcode
Then the Barcode model,
table: barcodes
Barcode belongs to many OrderItem
And last create a pivot table
php artisan make:migration create_barcodes_order_items_table and make two columns for foreign_ids, order_item_id and barcode_id.
It would automatically take care of your relationship unless you didn't do anything outside the pattern.
Then you can get all barcodes of order and all orders for a barcode.
$order->barcodes

Can Laravel hasOne be used with belongsToMany?

Let's say I have two tables:
Users: id, name, country_id
Countries: id, name
Of course each user can only have one country, but each country is assigned to multiple users.
So would it be safe to have a User model that utilizes hasOne and a Country model that uses belongsToMany method?
Documentation makes it seem like you can't mix and match different types of relationships.
What you are describing is actually a One To Many relationship, where one country has many users. Your Country model should utilize a hasMany relationship, while your user would have a belongsTo relationship.
#Andy has already answered well.
Anyway, my advice is to always think in the following way to create a One-To-One, One-To-Many, or a Many-To-Many relationship:
In the table with the foreign key (if any) use belongsTo
In the other table without the foreign key use hasOne or hasMany
In any of them have a foreign key, you have a Many To Many relationship and you must use belongsToMany in both of them (you need the pivot table, of course).

Laravel - Eloquent Models Relations, polymorphic or not?

I have this schema
All the relations here must be one-to-zero/one.
A user can be either an employee or a customer. The user_type ENUM gives me the type so I know where to go from there.
Then an employee can be either basic or a manager. The employee_type discriminator let's me know that.
How am I supposed to build the Eloquent Model relations?
Let's say I have a user that is an employee. I need to get it's common fields from the users table but also need to get common fields from employees table. Do I need to hard code, and know that when user_type=emp I need to select from the employees table? What if I need to add another user type later?
UPDATE
Would it make sense to change my schema into something simpler?
My problem is that by using, as suggested, polymorphic relations I would end up to something like this:
$user = new User::userable()->employable()->...
Would a schema in which I drop the employees table and have employee_managers and employee_basics linked straight to the users table?
this is an polymorphic relationship. but if you want to be easy, you need to fix some things.
in the table employees
- user_id
- employable_id
- employable_type enum(Manager, Basic) # References to the target model
.... this last two are for the polymorphic relation, this is the nomenclature
in the basics and managers table you could delete the user_id field, but you need an id field as increments type
and now in the model Employee you need to make this function
public function employable(){
return $this->morphTo();
}
I hope this works :)

Laravel5: How are Eloquent model relationships expressed in the database?

There's a missing link I fail to understand.
I use migrations to create database tables and I define the relationships there. meaning.. if I have a person table and a job table and I need a one to many relationship between the person and jobs, I'd have the job table contain a "person_id".
When I seed data or add it in my app, I do all the work of adding the records setting the *_id = values etc.
but somehow I feel Laravel has a better way of doing this.
if I define that one to many relationship with the oneToMany Laravel Eloquent suports:
in my Person model.....
public function jobs()
{
return $this->hasMany('Jobs);
}
what's done on the database level? how do I create the migration for such table? Is Laravel automagically doing the "expected" thing here? like looking for a Jobs table, and having a "person_id" there?
Yep, Laravel is doing what you guess in your last paragraph.
From the Laravel documentation for Eloquent Relationships (with the relevant paragraph in bold):
For example, a User model might have one Phone. We can define this
relation in Eloquent:
class User extends Model {
public function phone()
{
return $this->hasOne('App\Phone');
}
}
The first argument passed to the hasOne method is the name of the
related model. Once the relationship is defined, we may retrieve it
using Eloquent's dynamic properties:
$phone = User::find(1)->phone;
The SQL performed by this statement
will be as follows:
select * from users where id = 1
select * from phones where user_id = 1
Take note that Eloquent assumes the foreign key of the relationship based on the model name. In this case, Phone model is assumed to use a user_id foreign key.
Also note that you don't actually have to explicitly set the foreign key indexes in your database (just having those "foreign key" columns with the same data type as the parent key columns is enough for Laravel to accept the relationship), although you should probably have those indexes for the sake of database integrity.
There is indeed support to create foreign key relationships inside migration blueprints and it's very simple too.
Here is a simple example migration where we define a jobs table that has a user_id column that references the id column on users table.
Schema::create('jobs', function($table)
{
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
You can also use some other methods that laravel provides such as onDelete() or onUpdate
Of course to understand better the options that are available to you please read the documentation here.
Edit:
Keep in mind that Eloquent is just using fluent SQL wrapper and behind the scenes there are just raw sql queries, nothing magical is happening, fluent just makes your life a lot easier and helpers you write maintainable code.
Take a look here about the Query Builder and how it works and also, as #Martin Charchar stated , here about Eloquent and relationships.

Dynamically set the table name in a "has many" relation model

In my database schema, I have multiple tables that hold generic data for objects, for instance I have a user table and a user_data, post table and post_data, and so. these *_data tables all hold a foreign key to the object and a pair of key-value. now in my laravel models I would like to have a single data models for these tables (rather than a model for every single one) and represent the has_many relation in a dynamic way where somehow I can define the table name according to the parent model. I think the parent model would have something like:
return $this->hasMany('data');
but I don't know how to express the inverse relation nor how to tell laravel which *_data table to use. so my question is, is it possible? and if so, how?
You have two options.
Either create a model for each data_* table and use the relation as stated with $this->hasMany('data'); and $this->belongsTo('User'); in the data table and the user table.
Or you can use Polymorphic relations, I personally prefer the polymorphic relations solution, more neat.

Resources