Benefit Of Migrations in Laravel - php

as In laravel we Use Migrations to Create Tables and then Seeders to seed out table, am not getting its benefit, as we can do that in normal way by just going to PHPMYADMIN then what we need to that, as we code many lines for it, but how can we justify those lines of code ?
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateItemsTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('items', function(Blueprint $table)
{
$table->increments('id');
$table->integer('owner_id');
$table->string('name');
$table->boolean('done');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('items');
}
}
it is true that migrations are being created by php artisan commands, But what is the benefit of them? as we have an alternate to do that?
same for the Seeder files as we code many lines for it
class ItemTableSeeder extends Seeder{
public function run(){
DB::table('items')->delete();
$items= array(
array(
'owner_id' => '1',
'name' => 'Watch The Spectacular Now',
'done' => True
),
array(
'owner_id' => '2',
'name' => 'Watch Avengers',
'done' => False
),
array(
'owner_id' => '1',
'name' => 'Watch The Iron man',
'done' => False
),
array(
'owner_id' => '1',
'name' => 'Divergent',
'done' => False
),
array(
'owner_id' => '1',
'name' => 'Bat Man',
'done' => False
),
array(
'owner_id' => '1',
'name' => 'X-Men Days Of Future Past',
'done' => False
)
);
DB::table('items')->insert($items);
}
}

The main benefit is that you will do it in your development server/station, and you may change the schema many times in development, migrate, rollback migrations, and re-migrate them, and as soon as your application id done, you don't have to remember what you have to do in your production environment, Laravel will do it automatically for you.
Using PHPMyAdmin, you would have to create tables and edit fields manually locally and in your remote server, and you would risk forgetting something and breaking your application. And, if you have more than one server serving your application, the problem is bigger.

