laravel4 add checkbox column in database using migration file - laravel

I am using laravel4 to develop one of my project.I have a migration file where i want to add unchecked or by default a false checkbox colummn to add approval functionality for admin.So my question is very simple ,that is how to add a unchecked checkbox column in a migration file.
here is my marriage migration file,
Schema::create('marriages', function(Blueprint $table)
{
$table->increments('id');
------------------------ // field for unchecked checkbox column
$table->string('candidate_name',255)->unique();
$table->string('email',255)->unique();
$table->string('father_name',60);
$table->string('mother_name',60);
$table->date('date_of_birth');
$table->string('sex',60);
$table->string('location',255);
$table->string('blood_group',20);
$table->string('religion',60);
$table->string('present_address',255);
$table->string('permanent_address',60);
$table->string('height',100)->nullable();
$table->string('complexion',100);
$table->string('nationality',100);
$table->string('educational_qualification',255);
$table->string('occupation',255);
$table->integer('phone_number');
$table->integer('number_of_bro_sis');
$table->string('image',255);
$table->timestamps();
});
Update:
now how can i check it in my template,i want to show those results from this field which is actually approved ,should i use
#if($results->approved(true))
then show the results object
or should i use some thing else?

There is no such thing as a "checkbox" column. You are probably talking about a boolean, which is technically speaking a tinyint (assuming you use MySQL)
Here's how you add one:
$table->boolean('approved');
usually the default should be false now, but to make sure:
$table->boolean('approved')->default(false);
Here's the full reference of all schema builder column methods
About your edit
If you would want to use $results->approved(true) or $results->approved() you would have to add a custom function to your model.
However you can do it much simpler
#if($results->approved == true)
Or even omit == true because the if will check for a "truthy" value
#if($results->approved)

Related

laravel migration for change column type that used in a view

I use laravel migartion to create some tables and then i create a migration for a view that use my tables.
now, i want to change type of column that used in this view (i create a new migration for it.).but, PostgreSQL does not let me to change column type because column is used in view. i want to know what is best way to manage this issue.
i tried to use migration that created view to drop then and recreate it after changing column type but there is problem because migrations doesn't have namespaces and i don't know is it good way for solving this problem.
First, my English is not good. What i understand is, you are creating a new migration with already existing table? If the table is already existed then you may try to change the column name using this
Schema::table('users', function (Blueprint $table) {
$table->string('name', 50)->change();
});
Laravel Documentation
I fix my issue with following level:
add folder common-queries in project/database/migrations/
add CommonQueries namespace in composer.json with project/database/migrations/common-queries folder location.
add my view create and drop in a class MyCurrentView (for example).
use this class in old migration up and down function for creating and droping view
use this class in new migration and drop view before changing column type and create view after changing column type.

What is the best way to copy data from one field to another when creating a migration of a new field?

