Laravel get wrong table while querying - laravel

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

Related

Laravel Eloquent Many to Many Relationship pivot table

I have three tables categories, film_categories and films and three models respectively Category, FilmCategory and Film.
I have seen many tutorials where they don't create a pivot table model like i have created FilmCategory Model . They just create a pivot table film_categories without a model.
My question is what is the best practise - ?
Should i create a FilmCategory model and set a hasMany relationship
class Film extends Model
{
use HasFactory;
protected $primaryKey = 'film_id';
/**
* Film film Relationship
*
* #return Illuminate\Database\Eloquent\Relations\HasMany
*/
public function categories()
{
return $this->hasMany(FilmCategory::class, 'film_id', 'film_id');
}
}
OR
Should i just create a pivot table film_categories without a model FilmCategory and set belongsToMany relationship
class Film extends Model
{
use HasFactory;
protected $primaryKey = 'film_id';
/**
* Film film Relationship
*
* #return Illuminate\Database\Eloquent\Relations\HasMany
*/
public function categoriesWithPivot()
{
return $this->belongsToMany(Category::class, 'film_categories', 'film_id', 'category_id');
}
}
Technically speaking, both option are fine. You can implement the two of them, and depends on what you want to implement/achieve in the logic part of the code, use one between the two that suits best. Here are things to consider:
First, depends on what is film_categories table used for. If the table is simply exists to relate films and categories tables using many-to-many relationship, then there's no need to create the FilmCategory model, and you can just use belongsToMany(). Otherwise, if the film_categories will relates to another table, then you should create FilmCategory model and define the relation using hasMany(). You're also likely need to add a primary-key field to film_categories if this is the case.
The second consideration to take is what kind of data structure you want to have. Using the codes that you provide, you can get Films using these 2 queries and it'll gives you the correct values but with different structures:
Film::with('categoriesWithPivot')->get();
// Each record will have `Film`, `Category`, and its pivot of `film_categories` table
// OR
// Assuming that `FilmCategory` model has `belongsTo` relation to `Category` ...
Film::with('categories', 'categories.category')->get();
// Will gives you the same content-values as the above, but with in a different structure
And that's it. The first point is mostly more important to consider than the second. But the choice is completely yours. I hope this helps.
Since the film_categories table does not represent an entity in your system, I think you should define a belongsToMany relationship and should not create a separate model for the pivot table. If You still wanna have a model for your pivot table so create a model that extends Illuminate\Database\Eloquent\Relations\Pivot class. Check documentation here: model for pivot table

Laravel - How to query a relationship on a pivot table

My Setup
I have a many-to-many relationship setup and working with my database. This is using a pivot table that has an extra column named "linked_by". The idea of this is that I can track the user that created the link between the other 2 tables.
Below is an attempted visual representation:
permissions -> permissions_roles -> roles
permissions_roles -> persons
The Issue
The permissions_roles table has an addition column names "linked_by" and I can use the ->pivot method to get the value of this column. The issue is that it only returns the exact column value. I have defined a foreign key constraint for this linked to persons.id but I can't manage to work out a way to query this from a laravel Eloquent model.
The Question
How do I query the name of the person linked to the "linked_by" column form the Eloquent query?
Ideally, I would like the query to be something like:
permissions::find(1)->roles->first()->pivot->linked_by->name;
BUT, as I haven't defined an eloquent relationship for this pivot table column I can't do this but I can't work out how I would do this if it is even possible?
Is the only way to do this to do:
$linkee = permissions::find(1)->roles->first()->pivot->linked_by;
$person = person::find($linkee);
$person->name;
->using();
I have discovered that Laravel has a way to do what I wanted out of the box by creating a model for the pivot table.
This works by adding ->using() to the return $this->belongsToMany() model function.
By putting the name of the newly created pivot model inside the ->using() method, we can then call any of the functions inside this pivot model just like any other eloquent call.
So assuming that my permissions belongs to many roles and the pivot table has a 3rd column named "linked_by" (which is a foreign key of a user in the Users table):
My permissions model would have:
public function roles()
{
return $this->belongsToMany('App\roles','permissions_roles','permissions_id','roles_id')
->using('App\link')
->withPivot('linked_by');
}
and the new link model would contain:
Notice the extends pivot and NOT model
use Illuminate\Database\Eloquent\Relations\Pivot;
class link extends Pivot
{
//
protected $table = 'permissions_roles';
public function linkedBy()
{
return $this->belongsTo('App\users', 'linked_by');
}
}
Obviously you would need to define the opposite side of the belongsToMany relationship in the roles model, but once this is done I can use the following to pull the name of the person that is linked to the first role in the linked_by column:
permissions::find(1)->roles->first()->pivot->linked_by->name;
You should be able to achieve that in toArray method in Permission model.
/**
* Convert the model instance to an array.
*
* #return array
*/
public function toArray(): array
{
$attributes = $this->attributesToArray();
$attributes = array_merge($attributes, $this->relationsToArray());
// Detect if there is a pivot value and return that as the default value
if (isset($attributes['pivot']['linked_by']) && is_int($attributes['pivot']['linked_by'])) {
$linkeeId = $attributes['pivot']['linked_by'];
$attributes['pivot']['linkee'] = Person::find($linkeeId)->toArray();
//unset($attributes['pivot']['linked_by']);
}
return $attributes;
}

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';
}

How does eloquent recognize tables?

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.

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