I need an effective way to disable Laravel from auto incriminating the primary key of the table which I am going to insert data in.
Why? I don't check if there is any duplication between the DB and the inserted data so if there was any duplication I just handles it in a try-catch block.
The problem is if there was any failure Laravel counts it like I have inserted a row. So IDs column is not going to be in this order [1, 2, 3, etc], but in this [1, 4, 8, 20, etc].
I searched a lot about this issue and I have tried to use this line after the declaration of the class:
public $autoincrement = false;
Also
public $incrementing = false;
But they are not working.
I just want to use the AI of my DB. Not Laravel's one.
if you wish to use a non-incrementing or a non-numeric primary key you must set the public $incrementing property on your model to false.
eg :
class UserVerification extends Model
{
protected $primaryKey = 'your_key_name'; // or null
public $incrementing = false;
}
in case of migration :
$table->integer('id')->unsigned(); // to remove primary key
$table->primary('id'); //to add primary key
refer : https://laravel.com/docs/5.3/eloquent#eloquent-model-conventions
Try public $incrementing = false;
In your model:
public $incrementing = false;
In your migration:
//Remove the default $table->id();
//second param is what auto-increments, default is false so can be skipped
$table->unsignedBigInteger('id', false)->primary();
A quick comment on all the other outdated or wrong solutions you see here:
$primaryKey does not need to be overridden unless the primary column is different than 'id'
You do not need to use the ugly DB transaction just to remove auto-incrementing! Keep using the lovely eloquent models and just use this answer.
There are 2 solutions to your problem.
First one is, as you said, disable the increment column. To do that, just go to your migrations, and change
$table->increment('id)`
to
$table->integer('id')
It will remove the primary key, to set the primary key, just go to your Model file and add this:
protected $primaryKey = 'column_name';
Second solution is what I prefer. Whenever inserting, updating or removing a record and even sometimes reading a record, use laravel's DB transaction. Here is an example:
DB::beginTranscation();
try {
$model = new Model;
$model->column_name = $value;
$model->save();
DB::commit()
return;
}
catch(exception $e) {
DB::rollback();
return;
}
This approach is better than remove the auto increment. But now it's upto you to choose.
You have to declare your new primary key in your table migration file:
$table->primary('new_key_column');
Of course you have to disable autoincrement in your model as you did.
You can do something like below
Table: author
Columns: id, name, active
class Author extends Model
{
/**
* Configure the Model variables
*
*/
protected $table = 'author';
protected $primaryKey = 'id';
protected $fillable = ['name', 'active']; // eloquent Will use only these columns as you are mentioning them as fillable.
public static function saveAuthor($data) {
$author = Author::firstOrNew(['name' => $data['name']]);
$author->name = $data['name'];
$author->active = 1;
$author->save();
}
}
Here in fillable you define the columns that you want to change or update through model. Rest fields behaviour will take according to mysql definition.
I hope this will help you.
*/ please test this one
public function up()
{
Schema::create('tablename', function (Blueprint $table) {
// $table->increments('id');
$table->integer('id')->unsigned()->nullable();
$table->string('name');
$table->string('info');
$table->timestamps();
});
}
// note:
add below line in model
public $incrementing = false;
This is an example for table created its name site_rules and this is the migration file which i add the following line to make id primary and auto incremented
//add this line to make id auto incremented from a specified value
DB::statement("ALTER TABLE site_rules AUTO_INCREMENT = 1;");
and this is the migration file code :
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class SiteRules extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('site_rules', function (Blueprint $table){
$table->increments('id');
$table->string('name_ar');
$table->string('name_en');
$table->timestamps();
});
//add this line to make id auto increment from a specified value
DB::statement("ALTER TABLE site_rules AUTO_INCREMENT = 1;");
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('site_rules');
}
}
Try it
Sorry for taking your time guys,
The issue is if we tried to save any record in MYSQL whether it returned success or failure for any reason (like for duplication in my case),
MYSQL counts that the auto increment number was booked and any other coming record is not going to take it because of there may be more than an insertion process on the DB in the same time and waiting to know if the auto incrementally number is booked or not will cost MYSQL its speed.
So it is not a Laravel issue, its a MYSQL one.
I hope that it may help others.
Thank you all...
You can use
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->integer('matricule')->unsigned();;
$table->primary(['matricule']);
$table->string('nometprenom');
$table->string('age');
$table->string('adresse');
$table->string('telephone');
$table->string('login');
$table->string('password');
$table->string('type');
$table->engine = 'InnoDB';
});
}
Related
I have a questions table in my database, in which I have a column of question_title, now I have added a column question_slug, which will contain the question's slug URL, so how I set question_slug default value as question_title in Laravel Migration, I need this all because I have questions saved in the database so I have run php artisan make:migration add_column_to_questions --table=questions now I have this code:
Schema::table('questions', function (Blueprint $table) {
$table->string('question_slug')->default();
});
first of all, create a new migration and put this code within it:
connections_string : it's within web/config/database.php file
configuration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class NameOfUrMigration extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('questions', function (Blueprint $table) {
$table->string('question_slug')->default();
});
$questions = DB::connection('connections_string')->table('questions')->get();
foreach($questions as $question)
{
$question->question_slug = str_slug($question->question_title);
$question->save();
}
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
}
}
According to the documentation, default() is used to Declare a default value for a column.
That means the value that gets inserted by default in a field if you do not provide a value for it in the insert query.
The default() cannot help you achieve what you need here.
What you could do is create a new migration class with a raw query in the up() method which will update the value of question_slug with the value of question_title.
something like this:
public function up()
{
$sql = "UPDATE `questions` SET `question_slug` = `question_title` WHERE 1;";
//add filtering conditions if you don't want ALL records updated
DB::connection()->getPdo()->exec($sql);
}
Make sure you also create a corresponding down() method for the rollback
My Laravel migration keeps getting error when reset/refresh:
ORA-01758: table must be empty to add mandatory (NOT NULL)
The migration is as follow:
public function up()
{
Schema::table('kasbank', function (Blueprint $table) {
$table->dropColumn('name_bn');
$table->dropColumn('id_rekon');
$table->string('name_kb')->after('kode');
$table->integer('id_rek')->nullable();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('kasbank', function (Blueprint $table) {
$table->dropColumn('id_rek');
$table->dropColumn('name_kb');
$table->integer('id_rekon')->nullable();
$table->string('name_bn')->after('kode');
});
}
FYI, column id_rekon is initially nullable in the database.
What's missed from my migration?
The problem is that your table is not empty and the current rows will be given NULL as a default value, but the column is not allowed to be NULL.
You should be able to get around it by setting a default value.
From the Oracle docs:
However, a column with a NOT NULL constraint can be added to an
existing table if you give a default value; otherwise, an exception is
thrown when the ALTER TABLE statement is executed.
Try:
$table->integer('id_rek')->default($value)->nullable();
From: https://laravel.com/docs/5.5/migrations
Trying to change data column type to tinyInteger in a Laravel 5.2 migration:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AlterTableNameTableChangeNotificationSentTinyint extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('table_name', function ($table) {
$table->tinyInteger('column_name')->default(0)->change();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
}
}
I'm getting an error:
Doctrine\DBAL\DBALException]
Unknown column type "tinyinteger" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types wit
h \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgot to register all database types for a Doctrine Type. Use Abstrac
tPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot so
me mapping information.
Am I doing something wrong?
Indeed Doctrine Dbal does not support tinyint you can read from their doc here
Unfortunately as well, laravel stated that tinyint cannot be changed. Check here
I need someone to prove this as wrong, because I had to use smallInteger because of this issue for one of my projects. I am thinking maybe boolean() might be the solution. I have not tried this though.
i hope that this will solve your issue
DB::statement("ALTER TABLE table_name CHANGE COLUMN column_name column_name TINYINT UNSIGNED NOT NULL");
Do This
Change tinyInteger to smallInteger
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\SmallIntType;
if (!Type::hasType('integer')) {
Type::addType('integer', SmallIntType::class);
}
I got same problem and found this solution. It worked for me. But it raise in me a question that why creator don't update to doctrine/dbal package. Maybe this solution can cause errors in some case? Hope someone explain in this answer.
Can you use boolean?
or
$table->smallInteger('column_name')->tinyInteger('column_name')->unsigned()->change();
If you are trying to convert a non-numeric column to an int column, you will get this error. The values cannot be converted.
You might run into this when converting an old string value to an id reference to a parent table.
Instead of trying to change the existing column, create a new column and delete the old:
// Add new int column
Schema::table('children', function (Blueprint $table) {
$table->unsignedTinyInteger('parent_id')->after('parent_slug');
});
// Convert old values to new
// Only runs on environments that already have data in db, by virtue of pulling all records from the parents table
foreach (\App\Parents::all() as $parent) {
\App\Child::where('parent_slug', $parent->slug)->each(function ($child) use ($parent) {
$child->update([ 'parent_id' => $parent->id ]);
});
}
// Drop old string column
Schema::table('children', function (Blueprint $table) {
$table->dropColumn('parent_slug');
});
!!! This solution is only for empty tables. Not if already populated.
Just drop and recreate the column with same name.
public function up()
{
// Drop and recreate because laravel don't allow to change to the tinyInteger type
Schema::table('your_table_name', function (Blueprint $table) {
$table->dropColumn(['rating']);
});
Schema::table('your_table_name', function (Blueprint $table) {
$table->tinyInteger('rating')->nullable()->after('some_column_name');
});
}
According to this https://github.com/laravel/framework/issues/8840 "BOOL" and "BOOLEAN" are both synonymous to "TINYINT" therefor just use "boolean" method instead of "tinyInteger", its the same in Laravel.
try this
Schema::table('table_name', function (Blueprint $table) {
$table->tinyInteger('column_name')->default(0)->change();
I have a save method where I do validation, create a model and save it. Later in the save method I try and access the ID of the model and it's NULL.
Schema:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('body');
//and other fields that aren't important right now
$table->timestamps();
});
}
Save method:
public function savePost(Request $request) {
$this->validate($request, [
//some validation happens here
]);
$post = new Post();
$title = $request->input('title');
$body = $request->input('body');
$post->title = $title;
$post->body = $body;
$post->save();
//I later try to access the $post->id here and it's still NULL.
var_dump($post->id);//NULL
}
In MySQL the ID is being set (just an auto incrementing unsigned integer) - it seems like it gets set after the savePost method is complete.
I thought that after $post->save() was complete, the model's ID would be set - but that seems to not be the case. How can I access the model's ID from the same method where I save() it? Or have I made a mistake somewhere?
Laravel Framework version is 5.3.26
Edit: just to clarify: the model (including the auto incrementing PK) is being stored in MySQL, I'm just not able to access the model's id in the same method that I save it.
Figured it out:
I ran into this issue when switching from a string PK to an auto incrementing unsigned int.
I still had public $incrementing = false; in the Post model, which explains this issue. Switching to $incrementing = true solved the problem.
For other people how are using Pivot/Junction table, hence, if your model is extending Pivot instead of Model then this is why,
As #noob mentioned, You've to enable public $incrementing = true; manually or just extend Model instead.
I've just started with Laravel and I get the following error:
Unknown column 'updated_at' insert into gebruikers (naam, wachtwoord,
updated_at, created_at)
I know the error is from the timestamp column when you migrate a table but I'm not using the updated_at field. I used to use it when I followed the Laravel tutorial but now that I am making (or attempting to make) my own stuff. I get this error even though I don't use timestamps. I can't seem to find the place where it's being used. This is the code:
Controller
public function created()
{
if (!User::isValidRegister(Input::all())) {
return Redirect::back()->withInput()->withErrors(User::$errors);
}
// Register the new user or whatever.
$user = new User;
$user->naam = Input::get('naam');
$user->wachtwoord = Hash::make(Input::get('password'));
$user->save();
return Redirect::to('/users');
}
Route
Route::get('created', 'UserController#created');
Model
public static $rules_register = [
'naam' => 'unique:gebruikers,naam'
];
public static $errors;
protected $table = 'gebruikers';
public static function isValidRegister($data)
{
$validation = Validator::make($data, static::$rules_register);
if ($validation->passes()) {
return true;
}
static::$errors = $validation->messages();
return false;
}
I must be forgetting something... What am I doing wrong here?
In the model, write the below code;
public $timestamps = false;
This would work.
Explanation : By default laravel will expect created_at & updated_at column in your table.
By making it to false it will override the default setting.
Setting timestamps to false means you are going to lose both created_at and updated_at whereas you could set both of the keys in your model.
Case 1:
You have created_at column but not update_at you could simply set updated_at to false in your model
class ABC extends Model {
const UPDATED_AT = null;
Case 2:
You have both created_at and updated_at columns but with different column names
You could simply do:
class ABC extends Model {
const CREATED_AT = 'name_of_created_at_column';
const UPDATED_AT = 'name_of_updated_at_column';
Finally ignoring timestamps completely:
class ABC extends Model {
public $timestamps = false;
}
Link to laravel documentation https://laravel.com/docs/9.x/eloquent#timestamps
Nice answer by Alex and Sameer, but maybe just additional info on why is necessary to put
public $timestamps = false;
Timestamps are nicely explained on official Laravel page:
By default, Eloquent expects created_at and updated_at columns to exist on your >tables. If you do not wish to have these columns automatically managed by >Eloquent, set the $timestamps property on your model to false.
For those who are using laravel 5 or above must use public modifier other wise it will throw an exception
Access level to App\yourModelName::$timestamps must be
public (as in class Illuminate\Database\Eloquent\Model)
public $timestamps = false;
In case you still want the timestamps, but simply forgot to add them in the migration, adding the following to your migration file, will also work:
class AddUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->timestamps(); // <-- Add this to add created_at and updated_at
});
}
}
Don't forget to re-run your migration afterwards.
php artisan migrate:rollback
php artisan migrate
First Solution
If not necessary created_at and updated_at, please write the below code in the model.
public $timestamps = false;
Second Solution
If you need to use created_at and updated_at in the future, you can add columns.
Create migration file:
php artisan make:migration add_timestamps_fields_to_users_table
Edit migration file:
class AddTimestampsFieldsToUsersTable extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->timestamps();
});
}
}
Run migration:
php artisan migrate