How to create pivot table in Laravel 4? - laravel-4

I have a database table teacher_attendances, with field:
id, name, data, attendance.
I try to generate a pivot table based on teacher_attendances table.
I want rowname as TeacherName and columnname as Date and cloumnname below mark attendance.
How to create pivot table in Laravel 4?

Have you checked out Laravel Migration and Schema Builder Documentation?
Run php artisan migrate:make create_teacher_attendances_table --create --table=teacher_attendances in the CLI to generate the file.
Then edit the file to include something like this up method
public function up()
{
Schema::create('teacher_attendances', function(Blueprint $table)
{
$table->increments('id');
// Your code here
});
}
Don't forget about foreign-keys.

You need to execute following command:
php artisan make:migration create_attendance_teacher --table="attendance_teacher"
Note : create_attendance_teacher is taken singular form for the tables attendances & teachers respectively.
As per convention try to create pivot table alphabetical order. Hence we took attendance table before teachers table.
Then, in migration script:
public function up()
{
Schema::create('teacher_attendances', function(Blueprint $table)
{
$table->increments('id');
$table->integer('attendance_id');//Foreign key from attendances table
$table->increments('teacher_id');////Foreign key from teachers table
});
}

Related

General error: 1824 Failed to open the referenced table

I am trying to set foreign key of my 'books' table with 'categories' table using php artisan migrate, but I got the following error:
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'categories' (SQL: alter table `books` add constraint `books_category_id_foreign` foreign key (`category_id`) references `categories` (`id`))
books migration file:
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories');
$table->string("image");
$table->string("title");
$table->string("description")->nullable();
$table->string("author");
$table->string("cover");
$table->integer("nod")->nullable();// Number of downloads
$table->integer("rating")->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('books');
}
categories migration file:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string("title");
$table->string("image");
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('categories');
}
I really need help with this to use in my mobile app API. I hope someone can help me.
The problem is on the migration itself. Have a look carefully at this
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'categories' (SQL: alter table `books` add constraint `books_category_id_foreign` foreign key (`category_id`) references `categories` (`id`))
You are trying to open the categories table but it basically wasn't there or wasn't created yet. If you use GUI like HeidiSQL or Navicat, or PMA, You will be able to see it.
Laravel migration takes the timestamp on the beginning of the file to decide which migration should be migrated first in sequence.
Make sure you create the categories table first before the books table (this also applies for any tables that has reference). Or simply just rename the file (change the timestamp) like E.g:
2020_01_01_1234_create_books_table.php
2020_01_01_5678_create_categories_table.php
to this
2020_01_01_1234_create_categories_table.php
2020_01_01_5678_create_books_table.php
Then run php artisan migrate:fresh to refresh your migration.
I faced the same issue with you since yesterday and I later saw my mistakes, I was able to understand the cause of the problem.
There are so many factors to consider
Make sure the date for the parent table (categories) is earlier than the date for the child table (books) so that during the migration, the parent table will be created first because the child table might want to reference id in a table that does not exist.
Make sure to follow the convention for naming
you can refactor your migration file like this
$table->foreignId('category_id')->constrained('categories');
or
$table->foreignId('category_id')->constrained();
example of one of my migration files
public function up()
{
Schema::create('project_details', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
$table->id();
$table->foreignId('project_id')->constrained()->onDelete('cascade');
$table->string('name', 150)->nullable();
$table->string('description', 600)->nullable();
$table->string('location', 150)->nullable();
$table->integer('completed_percent')->nullable()->default(0);
$table->foreignId('manager_id')->constrained('staffs');
$table->foreignId('sponsor_id')->constrained('sponsors')->nullable();
$table->foreignId('donor_id')->constrained('sponsors')->nullable();
$table->foreignId('mda_id')->constrained('sponsors')->nullable();
});
}
You try get category for book before you create category table and book table cant understand what you referenced for.
Solution #1
Declare your category table before book table, just rename date in migration file name. Category table must be created before book table.
Solution #2
Create reference after you create category table.
Remove
$table->foreign('category_id')->references('id')->on('categories');
from book migration and create references after you up category table.
categories migration file:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string("title");
$table->string("image");
$table->timestamps();
});
Schema::table('books', function (Blueprint $table) {
$table->foreign('category_id')->references('id')->on('categories');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('categories');
}
Main idea is make all relations when all tables created.
Also, use php artisan migrate:fresh for fast wipe and recreate tables
I had the same error just right now.
It has something related to creating those migrations.
The problem I had because I refactored the table name manually and didn't take care of the connection between the tables and instantly tried to migrate them.
The solution I did and worked for me is I deleted the migrations manually and created them again using php make:magirate.
In my opinion you need to change the engine of the SQL to InnoDB, this issue was struggling with me for a lot of time all you need to do is adding
<?php
$table->engine = 'InnoDB';
?>
to the table migration file
reference :
https://web-brackets.com/discussion/4/-solved-sqlstate-hy000-general-error-1824-failed-to-open-the-referenced-table-alter-on-foreign-key-
The table (Categories) you are referencing its "id" is either not created or its created after the "books" table. You can manually delete both tables and create them again with "Categories" been first or you can manually change the date of the "Categories" to a date before the "books" and you are good to go.
Make sure you have such a table in your database. If you use a lot of database, then you need to specify the database for constrained
$connection_db = DB::connection('connection_name')->getDatabaseName();
$table->foreign('category_id')->references('id')->on("$connection_db.categories");
Make sure both the tables are created using the same engine. In my case, I created two tables with two different engines (MyISAM and InnoDB). Changing both the table engines to InnoDB did the trick.

Laravel Artisan - How to add and populate a new column into a table with existing records?

I wanted to add a new unique column called uuid into an existing table. This is my migration function.
public function up()
{
Schema::table('suppliers', function (Blueprint $table) {
$table->uuid('uuid')->index()->after('id');
});
}
However, the table already has existing records, ie 100+ records. How do I create a function to populate this new column with unique values for the existing records? Thanks.
you have to specify the type of the column so change $table->uuid to $table->string. so try following.
Schema::table('suppliers', function (Blueprint $table) {
$table->integer('uuid')->unique()->after('id');
});

Laravel Migration to change table name

I want to change my two table name in the Laravel, so do I have to manually change the table name or it can be possible through migration.
from the docs laravel.com/docs/5.1/migrations#renaming-and-dropping-tables
To change a table name, you can do this:
Schema::rename($currentTableName, $newTableName);
You can use the drop or dropIfExists methods to remove an existing table:
Schema::drop('users');
Schema::dropIfExists('users');
Just add that to a migration and it should work.
You can rename table like that
Schema::rename('old_table', 'new_table');
BUT be careful if you have foreign keys, indexes and unique-s.
you will not be able to deleted them after renaming, like thiat
Schema::table('new_table', function (Blueprint $table) {
$table->dropForeign(['transaction_id']);
});
because they will have old names and these names have table name in them.
Thus, I recommend deleting foreign keys and other stuff first
Schema::table('old_table', function (Blueprint $table) {
$table->dropForeign(['transaction_id']);
});
Schema::rename('old_table', 'new_table');
Schema::table('new_table', function (Blueprint $table) {
$table->foreign('transaction_id')->references('id')->on('transactions');
});
Firstly, use CLI command to create a migration:
php artisan make:migration rename_table
Now, in the up method of the new migration class, use the rename method to change table name:
Schema::rename('old_table_name', 'new_table_name');
Next, execute the migration command:
php artisan migrate
To rename an existing database table, use the rename method:
Schema::rename($from, $to);
To drop an existing table, you may use the drop or dropIfExists methods:
Schema::drop('users');
Schema::dropIfExists('users');
Firstly, run this in your terminal to create a migration file to rename a table:
php artisan make:migration rename_old_name_to_new_name_table
Then in the up method, you should have this:
public function up()
{
Schema::rename('old_table_name', 'new_table_name');
}
Then in the down method, you should have this in case you want to revert previous changes made:
public function down()
{
Schema::rename('new_table_name', 'old_table_name');
}

Laravel: how to run migration to add a field to a pivot table and insert a value if the pivot exists

I have two pivot tables that contains bookings for attendees and programs. Each record contains the attendee_id and program_id of a booking.
If there is a record entry i.e. booking that means that the attendee is registered.
I want to migrate my table so that there is a field registered and waitlisted. Like so.
public function up()
{
//
Schema::table('bookings', function(Blueprint $table)
{
$table->increments('id');
$table->boolean('registered');
$table->boolean('waitlisted');
});
Schema::table('prog_bookings', function(Blueprint $table)
{
$table->increments('id');
$table->boolean('registered');
$table->boolean('waitlisted');
});
}
But to complete the migration, I need to set registered to be 1 if the booking previously existed in my database (there is a record in the pivot table). How do I do that?
Migrations are for setting up database tables and schemas, I think it would be better to leave that separated from generating and filling the values in side the table.
I suggest you use a script to do the job of setting registered to 1. Seeding is a convenient component for database scripts in Laravel. For example:
# AttendeeRegisteredSeeder.php
public function run()
{
foreach (Attenndee::all() as $attendee) {
foreach ($attendee->programs as $program) {
$program->pivot->registered = 1;
$program->pivot->save();
}
}
}
After you completed the seeder script, run the artisan command:
php artisan db:seed --class=AttendeeRegisteredSeeder
This will only run the specified seeder class, which I think is what you want in your case.
Hope this helps.

How is a pivot table created by Laravel?

In Laravel 4, when working with many-to-many relationships as described in the 4.2 docs, how can I actually get Laravel to create the pivot table for me?
Do I need to add something in my migrations for the two models that are involved? Do I need to manually create a migration for the pivot table? Or how does Laravel know to create the pivot table?
All I've done so far is add the belongsToMany information to the two respective models, i.e.
class User extends Eloquent
{
public function roles()
{
return $this->belongsToMany('Role');
}
}
However, that does not trigger creation of the pivot table. What step am I missing?
It appears as though the pivot table does need to be created manually (i.e. Laravel does not do this automatically). Here's how to do it:
1.) Create a new migration, using singular table names in alphabetical order (default):
php artisan make:migration create_alpha_beta_table --create --table=alpha_beta
2.) Inside the newly created migration, change the up function to:
public function up()
{
Schema::create('alpha_beta', function(Blueprint $table)
{
$table->increments('id');
$table->integer('alpha_id');
$table->integer('beta_id');
});
}
3.) Add the foreign key constraints, if desired.
(I haven't gotten to that bit, yet).
Now to seed, say, the alpha table, using keys from beta, you can do the following in your AlphaTableSeeder:
public function run()
{
DB::table('alpha')->delete();
Alpha::create( array(
'all' => 'all',
'your' => 'your',
'stuff' => 'stuff',
) )->beta()->attach( $idOfYourBeta );
}
I use Jeffrey Way's Laravel-4-Generators or Laravel-5-Generators-Extended.
then you can just use this artisan command:
php artisan generate:pivot table_one table_two
To expand on Ben's answer (I tried to edit it but reviewers said it added too much):
To add the foreign key constraints, make sure if alpha id is unsigned, alpha_id is also unsigned in the pivot table. This migration would run after (2) in Ben's answer since it alters the table created then.
public function up()
{
Schema::table('alpha_beta', function(Blueprint $table)
{
$table->foreign('alpha_id')->references('id')->on('alpha');
$table->foreign('beta_id')->references('id')->on('beta');
});
}
For Many to Many relationships you can create the Migration file of the Database manually like this:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateAccountTagTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('account_tag', function (Blueprint $table) {
// $table->timestamps(); // not required
// $table->softDeletes(); // not required
$table->integer('account_id')->unsigned();
$table->foreign('account_id')->references('id')->on('accounts');
$table->integer('tag_id')->unsigned()->nullable();
$table->foreign('tag_id')->references('id')->on('tags');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('account_tag');
}
}
Note: in case you have timestamps on the pivot table you must set withTimestamps on the relationship of both ends like this:
return $this->belongsToMany(\Mega\Modules\Account\Models\Tag::class)->withTimestamps();
.
return $this->belongsToMany(\Mega\Modules\Account\Models\Account::class)->withTimestamps();
Create new migration:
php artisan make:migration create_alpha_beta_table --create=alpha_beta
Inside the newly created migration:
public function up() {
Schema::create('alpha_beta', function(Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('alpha_id');
$table->unsignedBigInteger('beta_id');
// foreign keys
$table->foreign('alpha_id')->references('id')->on('alphas');
$table->foreign('beta_id')->references('id')->on('betas');
});
}
for the latest Laravel's versions:
composer require --dev laracasts/generators
php artisan make:migration:pivot table1 table2
In addition to all the above answers
There is no need to have an AI index for a pivot table. Its uniquely defined by its touple (key1,key2).
The primary key should be the composition (key1,key2). The benefits are that the touples are unique and all queries are best optimized.
So here comes a real life example:
Schema::create('bill_user', function (Blueprint $table) {
// unsigned is needed for foreign key
$table->integer('user_id')->unsigned();
$table->integer('bill_id')->unsigned();
$table->primary(['user_id', 'bill_id']);
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
$table->foreign(bill_id')
->references('id')->on('bills')
->onDelete('cascade');
});
following the latest laravel conventions, the up method should be
public function up() {
Schema::create('country_timezone', function (Blueprint $table) {
$table->foreignId('country_id')->references('id')->on('countries');
$table->foreignId('timezone_id')->references('id')->on('timezones');
});
}
the simplest but modern way of writing pivot table migration, where the Country and Timezone are models with many-to-many relationship. And id and timestamps are not necessary to include but straightforward manner
in the older version, you can use some generator or artisan to make pivots,
but in the newer version, this work is too easy.
you must only make migration to do that like the below code.
php artisan make:migration category_post --create=category_post
after run code
make migration with this params
$table->foreignId('post_id')->constrained('post');
$table->foreignId('category_id')->constrained('category');

Resources