How Laravel Eloquent references the right table - laravel

I'm currently watching the Laravel Tutorial Episode 7
https://laracasts.com/series/laravel-from-scratch-2017/episodes/7
I created the database and populated its data on the previous episode,
it is only this time, the tutorial introduces model, upon creating the model name "Task" via php artisan make:model Task, it automatically connects to my table "tasks" without any clue how it happened.
So how did a freshly out of the box model knows it?

It's general definition standard.
If you create a table with plural name and create model for this table as singular, then model automatically connects corresponding table, otherwise you should define table name in model like:
protected $table = 'task_table';

It's a convention Laravel follows. Laravel will search for a table that is the snake cased Model's name in plural unless you indicate another table.
If you generate the model with the migration flag (e.g. php artisan make:model Task --migration), it will also create a table with the model's name in plural automatically (in this case, Tasks).
You can check more about it in the documentation.
Table Names
Note that we did not tell Eloquent which table to use for our Flight
model. By convention, the "snake case", plural name of the class will
be used as the table name unless another name is explicitly specified.
So, in this case, Eloquent will assume the Flight model stores records
in the flights table. You may specify a custom table by defining a
table property on your model (...)

Related

Tables names with capitals use _

I just created a model called GrupoInstructor, the table's name is grupoinstructor
When I want to create a query for that model it shows "base table grupo_instructors doesn't exist". Why is that? why laravel adds a _ to the table's name?
Is there a way to tell lavarel that my table's name is grupoinstructor? I just realized that have some errors in my previous migrations so my last one doesn't rollback...
Thanks in advance.
In your model you can override the name of your table to suit your needs
protected $table = 'grupoinstructor';
Laravel and most of the frameworks assume that capital letters are used for separation hence the reason why it expects your table name to be called grupo_instructor which in my mind is more readable way anyway instead of concatenating the words together.

Laravel Dynamic Eager Loading for Dynamic Relationships

Laravel Version: 5.5
PHP Version: 7+
Database Driver & Version: mysql 5.7+
Scenario:
I have a SaaS application that has flexible database structure, so its fields are bound to change, especially given it has a Json field (for any extra database structure to be created from client side of the application), including relationship based fields. so Account Table can have dynamically created employee_id field, and thus the need to access relationships dynamically
Problem:
I need to EagerLoad models based on this dynamic relationship. If I had something like this:
// Account Model
public function employee(){
return $this->belongsTo(App\Employee);
}
it would be easy. But what I have is this:
public function modelBelongsTo(){
return $this->belongsTo($dynamicClassName, $dynamicForeignKey);
}
Now if I eager load this, I'll get Account Model instance with related Employee on key modelBelongsTo. This is how Eloquent Names based on the function of eagerload. But after this I cannot use this function again to eagerload a second model because it'll just overwrite results on modelBelongsTo key.
Possible Solution Directions:
1) Can I Somehow change laravel's process to use a name I provide?
or
2) Can I write functions on the fly to overcome this so I'll write employee function on the fly?
or
3) Worst Case Scenario: I iterate over all records to rename their keys individually because I am using a pagination, it wouldn't that big of a deal to loop over 10 records.
Us a morph relationship
define the various dynamic classnames say
Employee
Boss
Morph works by having the related key and the table name stored in the parent table, it means to relate them you have to use a join or an orm and you cant have foreign key constraint on it as it links to different tables.
then have your account have morphs where
we have
Account
as top class
then we have
EmployeeAccount, BossAccount
which have their relation to boss and employee
then in Account have morphto relation call it specificAccount()
to which in its child morphs have the morph relation to Account
then add it to $with so to eager load them so when fetching account you could simply do
$account ->specificAccount
to get its morph child. which is nullable
This is totally dynamic such that if you have other classes in future you can just add and add the morph relationship. This may be applied to any reflection or runtime evaluated and loaded classes/code though it is not advisable to do this, as you can always edit code to create new functionality without affecting previous.

CFWheels: Model FindAll() appends letter "s" in related table name

checklist = model("user_checklist").findAll(include="tb_machine_checklist");
Above is the query I am using to fetch records from a table called user_checklist and it is related to table called tb_machine_checklist.
Now there is a table called "tb_machine_checklist", however it it gives me an error saying;
The "tb_machine_checklists" table could not be found in the database.
Why is the "s" being added when I didn't specify?
Be sure to read the chapter in the documentation about Conventions.
CFWheels adopts a Rails-style naming conventions for database tables and model files. Think of a database table as a collection of model objects; therefore, it is named with a plural name. Think of a model object as a representation of a single record from the database table; therefore, it is named with a singular word.
Fortunately, CFWheels lets you override most conventions with a little bit of extra code.
In your tb_machine_checklist model's init method, add this line of code:
<cffunction name="init">
<cfset table("tb_machine_checklist")>
</cffunction>
Then any queries that CFWheels writes for you will use your singular table name instead of the conventional plural one.
I guess the include in findAll specifies the model name, not the table Name. Wheels ORM pluralizes in some occasions the model Name and maps it to the table Name. Maybe you could explicitely set the table name for the model in the model?
I solve this matter, My models were not named the same as my database tables. and once that was done properly, this problem went away.

why model name in eloquent are not as same as table name?

When you create model in laravel for eloquent, the User model is treated like a users table. Why is that? Can we use an exact table name for the model?
I think more than anything it's convention. I don't see why you couldn't create a Users model for your users table, but a User is an instance of users, which is why it's done that way. You can always specify the table the model uses with:
protected $table = 'name_of_table';
which can be different than the model name. For example, a Data model can use the table userdata, as long as you specify that.
Hope that helps.

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