Laravel8 Many To Many change id for custom attribute - laravel

I created a relationship many-to-many between Faculties and Departments(im Working in a prototype timetable problem). For a petition, these tables need a validation code vcode. The problems are in the relationship of this, I don't know why the relationship recognize only the id´s tables for the eloquent query and not the vcode.
attached my migrations and model relationship.
Migration Faculties Table
public function up()
{
Schema::create('faculties', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('vcode')->index()->unique();
$table->string('code');
$table->string('name');
$table->string('website');
$table->string('email');
$table->string('phone');
$table->timestamps();
});
}
Relationshop on Faculty Model
public function departments()
{
return $this->belongsToMany(Department::class, 'faculty_departments','faculty_vcode','department_vcode');
}
Migration Departments Table
public function up()
{
Schema::create('departments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('vcode')->index()->unique();
$table->string('code');
$table->string('name');
$table->string('phone');
$table->string('email');
$table->string('website');
$table->timestamps();
});
}
Relationshop on Department Model
public function faculties()
{
return $this->belongsToMany(Faculty::class, 'faculty_departments', 'department_vcode','faculty_vcode',);
}
Migration FacultyDepartments (Relationship)
public function up()
{
Schema::create('faculty_departments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('faculty_vcode')->nullable()->index();
$table->foreign('faculty_vcode')
->references('vcode')
->on('faculties')
->cascadeOnUpdate()
->nullOnDelete();
$table->unsignedBigInteger('department_vcode')->nullable()->index();
$table->foreign('department_vcode')
->references('vcode')
->on('departments')
->cascadeOnUpdate()
->nullOnDelete();
$table->timestamps();
});
}
I provocate a error for get the query and tested the error (getting id´s table).
faculty::with('departments')->get() gives me:
select `departments`.*, `faculty_departments`.`faculty_vcode` as `pivot_faculty_vcode`, `faculty_departments`.`department_vcode` as `pivot_department_vcode`
from `departments`
inner join `faculty_departments` on `departments`.`id` = `faculty_departments`.`department_vcode`
where `faculty_departments`.`faculty_vcode` in (1, 2, 3, 4, 5, 6, 7)

Since you're not providing the field names for the faculties table or the departments table Laravel will assume it's the primary key (id) for those tables.
You need to update your belongsToMany method to be:
public function departments()
{
return $this->belongsToMany(
Department::class, // The related model
'faculty_departments', // The intermediate (pivot) table name
'faculty_vcode', // The pivot field relating to faculties
'department_vcode', // The pivot field relating to departments
'vcode', // The field on the faculties table
'vcode', // The field on the departments table
);
}

Related

Laravel 8 - Foreign key constraint is incorrectly formed

I don't know what's wrong because I'm very new to this.
// Product Model
class Product extends Model
{
use HasFactory;
public function store()
{
return $this->belongsTo(Store::class);
}
}
// Store Model
class Store extends Model
{
use HasFactory;
public function products()
{
return $this->hasMany(Product::class);
}
}
// Products table migration
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->float('price');
$table->string('description');
$table->timestamps();
$table->foreignId('store_id')->constrained()->onDelete('cascade');
});
// Stores table migration
Schema::create('stores', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('image_url');
$table->string('phone');
$table->timestamps();
});
When I run the migration, it gives me this error
I've tried changing the data type of the 'id' but still not working. I've also tried with
$table->foreign('store_id')->references('id')->on('stores')->onDelete('cascade');
but still not working.
What I want is a relation so that when I delete a store, all products that belong the store are also deleted.
Thanks 🙏
Change the name of the stores migration file to a date prior to 2021-07-28 so the table stores is migrated before the table products
Example: 2021_07_27_004700_create_stores_table
Laravel uses the name of the migration files for the order of migration. With the format of the date as the start of the file name, it is dependant on the date of the creation of the file.

Laravel ManyToMany relationship Is reversing tables names

