How do i change a column's reference table in laravel 7 - database

I made a mistake when i was building database, so as you will see in codes, my "order_id" column in "baskets" table is referenced from "customers" table but it should have been from "orders" table,
public function up()
{
Schema::create('baskets', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('firm_id');
$table->foreign('firm_id')
->references('id')->on('firms')
->onDelete('cascade');
$table->unsignedBigInteger('customer_id');
$table->foreign('customer_id')
->references('id')->on('customers')
->onDelete('cascade');
$table->unsignedBigInteger('order_id');
$table->foreign('order_id')
->references('id')->on('customers')
->onDelete('cascade');
$table->unsignedBigInteger('service_id');
$table->foreign('service_id')
->references('id')->on('services')
->onDelete('cascade');
$table->decimal('price', 11, 2);
$table->integer('quantity')->default(1);
$table->string('note')->nullable();
$table->timestamps();
});
}
So how can i change its reference table from "customers" to "orders" table.
Thank you all in advance.

You should be looking at the dropForeign method (scroll down a little).
This method accepts an $index argument. The documentation already shows how to write this $index. Looking at the source code you can also see how this index is being generated. At some point the createIndexName method is being called during the foreign call.
Looking at your code and the createIndexName method, we could guess the index name that is being created:
baskets_order_id_foreign
To round it up you might be able remove the foreign key by executing the following:
public function up()
{
Schema::table('baskets', function (Blueprint $table) {
$table->dropForeign('baskets_order_id_foreign');
// Add your new foreign key
});
}

Related

Add column to all tables through migration in Laravel

As our project scaled we decided that every single data should belong to companies that created them. Therefore I'm to add a column "data_owner_company_id" that points to the company that owns given record. Yes it's possible to generate migration to add this column to each model but that is not really feasible since there is 120+ tables & models. How can i tackle this with minimum effort ?
For the model part i figured i can easily apply it to all models by inheritance, but not sure about migration.
TL;DR
How to add int column to all tables by migration ?
Database: MySQL v8
Framework: Laravel 8, PHP 7.3
It's simple if you find all the tables' names in your database, you have to loop and create columns for each and every table.
Try creating columns using queues as it will be a heavy job for 120 tables.
Check the following code:
class CreateDataOwnerCompanyIdtoEachTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up ()
{
$columns = 'Tables_in_' . env('DB_DATABASE');//This is just to read the object by its key, DB_DATABASE is database name.
$tables = DB::select('SHOW TABLES');
foreach ( $tables as $table ) {
//todo add it to laravel jobs, process it will queue as it will take time.
Schema::table($table->$columns, function (Blueprint $table) {
$table->unsignedInteger('data_owner_company_id');
});
}
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down ()
{
$columns = 'Tables_in_' . env('DB_DATABASE');//This is just to read the object by its key, DB_DATABASE is database name.
$tables = DB::select('SHOW TABLES');
foreach ( $tables as $table ) {
//todo add it to laravel jobs, process it will queue as it will take time.
Schema::table($table->$columns, function (Blueprint $table) {
$table->dropColumn('data_owner_company_id');
});
}
}
}
I'm not 100% sure that it's going to work, but here it goes:
Create class that extends Illuminate\Database\Schema\Blueprint;
In constructor call parent construntor and then
$this->unsignedBigInteger('data_owner_company_id')->nullable();
Use your new class in migrations instead of default Blueprint

Don't see new field in laravel DB after migration

I had glass_posts table in database like that
Schema::create('glass_posts', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->integer('category_id')->unsigned();
$table->string('title', 255);
$table->string('slug', 255)->unique();
$table->text('fulltext')->nullable();
$table->string('image', 255)->nullable();
$table->timestamps();
$table->softDeletes();
$table->foreign('category_id')
->references('id')
->on('glass_categories')
->onDelete('RESTRICT');
$table->index('published');
});
then I decided to insert one more field gallery
Schema::create('glass_posts', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->integer('category_id')->unsigned();
$table->string('title', 255);
$table->string('slug', 255)->unique();
$table->text('fulltext')->nullable();
$table->string('image', 255)->nullable();
$table->string('gallery', 255)->nullable();
$table->timestamps();
$table->softDeletes();
$table->foreign('category_id')
->references('id')
->on('glass_categories')
->onDelete('RESTRICT');
$table->index('published');
});
So I delete glass_posts table from DB, then delete value 2020_03_29_104428_create_glass_tables from migrations database and then I run php artisan migrate
Now when I go to DB I see table with new field, but when I output value from database dd($item) I see all fields, except gallery.
It is not clear for me why it is so.
I tried to clear cache, but no help.
php artisan route:clear
php artisan view:clear
php artisan cache:clear

How sol solve this database migration issue?