Migrations and seeds are database versioning. Imagine that one day you fall in love with, say PostgreSQL or anything other than MySQL. Then imagine you'd like to do some tests with more than several rows of data.. Would you run PHPMYADMIN's equivalent and insert 100, 1000 or 10000 rows?
So now check this out:
// migration
class CreateCommentsTable extends Migration {
public function up()
{
Schema::create('comments', function(Blueprint $table) {
$table->increments('id');
$table->string('body');
$table->integer('author_id')->unsigned();
$table->integer('post_id')->unsigned();
$table->timestamps();
});
}
// seeder
class CommentsTableSeeder extends Seeder {
public function run()
{
Eloquent::unguard();
$faker = Faker::create();
foreach(range(1, 1000) as $index)
{
Comment::create([
'body' => $faker->sentence(10),
'author_id' => rand(1,20),
'post_id' => rand(1,150)
]);
}
}
Faker is a great tool you can find here: https://github.com/fzaninotto/Faker
All you need to do now is run artisan migrate --seed.
Of course there are more advantages than automating seeds, you can alter your tables with migrations in case you want to change your schema and so on.

Migration files maintains the schema of the tables. Using migration, you may never have to go to phpMyAdmin (except for creating a DB). Once done you can simply run the command 'php artisan migrate' and create the tables from the PHP side itself. Also you will never have to worry about the DB environment (MySql, Posgres, Sql Lite etc) as the migration does not truly depend on the environment to which you are migrating the tables.
Seeding helps in creating, for example, different roles (Admin, User, Editor etc) within your application. You will have to just create the seeder files and run the 'php artisan db:seed' command to populate data to the tables from the php side. Also seeds help in creating test data.

Related

Illuminate\Database\Grammar::parameterize(): Argument #1 ($values) must be of type array, string given

I am trying to Seed a database using a Model Factory in Laravel but am seeing this error on the terminal.
$ php artisan tinker
Psy Shell v0.11.8 (PHP 8.1.0 — cli) by Justin Hileman
>>> Parking::factory(1)->create();
[!] Aliasing 'Parking' to 'App\Models\Parking' for this Tinker session.
TypeError: Illuminate\Database\Grammar::parameterize(): Argument #1 ($values) must be of type array, string given, called in C:\wamp64\www\my-valet\vendor\laravel\framework\src\Illuminate\Database\Query\Grammars\Grammar.php on line 1010
From the multiple solutions I have tried, it seems the issue is at the faker-generated content level, but I need that faker content for the factory to work as intended.
Below are the Factory and Migration classes that will help you when trying to find the solution.
Here is my factory class
class ParkingFactory extends Factory
{
protected $model = Parking::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition(): array
{
return [
'name' => $this->faker->words(2),
'description' => $this->faker->sentence,
'spaces' => rand(10, 100),
'physical_location' => $this->faker->streetAddress,
'latlng' => $this->faker->localCoordinates,
'base_pay' => $this->faker->numberBetween(100, 200),
'base_pay_breakdown' => $this->faker->sentence,
'rate_per_minute' => $this->faker->numberBetween(2, 10),
'overnight_base_pay' => $this->faker->numberBetween(100, 200),
'overnight_base_pay_breakdown' => $this->faker->sentence,
'overnight_rate_per_minute' => $this->faker->numberBetween(2, 10),
'other_charges_base_pay' => $this->faker->numberBetween(100, 200),
'other_charges_base_pay_breakdown' => $this->faker->sentence,
'other_charges_rate_per_minute' => $this->faker->numberBetween(2, 10),
'has_disability_accessibility' => $this->faker->boolean,
'has_other_charges' => $this->faker->boolean(1),
'has_overnight_parking' => $this->faker->boolean,
'overnight_charge_type' => $this->faker->randomElement(['none', 'flat', 'minute', 'both']),
// 'owner_id' => User::factory()->create(),
'created_at' => now(),
'updated_at' => now()
];
}
}
Here is the migration for the Parking table
Schema::create('parkings', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->mediumText('description');
$table->string('code')
->nullable();
$table->integer('spaces');
$table->string('physical_location')
->nullable();
$table->string('latlng')->nullable();
//charges info
$table->decimal('base_pay')
->default(0.00);
$table->string('base_pay_breakdown')
->nullable();
$table->decimal('rate_per_minute')
->default(0.00);
$table->decimal('overnight_base_pay')
->default(0.00);
$table->string('overnight_base_pay_breakdown')
->nullable();
$table->decimal('overnight_rate_per_minute')
->default(0.00);
$table->decimal('other_charges_base_pay')
->default(0.00);
$table->string('other_charges_base_pay_breakdown')
->nullable();
$table->decimal('other_charges_rate_per_minute')
->default(0.00);
//charges info end
$table->boolean('has_disability_accessibility')
->default(false);
$table->boolean('has_other_charges')
->default(false);
$table->boolean('has_overnight_parking')
->default(true);
$table->string('overnight_charge_type')
->default('none'); //flat | minute | both
$table->string('status')
->default('active');
$table->foreignId( 'owner_id')
->nullable()
->constrained('users')
->nullOnDelete();
$table->timestamps();
$table->softDeletes();
});
It is worth noting am using Laravel v9.24.0, PHP v8.1.0, and MySQL v8.0.27.
What might be the cause of my error?
The name field of your table is defined as a string, however, the words method of faker returns an array.
Supplying the words method with true as a second argument will return two words as a string.
'name' => $this->faker->words(2, true);
$this->faker->words(2)
Generates 2 words in an array, which isn't accepted as valid param when you're trying to insert it into the db.
[
"omnis",
"sequi",
]
Either serialize it using implode function, or do it any other way.

Error : "Trying to get property 'id' of non-object" with Foreign keys on Laravel8

I want to write a correct PostFactory for seed my DB with Laravel8
I follow the documentation on Laravel8 for make my Factory for seed my database
https://laravel.com/docs/8.x/seeding#using-model-factories
I have 3 Models :
Category.php
Post.php
User.php
I can seed my DB when i use this command :
php artisan db:seed --class=UserSeeder
php artisan db:seed --class=CategorySeeder
But i can't seed :
php artisan db:seed --class=PostSeeder
php artisan db:seed for seed all DB with one command
My PostSeeder :
class PostSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
\App\Models\Post::factory(50)->create();
}
}
My PostFactory :
public function definition()
{
return [
'title' => $this->faker->sentence(rand(5, 10)),
'content' => $this->faker->sentences(50, true),
'image' => 'https://via.placeholder.com/350/65' . rand(1, 100),
'created_at' => now(),
'updated_at' => now(),
'category_id' => Category::inRandomOrder()->first()->id,
'users_id' => User::inRandomOrder()->first()->id,
];
}
My PostFactory does'nt want to take my seed
I encounter this error :
PS C:\Users\Chris\Desktop\Laravel_Projects\Blog> php artisan db:seed
ErrorException
Trying to get property 'id' of non-object
at C:\Users\Chris\Desktop\Laravel_Projects\Blog\database\factories\
28▕ 'content' => $this->faker->sentences(50, true),
29▕ 'image' => 'https://via.placeholder.com/350/65'
30▕ 'created_at' => now(),
31▕ 'updated_at' => now(),
1 C:\Users\Chris\Desktop\Laravel_Projects\Blog\database\factories\PostFactory.php:32
Illuminate\Foundation\Bootstrap\HandleExceptions::handleError("Trying to get property 'id' of non-object", "C:\Users\Chris\Desktop\Laravel_Projects\Blog\database\factories\PostFactory.php", [])
2 C:\Users\Chris\Desktop\Laravel_Projects\Blog\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Factories\Factory.php:424
Database\Factories\PostFactory::definition()
My problem come with my 2 foreign keys :
I see the other post with this error but i can't debug with a dd();
I don't found how write my definition for my 2 foreign keys
I have try to check() my id but it'same result.
And to seed my posts_table after and before my users_table and catergories_table it's same.
I tried things with the different posts on the subject without success..Any help is appreciated.
Use the random id it is create random id and how many create record so you define in your seeder.this two line add on your post factory. i hope help you.
'category_id' => Category::all()->random()->id,
'users_id' => User::all()->random()->id,