i need to make the post accepts as many language as i need so i have tow models post and language
in post model:
public function languages(){
return $this->belongsToMany(\App\Models\Language::class);
}
in my language model :
public function posts()
{
return $this->belongsToMany(\App\Models\Post::class);
}
post migration :
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->boolean('puplished')->default(false);
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
language migration :
Schema::create('languages', function (Blueprint $table) {
$table->id();
$table->string('text')->unique();
$table->string('value');
$table->timestamps();
});
i also created post_language_table migration to connect post and language:
Schema::create('post_language', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('post_id');
$table->unsignedInteger('language_id');
$table->timestamps();
});
in my controller :
$langs = collect(json_decode($request->languages,true))->pluck('id');
$post = [];
$post['body'] = $request->body;
$post['title'] = $request->title;
$post['user_id'] = 1;
$new_post = \App\Models\Post::create($post);
$new_post->languages()->attach($langs);
but when i try to insert new record to tha database this error shows:
Illuminate\Database\QueryException
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'laravel.language_post' doesn't exist (SQL:
insert into `language_post` (`language_id`, `post_id`) values (1, 4), (3, 4), (4, 4))
so the problem is that for some reason the table name is exchanged !
The Laravel convention for pivot tables based on models is table1_table2, where table1 is the lowercase, singular version of the model that comes first in the alphabet, and table2 is the lowercase, singular version of the model that comes last in the alphabet. So in your case, the pivot table should be language_post, since L comes before P.
You can modify the pivot table in your migration:
Schema::create('language_post', ...)
Or override it on the relationship:
Post.php:
public function languages() {
return $this->belongsToMany(Language::class, 'post_language');
}
Language.php
public function posts() {
return $this->belongsToMany(Post::class, 'post_language');
}
The 2nd param passed to belongsToMany is the name of the pivot table.
From the documentation:
To determine the table name of the relationship's intermediate table, Eloquent will join the two related model names in alphabetical order.
https://laravel.com/docs/8.x/eloquent-relationships#many-to-many

Laravel Polymorphic HasOne ,two different categories model to the same item

I'm trying to use two different Category model to the same items table.
I'v got 3 models
SystemCategory
Schema::create('system_categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
UserCategory
Schema::create('user_categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->integer('user_id');
$table->timestamps();
});
Item
Schema::create('items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->integer('categoryable_id');
$table->string('categoryable_type');
$table->timestamps();
});
Item category could be either from system_categories or user_categories table
I saw some Polymorphic relations but its about how two different models can belongs to one category, not about how model can belongs to two different category models
Thanks.
It can be done, first thing your schema looks ok but you want to set catagoryable_id to a bigInteger to match the id columns of the 2 category tables.
Then you would set your models up
class Item extends Model
{
public function categoryable()
{
return $this->morphTo();
}
}
class SystemCategory extends Model
{
public function items()
{
return $this->morphMany('App\Item', 'categoryable');
}
}
class UserCategory extends Model
{
public function items()
{
return $this->morphMany('App\Item', 'categoryable');
}
}
Obviously this is presuming your models are in the App namespace

Get data from 2 tables connected using a pivot table (Laravel 5.3)