I'm having trouble with Laravel database migration. I have entered foreign key constraint in my database migration file, but when I try to migrate the file it shows this error message.
Illuminate\Database\QueryException : SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') on delete cascade on update cascade' at line 1 (SQL: alter table education_qualifications add constraint education_qualifications_teacher_id_foreign foreign key (teacher_id) references teachers () on delete cascade on update cascade)at E:\XAMPP\htdocs\ViduresaApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:664
660| // If an exception occurs when attempting to run a query, we'll format the error
661| // message to include the bindings with SQL, which will make this exception a
662| // lot more helpful to the developer instead of just the database's errors.
663| catch (Exception $e) {
> 664| throw new QueryException(
665| $query, $this->prepareBindings($bindings), $e
666| );
667| }
668|
Exception trace:
1 PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') on delete cascade on update cascade' at line 1")
E:\XAMPP\htdocs\ViduresaApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:452
2 PDO::prepare("alter table education_qualifications add constraint education_qualifications_teacher_id_foreign foreign key (teacher_id) references teachers () on delete cascade on update cascade")
E:\XAMPP\htdocs\ViduresaApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:452
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateEducationQualificationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('education_qualifications', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('teacher_id')->nullable();
$table->unsignedInteger('student_id')->nullable();
$table->string('institute_name');
$table->string('user_degree');
$table->string('field_of_study');
$table->string('user_grade');
$table->date('from_date')->nullable();
$table->date('to_date')->nullable();
$table->text('edu_description');
$table->timestamps();
$table->foreign('teacher_id')->references('id')->on('teachers')->onUpdate('cascade')->onDelete('cascade');
$table->foreign('student_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade');
$table->primary(['teacher_id', 'student_id']);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('education_qualifications');
}
}
You can use both onupdate and ondelete at the same line
For example:
$table->foreign(’author’)->references(’id’)->on(’users’)->onUpdate(’cascade’);

Laravel Eloquent how to create UNIQUE constraint with duplicate NULLs

I'm usinq Laravel 5 with MS Sql Server 2014.
I want to create a unique constraint but it should allow multiple null values.
Here is code I'm using. Where 'passport_no' has to be unique if not null.
Schema::create('UserProfile', function(Blueprint $table){
$table->increments('userprofile_id');
$table->integer('user_id')->unsigned();
$table->string('passport_no', 50)->unique()->nullable();
$table->foreign('user_id')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
});
This is an ancient question, but sill needs answering. As stated above, SQL Server from 2008, including Azure SQL, supports a special index that will work around it. In your database migration you can check the driver used and substitute the database builder standard SQL with an MSSQL-specific statement.
This migration example is for Laravel 5+, and creates a users table with a unique, but nullable, api_token column:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
$table->string('name', 100)->nullable()->default(null);
// etc.
$table->string('api_token', 80)->nullable()->default(null);
if (DB::getDriverName() !== 'sqlsrv') {
$table->unique('api_token', 'users_api_token_unique');
}
});
if (DB::getDriverName() === 'sqlsrv') {
DB::statement('CREATE UNIQUE INDEX users_api_token_unique'
. ' ON users (api_token)'
. ' WHERE api_token IS NOT NULL');
}
}
you can use a unique Index and in its filter set your condition like
passport_no is not null
in this way you can solve your problem

Does EF create an in memory model of the database every time I create a new DbContext?

I have the following class to create my dbcontext:
public class DataContext : DbContext
{
public DataContext()
: base(nameOrConnectionString: "Default") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public DbSet<TestAccount> TestAccounts { get; set; }
public DbSet<Application> Applications { get; set; }
}
My database has the following table:
CREATE TABLE [dbo].[TestAccount] (
[TestAccountId] INT IDENTITY (1, 1) NOT NULL,
[ApplicationId] INT,
[Name] NVARCHAR (MAX) NOT NULL,
[DataVersion] ROWVERSION,
CONSTRAINT [PK_dbo.TestAccount] PRIMARY KEY CLUSTERED ([TestAccountId] ASC),
CONSTRAINT fk_AccountApplication FOREIGN KEY (ApplicationId) REFERENCES Application(ApplicationId)
);
From what I understand EF will create an in memory model of the database but what I don't understand is will that information automatically include the foreign key relationships or do I need to specify those like this example that I found on the internet:
// public AccountConfiguration()
// {
// // // Account has 1 Speaker, Speaker has many Account records
// // HasRequired(s => s.Speaker)
// // .WithMany(p => p.SpeakerAccounts)
// // .HasForeignKey(s => s.SpeakerId);
// }
Also if the database is already existing do I need to put in things like I have to remove the PluralizingTableNameConvention?
One more question. How often does EF create the "in memory model of the database". Does this happen every time I instantiate the DbContext class?
Yes you need to configure relationships unless you are following the conventions . Here is some details on code first conventions.
If database already existing you may need to change configuration(mapping) according to the existing database.
For each instance of DbContext it will create an in memory instance (But it will not load all the data in the db to the memory unless you access them)

Resources