Laravel create user statement doesn't store specific columns

I am using Laravel version 5.4 . I have a table called Users and each user has the below columns :
Schema::create('users', function (Blueprint $table) {
$defaultValue = 0;
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('facebook_id')->unique();
$table->string('avatar');
$table->integer('newsletter')->default($defaultValue); // <-
$table->bigInteger('category_1')->default($defaultValue); // <-
$table->bigInteger('category_2')->default($defaultValue); // <-
$table->bigInteger('category_3')->default($defaultValue); // <-
$table->timestamp('unlocked_tip_of_category_1_at')->nullable();
$table->timestamp('unlocked_tip_of_category_2_at')->nullable();
$table->timestamp('unlocked_tip_of_category_3_at')->nullable();
$table->rememberToken();
$table->timestamps();
});
The problem is that when i use the function to create a user category_1, category_2 and category_3 don't take the new value which is 1.
After taking auth from facebook i use the below to store user's information :
return User::create([
'name' => $facebookUser->name,
'email' => $facebookUser->email,
'facebook_id' => $facebookUser->id,
'avatar' => $facebookUser->avatar,
'newsletter' => 0,
'category_1' => 1,
'category_2' => 1,
'category_3' => 1,
]);
For example name changes to facebook user's name. Also i tried changing
'name' => $facebookUser->name,
to
'name' => $facebookUser->name . " HEY",
Which successfuly stored the name and + " HEY" at the end. (Just to be sure that this runs).
Categories are bigInteger that means a bigint(20) type. I am thinking something happens with the default values which i've set it to 0.
Any ideas? If you need any more information please let me know.
From what i am trying to accomplish the best way to solve this is to change the $defaultvalue to 1, but i don't understand why this doesn't work.
If you're using the default laravel scaffolding then you need to ensure you're updating the default App\User model based on all columns you need to have as fillable:
class User extends Model {
protected $fillable = [
'name', 'email', 'password','facebook_id','avatar','newsletter',
'category_1', 'category_2', 'category_3'
];
...
}
Same applies if you're creating your own model.

Faker for Laravel Seeder