How to get data from 2 tables connected using a pivot table ? for example, in my case I have users table connected to journal table using a pivot table (penulis table). Now I want to get journals data that belonged to specific user. I tried this :
$journal_list = DB::table('journal')->where('id_user', '=','id_journal')->orderBy('id', 'desc')->paginate(20);
That code above doesn't work. Below are my migrations :
Users table :
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('username')->unique();
$table->string('userslug');
$table->string('nameslug');
$table->string('email')->unique();
$table->string('phone')->nullable();
$table->string('address')->nullable();
$table->string('password');
$table->rememberToken();
$table->enum('level', ['admin', 'author']);
$table->timestamps();
});
}
Journal table :
public function up() {
Schema::create('journal', function (Blueprint $table) {
$table->increments('id');
$table->string('title', 255);
$table->text('abstract');
$table->text('file');
$table->integer('id_edition')->unsigned();
$table->string('journalslug');
$table->timestamps();
});
}
Penulis table (the pivot table)
public function up()
{
Schema::create('penulis', function (Blueprint $table) {
// Create tabel penulis
$table->integer('id_user')->unsigned()->index();
$table->integer('id_journal')->unsigned()->index();
$table->timestamps();
// Set PK
$table->primary(['id_user', 'id_journal']);
// Set FK penulis --- user
$table->foreign('id_user')
->references('id')
->on('users')
->onDelete('cascade')
->onUpdate('cascade');
// Set FK penulis --- journal
$table->foreign('id_journal')
->references('id')
->on('journal')
->onDelete('cascade')
->onUpdate('cascade');
});
}
View composer :
public function boot()
{
View::composer('user/show', function ($view) {
$journal_list = User::where('id', $user_id)->with('journal')->first();
$view->with('journal_list', $journal_list);
});
}
If you want to use Eloquent, you should setup belongsToMany() relation first:
class User extends Authenticatable
{
public function journals()
{
return $this->belongsToMany('App\Journal');
}
Then use eager loading to load the data:
User::where('id', $userId)->with('journals')->first();
If you don't want to use Eloquent and just need journals:
$journal_ids = DB::table('penulis')->where('id_user', $userId)->get(['id_journal'])->toArray();
$journal_list = DB::table('journal')->whereIn('id', $journal_ids)->paginate(20);
Or do the same by using join().
Why not make use of the Eloquent if you are using Laravel
First define the relations in your models
class User extends Model {
public function journal(){
return $this->belongsToMany('App\Journal', 'penulis', 'id_user', 'id_journal');
}
}
class Journal extends Model {
public function user(){
return $this->belongsToMany('App\User', 'penulis', 'id_journal', 'id_user');
}
}
Of course you need to define the table and fillables in your model with table name and table columns respectively.
And to get the specific data related to users you can use eloquent,
User::with('journal')->paginate(20);
This will load 20 users(paginated) with related journal data.
To know further about the eloquent relationships, take a look at this link.
Hope it solves your problem.

Laravel Eloquent Composite Primary Key Relationships

I have the following schema:
Schema::create('companies', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->timestamps();
});
Schema::create('departments', function (Blueprint $table) {
$table->increments('id');
$table->integer('company_id');
$table->string('name');
$table->timestamps();
$table->foreign('company_id')->references('id')->on('companies');
$table->unique(['company_id','name']);
});
Schema::create('employees', function (Blueprint $table) {
$table->increments('id');
$table->integer('company_id');
$table->string('name');
$table->timestamps();
$table->foreign('company_id')->references('id')->on('companies');
});
Schema::create('managed_departments', function (Blueprint $table) {
$table->integer('company_id');
$table->integer('department_id');
$table->integer('manager_id');
$table->timestamps();
$table->primary(['company_id','department_id']);
// Overlapping foreign keys guarantee that the manager
// and the department belong to the same company.
$table->foreign(['company_id','department_id'])
->references(['company_id','department_id'])
->on('departments');
$table->foreign(['company_id','manager_id'])
->references(['company_id','id'])
->on('employees');
});
Schema::create('department_staff', function (Blueprint $table) {
$table->integer('company_id');
$table->integer('department_id');
$table->integer('employee_id');
$table->timestamps();
$table->primary(['company_id','department_id', 'employee_id']);
// Overlapping foreign keys guarantees that the employee and the
// managed department belong to the same company.
$table->foreign(['company_id','department_id'])
->references(['company_id','department_id'])
->on('managed_departments');
$table->foreign(['company_id','employee_id'])
->references(['company_id','id'])
->on('employees');
});
Whats the correct model relationship between the departments, managed_departments and the department_staff tables in the
above schema - i'm a bit confused with how to define the relationship when there are composite primary keys and the following doesn't look right to me and how will eloquent know the correct foreign keys?
class Department extends Model
{
// a department is managed by an employee
public function managedDepartment
{
$this->hasOne(app\ManagedDepartment)
}
}
class ManagedDepartment extends Model
{
// a managed department belongs to department
public function Department
{
$this->belongsTo(app\Department)
}
// a managed department is managed by an employee
public function Employee
{
$this->belongsTo(app\Employee)
}
}
class DepartmentStaff extends Model
{
public function employee()
{
return $this->belongsTo('App\Employee');
}
}
class Employee extends Model
{
// an employee can managed many depts
public function managedDepartment
{
$this->hasMany(app\ManagedDepartment)
}
// an employee is asigned to one department
public function departmentStaff()
{
return $this->hasOne('App\DepartmentStaff');
}
}

Resources