I have a database table having a field that has a boolean field type. Now, as per the new requirement, the field should be changed to the small integer type.
In order to achieve it, I created a migration and added the script in the same migration file to copy the value from the old field to the new field. However, I think this is not the best approach that I have followed. Can someone please help and advise about the best way to handle this scenario.
public function up()
{
Schema::table('skills', function (Blueprint $table) {
$table->tinyInteger('skill_type_id')->nullable()->comment = '1 for advisory skills, 2 for tools, 3 for language & framework';
});
$skill_object = (new \App\Model\Skill());
$skills = $skill_object->get();
if (_count($skills)) {
foreach($skills as $skill) {
$skill_type = 1;
if ($skill->is_tool) {
$skill_type = 2;
}
$skill_object->whereId($skill->id)->update(['skill_type_id' => $skill_type]);
}
}
}
You can do it with 02 migrations, the first one is to create the new field, as already did. The second is create a migration with raw statement to copy value from old field to new field.
If you don't need anymore old field, you can create a third migration deleting the old field.
public function up()
{
Schema::table('skills', function (Blueprint $table) {
DB::statement('UPDATE skills SET skill_type_id = IF(is_tool, 2, 1)');
}
}
You can do this(update the data) from the following way in your scenario.
Create separate routes and update the data after the migrations.
Create seeder(having the same query as above in migrations file) run the seeder.
But above both solutions are little risky if you are trying to do this with your production database. If someone mistakenly hit URL and run seeder multiple time, It's difficult to manage.
I believe the best way to solve your problem by seed(modify) the data on the same migrations file after modifying the schema because migrations won't run again (even mistakenly), Once it migrated.
You are doing the correct way as I believe.
You are free to develop your own way to achieve this task, but as far as migrations are concerned, these are meant for controlling and sharing the application's database schema among the team, not the actual data ;)
You can create separate seeder for this task.
It will keep your migration clean and easy to rollback if needed.
NOTE: Don't include this seeder class in DatabaseSeeder.
These kind of seeder class are only meant for update the existing data after fixing the current functionality(I am taking into consideration, you have already fixed the code as per your new requirement). So, there is not need to worry about re run the same seeder class.
Considering (laracast, stack-overflow), i will prefer to go by your way over the suggestions provided above as neither i have to maintain extra route nor additional migration (03).
The only improvement i can suggest here is you can use databse-transaction something like this :
// create new column
DB::transaction(function () {
update new column
delete old column
});

Laravel Database migrations Schema builder custom column type

I am trying to create migrations with Laravel but I am in a situation where I need custom column type since the one I want isn't included in schema builder , which is "POLYGON". So I want to know, how I can create my custom column type, other than those that are already in the Schema builder.
What I want would look like this in SQL statement:
alter table xxx add polygon POLYGON not null
Is it possible to do it by myself or I am forced to use some library like this?
I know that I can do like this:
DB::statement('ALTER TABLE country ADD COLUMN polygon POLYGON');
but it leads me to the error that the table doesn't exist.
There is no built in way to do this but you can achieve a good result with minimal code.
<?php
use Illuminate\Database\Schema\Grammars\Grammar;
// Put this in a service provider's register function.
Grammar::macro('typePolygon', function (Fluent $column) {
return 'POLYGON';
});
// This belongs in a migration.
Schema::create('my_table', function (Blueprint $table) {
$table->bigIncrements('id');
$table->addColumn('polygon', 'my_foo');
});
The key is to add a function with the name typePolygon to the Grammar class because this function is what determines the actual type used by the particular DBMS. We achieve this by adding a macro to the Grammar.
I have written a blog post about how to extend this solution to any custom type: https://hbgl.dev/add-columns-with-custom-types-in-laravel-migrations/
I assume you require spatial fields in your DB... I would consider via Packagist.org and search for laravel-geo (or equivalent) - which supports spatial column tyes inc Polygon. You could then use standard Laravel migration files for your custom fields -e.g.
$table->polygon('column_name');
In your UP function in your migration file...

Laravel migration default value

I didn't understand what is the effect of the default option in the migrations.
I can see that the column in the database is defined with default value, but the models are ignore it completely. Say I have a Book model that reflect the books table in the database. I have migration to create the books table:
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
->string('author');
->string('title');
->decimal('price', 4, 1)->default(100);
->timestamps();
});
When I create a new instance of Book model I see:
$book = new Book();
var_dump($book->price); //Always 0...
The default value is ignored and the attribute is not sets correctly.
Ok, I can get it, because it is a new object and it shouldn't get the default values from the DB. But if I tries to save model like:
$book = new Book();
$book->author = 'Test'
$book->title = 'Test'
$book->save();
It is saves 0 in the field price in the database!
So what is the point of the default option in the migrations?
By the way...
It wasn't be better if the model see inside the migration (if exists) what are the fields types and behavior instead to define it manually in the model and the migration? And moreover, even to create a validator automatically for the model. I think that it was possible with small change of the migration structure, so why it is not like that?
Put the default value in single quote and it will work as intended. An example of migration:
$table->increments('id');
$table->string('name');
$table->string('url');
$table->string('country');
$table->tinyInteger('status')->default('1');
$table->timestamps();
EDIT : in your case ->default('100.0');
In Laravel 6 you have to add 'change' to your migrations file as follows:
$table->enum('is_approved', array('0','1'))->default('0')->change();
You can simple put the default value using default(). See the example
$table->enum('is_approved', array('0','1'))->default('0');
I have used enum here and the default value is 0.
Might be a little too late to the party, but hope this helps someone with similar issue.
The reason why your default value doesnt't work is because the migration file sets up the default value in your database (MySQL or PostgreSQL or whatever), and not in your Laravel application.
Let me illustrate with an example.
This line means Laravel is generating a new Book instance, as specified in your model. The new Book object will have properties according to the table associated with the model. Up until this point, nothing is written on the database.
$book = new Book();
Now the following lines are setting up the values of each property of the Book object. Same still, nothing is written on the database yet.
$book->author = 'Test'
$book->title = 'Test'
This line is the one writing to the database. After passing on the object to the database, then the empty fields will be filled by the database (may be default value, may be null, or whatever you specify on your migration file).
$book->save();
And thus, the default value will not pop up before you save it to the database.
But, that is not enough. If you try to access $book->price, it will still be null (or 0, i'm not sure). Saving it is only adding the defaults to the record in the database, and it won't affect the Object you are carrying around.
So, to get the instance with filled-in default values, you have to re-fetch the instance. You may use the
Book::find($book->id);
Or, a more sophisticated way by refreshing the instance
$book->refresh();
And then, the next time you try to access the object, it will be filled with the default values.
The problem you face is not about the migration file. The value turns into 0 every time because you didn't change $fillable on your model. When you forget to add recently added column to $fillable of its model, Laravel inserts 0.

Can Laravel's Eloquent update a creation time but not an update time?

I'm presently learning Laravel and Eloquent, and have set up some initial migrations to play with. One of my tables only needs a creation time, since once a row is inserted there, it will never be updated:
// The run table only needs a creation timestamp, not an updated timestamp
Schema::create('runs', function (Blueprint $table) {
$table->increments('id');
$table->timestamp('created_at');
});
I understand that Eloquent by default expects both a created_at and an updated_at column to be present, and that this feature can be turned off entirely. From the manual:
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.
However, is it possible for Eloquent to be asked to automatically set a creation time and not an update time? I realise I can do this manually, but it would be nice if Eloquent could do this "for free".
Short answer: no.
I had a look at framework/src/Illuminate/Database/Eloquent/Model.php which handles the timestamps and it's not directly possible.
You could override a bunch of methods to make it work:
public function setUpdatedAt($value)
anywhere there's a reference to static::UPDATED_AT
anywhere that depends on the value of usesTimestamps()
and certainly other places
At best, this would be vulnerable to future code changes so I don't recommend it.
you can just use
$model->touch();

Resources