I have a table users in a one-many relationship with a table called videos. I want to seed the two table without loosing data integrity. This is what I did below:
$factory->define(App\User::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'email' => $faker->email,
'username' => $faker->unique()->userName
];
});
$factory->define(App\Video::class, function(Faker\Generator $faker){
$user = factory(App\User::class)->create();
return [
'title' => $faker->city,
'link' => $faker->domainName,
'user_id' => $user->id,
'description' => $faker->sentence(40)
];
});
So now all I have to do is create a VideoTableSeeder and run the amount I want. I feel like the way I am handling it is not good enough so I would like to know what better way I can do it. Especially, I want the videos to be more than users rather than the same amount, in the one I had done they will all be the same amount.
Checkout the documentation the section Adding Relations to Models
Adding Relations To Models
You may even persist multiple models to the database. In this example,
we'll even attach a relation to the created models. When using the
create method to create multiple models, an Eloquent collection
instance is returned, allowing you to use any of the convenient
functions provided by the collection, such as each:
$users = factory(App\User::class, 3)
->create()
->each(function($u) {
$u->posts()->save(factory(App\Post::class)->make());
});

laravel returns json string on local machine but integer on elastic beanstalk instance

I am having a strange problem with aws, mysql, laravel and angular.
I have a vagrant instance running locally with both my app and database running on it.
I am using angular on the front-end so when the view is loaded angular makes a request to receive a list of all 'goals' entered by the user. one of the fields in goals is goalStatus. this is either 0 or 1 stored as an integer in the mysql table.
angular checks if this value is 0 or 1 and displays and different table cell depending on the result like so
<th ng-if="goal.goalStatus === '0'"><p class="text-danger">In Progress</p></th>
<th ng-if="goal.goalStatus === '1'"><p class="text-success">Achieved</p></th>
in chrome dev tools when I look at the response result for this request I see goalStatus being returned like so
"goalStatus":"0"
and the angular if statements work as intended.
however when I push this app to a development environment in elastic beanstalk which connects to a mysql rds instance that has the same migrations and seeding run on it dev tools shows goalStatus as this
"goalStatus":0
and the angular if conditions are not met so neither one of the elements displays
So it seems that on the elastic beanstalk instance it is being returned as an integer but on the local machine it is being returned as a string. I dont know weather the problem would be in mysql, laravel, or somewhere else.
any ideas? I have included the laravel migration and seed classes for the table below just in case
migration
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateGoalsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('goals', function(Blueprint $table) {
$table->increments('id');
$table->integer('userId');
$table->string('title');
$table->string('goalDesc');
$table->integer('goalStatus')->nullable();
$table->integer('bodyGoalId')->nullable();
$table->integer('strengthGoalId')->nullable();
$table->integer('distanceGoalId')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('goals');
}
}
seeder
<?php
class GoalsTableSeeder extends Seeder
{
public function run()
{
// Uncomment the below to wipe the table clean before populating
DB::table('goals')->truncate();
$now = date('Y-m-d H:i:s');
$goals = array(array(
'userId' => 1,
'title' => 'first goal title',
'goalDesc' => 'This should describe my goal in text form',
'goalStatus' => 0,
'bodyGoalId' => null,
'strengthGoalId' => null,
'distanceGoalId' => 1,
'created_at' => $now,
'updated_at' => $now),
array(
'userId' => 1,
'title' => 'strength goal title',
'goalDesc' => 'This should describe my strngth goal in text form',
'goalStatus' => 0,
'bodyGoalId' => null,
'strengthGoalId' => 1,
'distanceGoalId' => null,
'created_at' => $now,
'updated_at' => $now),
array(
'userId' => 1,
'title' => 'body goal title',
'goalDesc' => 'This should describe my body goal in text form',
'goalStatus' => 0,
'bodyGoalId' => 1,
'strengthGoalId' => null,
'distanceGoalId' => null,
'created_at' => $now,
'updated_at' => $now)
);
// Uncomment the below to run the seeder
DB::table('goals')->insert($goals);
}
}
So this appears to be an issue with the php mysql driver returning all fields as strings regardless of type. source
My aws elastic beanstalk instance seems to be setup to account for this so it is returning strings and strings and ints as ints whereas my vagrant setup needed to be changed to use php5_mysqlnd driver instead of the one it had and this resolved the issue

Categories