How does eloquent recognize tables? - laravel

I am curious about how eloquent knows in which table it should save the records we give it by running $ php artisan tinker . I do not actually remember setting so an option.

In Laravel when using Eloquent you should assign a table name using the property $table for example:
protected $table = 'some_thing';
Otherwise it assumes that the table name is the plural form of the model name and in this case for User model the table name should be users. Follwing paragraph is taken from Laravel website:
Table Names
Note that we did not tell Eloquent which table to use for our Flight
model. 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 use this instead:
class Flight extends Model
{
// Explicit table name example
protected $table = 'my_flights';
}
So, if you don't follw this convention when creating/naming your database tables that Laravel expects then you have to tell Laravel the name of the table for a model using a protected $table property in your model.
Read the documentation here.

Actually if you not set the $table property, Eloquent will automatically look the snake case and plural name of the class name. For example if class name is User, it will users.
Here the code taken from Illuminate/Database/Eloquent/Model.php
public function getTable()
{
if (isset($this->table)) {
return $this->table;
}
return str_replace('\\', '', Str::snake(Str::plural(class_basename($this))));
}

Model name is mapped to the plural of table name, like User model maps to users table and so.
When you do
User::all() laravel knows that you want the records from users table.
To specify the table name explicitly you use protected $table ='name' field on model.

Actually, Eloquent in its default way, is an Active Record System just like Ruby On Rails has. Here Eloquent is extended by a model. Those model name can be anything starts with capital letter. Like for example User or Stock
but the funny thing is this active record system will imagine that if no other name of custom table is specified within the class model then the table name should be the small cased plural form of the Model name. In these cases users and stocks.
But by keeping aside theses names you can extensively can provide your own table name within the model. As in Laravel protected $table= 'customTableName'
Or, in a more descriptive way,
class Stock extends Eloquent{
// Custom Table Name
protected $table = 'custom_tables';
}
I hope this will solve your curious mind.

Related

Laravel find record in another table associated with $data

I am looking over some laravel code and I have a few questions regarding the code. In the view, I see a piece of code "$data->profile->age". Does this code automatically find the profile record in the profile table associated with the $data? How does it find the associated profile?
Controller:
return view('new-design.pages.influencer.info')
->withData($data)
View:
$data->profile->age
Yes. It finds the associated profile using the relations you definied in your Profile model
Once the relationship is defined, we may retrieve the related record using Eloquent's dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model:
Here's a simple example from the documentation to help you understand:
Let's say you have a posts table and a comments table:
We need to define a relationship between this two tables.
A one-to-many relationship is used to define relationships where a single model owns any amount of other models. For example, a blog post may have an infinite number of comments.
Note: you must have a foreign key in your comments table referencing the posts table, like post_id, in this case, if you use a different name you should inform that in your relation:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
In your Post model you could do:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
}
And in your Comment model you should define the inverse relationship
<?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');
}
}
Now, if you want to access all comments from a post you just need to get the relation:
$post = Post::find($id); // find a post
$post->comments; // This will return all comments that belong to the given post
So, you basically access them as if they were a property from the model, as said in the documentation
In your view you could do something like this:
#foreach($post->comments as $comment)
{
{{$comment->text}}
}
#endforeach
This example will print every comment text from the Post we get in the controller.
I reckon in your model for $data there is a function called profile. From that it is getting the equivalent profile.
Example: Imagine you have a model called phone and you want to find the user who owns it. You can write the following function in your model.
public function user()
{
return $this->belongsTo('App\User');
}
And in the view you may write something like
$phone->user->name
Now, behind the scene laravel will go to the phone and get the value from user_id for that phone. (If the foreign key is located in different column you can specify that too). Then laravel will find the users table with that user_id and retrieve the row. Then show the name on view.
Now if there is a complex query you can also write a function for that in the model.

Laravel 5.4 : get parent object from the child object using Model Inheritance

I am using Laravel 5.4.
The issue I am facing is regarding model inheritance.
Following is the code snippet of the 2 classes:
class Company extends Model{
protected $table = 'companies';
}
class Vendor extends Company{
protected $table = 'companies';
}
NOTE : Here the Company is the parent class and Vendor is the child class. Also, both the models refer to the same table.
I am having an object of the Vendor class (i.e. child class).
For example:
$vendor = Vendor::find(1);
How can I get the Company object from the existing Vendor object?
As both refer to the same record in the database.
You can solve your problem by specifying field/column names in your relationship method. You can specify the exact keys when you declare the relationship method so Laravel will not use it's convention for mapping the model/table, for example, you can use the following syntax in your Company model for it's many-to-many relationship method:
class Company extends Model
{
public function someMethod()
{
return $this->belongsToMany(
'App\OtherModel', // name of the other model
'pivot_table_name', // name of the pivot table
'company_id' // this model foreign key
'other_model_foreign_key' // other model foreign key
);
}
}
In thus case, the foreign keys should match with the field/column names used in your pivot table. Now you can call your relationship method (someMethod) from instance of Vendor objects and it'll work just fine because compoany_id is specified so Laravel will use that column name instead of vendor_id. Check more about many-to-many relationship.

Laravel 5.5 eloquent creation table

any of you know how to create tables in laravel through Eloquent without adding the final s to the name of these?
For instance after the creation with this commands:
php artisan make:model Article -crmf
php artisan migrate
The table in database will be named as Articles. If I try to change the name in the respective file as Article i receive error during the execution of query,like:
SQLSTATE[42S02]: Base table or view not found:
How can I create table without the adding of final S ?
thanks
As per the docs:
Table Names
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 Article model stores records in the articles table. You may specify a custom table by defining a table property on your model:
class Article extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'article';
}

Laravel get wrong table while querying

I try to insert some data to the new table that I have create but laravel choose wrong reverse table. Instead of job_contract get contract_job.
QueryException in Connection.php line 636:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'job.contract_job' doesn't exist (SQL: insert into contract_job (contract_id, job_id) values (2, 4))
I am new in laravel. Is anyone know the way that laravel defines the names of tables
I am not sure about what the Model name of your related php file is.
Usually, the table would be like
if your model name isUser the table name should be users !
For tables like customer_details , the model name should be CustomerDetail
But you can also select a particular table with the model using
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'my_flights';
}
In this example, you can see that the table name by default should be flights but you can change it to whatever you want like this !
A way to fix this is to tell the Model wich table to use (Put in your model):
protected $table = 'job_contract';
This way you force the Model to use that table and not some other table
See more here
A quote about the relation table:
The role_user table is derived from the alphabetical order of the related model names, and contains the user_id and role_id columns.
In your case it would be contract_job with contract_id and job_id.
And another quote:
However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method:
return $this->belongsToMany('App\Role', 'user_roles');
So I guess you only need to pass the correct table name as second param to your belongsToMany method(s) like this:
//in your Contract model
return $this->belongsToMany('App\Job', 'job_contract');
and
//in your Job model
return $this->belongsToMany('App\Contract', 'job_contract');
Quotes from Laravel docs

How does laravel relate an actual table to the eloquent class?

How does laravel relate an actual table to the eloquent class ?
From what i understood is that the class name should be same as the table name but without the s
example
Articles table the Eloquent class name is Article.
But what if the table name is Article or if there are 2 tables say Articles and article.
How does laravel assign the Eloquent class to the table ?
If none is provided Laravel guesses the table name by lowercasing and pluralizing the model name. If you want to provide a specific table name, here is what you should do:
class Article extends Eloquent {
protected $table = 'your_own_table_name';
...
}

Resources