I usually work with SF2, and with Doctrine, Entities can be generated automatically and if you build the schema in a Soft like MySQL Workbench you can do Reverse Engineering.
I'm new to Laravel so there is a way to do these both things? I would use Laravel because I've to do a very little project, but I didn't want to write all this code for what we call "Migrations", seems very boring no?
So there is a way to generate this stuff in laravel? Maybe I've to use Doctrine in Laravel for that?
If you want to generate migration files from an existing mysql database you can use a Laravel package called XCMer / larry-four-generator. Apart from reverse engineering it has a bunch of other features.
Larry Four is a Laravel 4 package offering advanced model and
migration generation functionality. Thanks to Larry you can quickly
jot down the data scheme for your idea in an easy DSL and genereate
migrations and models from it with just a single click. Larry can also
analyse your existing data scheme and generate some magic for you too.
Try the original best master branch
https://github.com/XCMer/larry-four-generator/tree/master
or my Extended Models fork offering additional functionality
https://github.com/XCMer/larry-four-generator/tree/Gadoma-extendedmodels
As far as I can tell there is still no way to reverse a schema to migration files, using Laravel only. But you can:
1) Export your MySQL schema
mysqldump -u root -p --no-data dbname > schema.sql
2) Create a migration to use your schema
php artisan migration:make create_schema
3) Boot your full schema
class CreateSchema extends Migration {
public function up()
{
$file = file_get_contents(app_path().'/database/data/full_schema.sql', true);
DB::unprepared($file);
}
public function down()
{
}
}
4) After that, if you need to do any changes to your schema, just create new migrations and make your changes.
Not tested, but should work.
Related
Coming from a long Symfony-Doctrine background, I have started learning Laravel 8.
One of my first discovery was that migration needed to be manually created after using make:migration (from what I understood thus far) in both Models and Migration.
Symfony, with Doctrine, allowed a bunch of automatisation, and I only needed to create the field or relation from the Model (php annotation or yaml) - before launching doctrine:schema:validate and make:migration
https://symfony.com/doc/current/doctrine.html#migrations-adding-more-fields.
Let 'say I create a Post and Comment entity, with a One-To-Many relationship.
If I define the relation in the php classes
class Comment extends Model
{
/**
* Get the Post owning this comment
*/
public function post()
{
return $this->belongsTo(Post::class);
}
}
Post class
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany(Comment::class);
}
}
Is possible to generate the migration scripts that would update the database and create these relation ship ? Or will I have to rewrite it twice (once in the PHP class with hasMany/BelongsTo then again in the Migtration file ?
Not having a central file to map/read a model (which linkied php and database) seems weird to me now.
I've only started but the documentation does not seems to mention anything equivalent
Edit : for more clarity : I'm asking if there are equivalent of Generating migration code/script from models (or a central mapping file : yaml or annotation ) without having to write fields to both migration and models ( in $fillable or other fields...)
Edit 2 Closest thing I could find is this
https://github.com/laracasts/Laravel-5-Generators-Extended
Another use case where this is cumbersome : many-to-many migrations
Having to manually write that third middle table from scratch is really something I wish was made automatically.
In laravel framework despite other famous fameworks like symfony or python django, you're responsible for making database migration files. By this way, you are free to customize your database schema and add any database constrains like (unique constrain, relation constrains and etc.). Also you can add any raw sql using \DB::unprepared(); in your migration files.
I can tell you that it is normal to be a little confuse about this flow, because you've used to this kind of automation in other frameworks like I did, but beilieve me, you get to used to this flow.
By the way, there are some packages out there that do this automation (create migration files according to model) for you.
For creating a migration you need to run command
php artisan make:migration migration_name
And for creating a model you need to run command
php artisan make:model table_name
Refer to this link
https://laravel.com/docs/8.x/eloquent#generating-model-classes
By creating a model you create a table, where you can define the columns types and different properties and define the relationship with other tables.
By creating a migration file you can define the table columns and the constraints.
Best way for me to describe my problem and it's go-to solution would be this link;
StackOverflow
My problem is exactly this, and the solution actually is working, but not in my case, either I will have an alternative solution for mine, or I'm doing something wrong with my schema builder and I need to understand it better.
My code is basically like this:
//just an example, not my code
Schema A (as)
//other code, such as table->increments('id')
$table->unsignedInteger('b_id');
$table->unsignedInteger('c_id');
$table->foreign('b_id')->references('id')->on('bs');
$table->foreign('c_id')->references('id')->on('cs');
Schema B (bs)
$table->unsignedInteger('a_id');
$table->unsignedInteger('c_id');
$table->foreign('a_id')->references('id')->on('as');
$table->foreign('c_id')->references('id')->on('cs');
Schema C (cs)
$table->unsignedInteger('a_id');
$table->unsignedInteger('b_id');
$table->foreign('a_id')->references('id')->on('as');
$table->foreign('b_id')->references('id')->on('bs');
So neither order helps me with this solution.
Is there a solution to my case, or my code/schema logic is wrong and I need to modify my code?
Your schema is incorrect. You can't have tables being interdependent, i.e, they can't be both master and slave to each other at the same time. This way, you can never make them at all.
You should create master tables first, let's say A,B,C.
Schema A:
$table->increments('id');
// some other columns
Schema B:
$table->increments('id');
// some other columns
Schema C:
$table->increments('id');
// some other columns
Now, create the child tables, in other words, these are intermediate tables describing many-to-many relationships and you can access them using pivot attribute.
Schema AS:
$table->unsignedInteger('b_id');
$table->unsignedInteger('c_id');
$table->foreign('b_id')->references('id')->on('B');
$table->foreign('c_id')->references('id')->on('C');
Schema BS:
$table->unsignedInteger('a_id');
$table->unsignedInteger('c_id');
$table->foreign('a_id')->references('id')->on('A');
$table->foreign('c_id')->references('id')->on('C');
Schema CS:
$table->unsignedInteger('a_id');
$table->unsignedInteger('b_id');
$table->foreign('a_id')->references('id')->on('A');
$table->foreign('b_id')->references('id')->on('B');
Now, you can successfully run a migration in this order and you should be good to go.
In Laravel >= 5.0, one way to achieve this is to have certain scripts in properly named migration folders. Like I use to have migrations in Sprints.
--migrations/
---Sprint8/
------user_table.php
------car_table.php
--Sprint9/
------complaint_table.php
------supervisor_table.php
With this approach, you have to run the migration command on each of your subfolders:
php artisan migrate --path=/database/migrations/Sprint8
php artisan migrate --path=/database/migrations/Sprint9
However, what you can do is easily extend the artisan system to write your own migrate command that will iterate through all folders under the migrations folder, create these commands for you and run them.
You can also simply write a shell script if you don't want to get into doing this via artisan
I am new in the database migration world. I use or try to use migrations in Rails and Laravel but in none of them I did not understand this parts:
1.For each modification of database like adding a column, change a field type from integer to string, change database type from InnoDB in Myisam should I generate a migration from comand line?
php artisan make:migration ........ for laravel
rake db:migration ..... for rails
Or to edit existing migration files and after execute migration? Or create manually file?
2.When Laravel documentation say:
To rename a column, you may use the renameColumn method on the Schema
builder. Before renaming a column, be sure to add the doctrine/dbal
dependency to your composer.json file:
Schema::table('users', function ($table) {
$table->renameColumn('from', 'to');
});
This mean that I have to insert this code to the last migration file or to create a new migration file?
Most common practice is to generate new migrations for changes. Compare workflows:
When creating new migration:
rails g migration ...
rake db:migrate
When editing existing:
rake db:rollback # you should not forget to execute it first; also, data may be lost
edit migration
rake db:migrate
Restore data if it was lost on first step
Also, when you work in team, each member should process these steps, too. Just too much noise, better to generate new migration.
To make it clear let's make classic example - User and Post.
Creating db schema in Symfony2 is clean and simple:
we create entities Post and User
additionaly we can simply add columns/indexes to each.
then just add value with OneToMany annotation in User and ManyToOne in Post
..well, that's it. Now if we run db:schema:update --force and we can get what we want - database schema and simple adding another rows in database.
What about Laravel4? So far only solution I found:
create/generate Post and User models
declare in each model which table it refers to
create migrations and in Post migration add foregin key to user_id column
run migration
add in each model methods in which we refer to the other model (hasMany, belongsTo .. )
As I wrote it, it doesn't seem so complicated, but it's not so concentrated in Laravel as it is in Symfony. I'm kinda lazy person and I really enjoy the process in Symfony, while in Laravel it is a little bit too diffuse. Is there any simpler ( lazier :P ) way to do this in Laravel? Something like creating schema based on Model?
The question makes sense but unfortunately there isn't such functionality on Laravel at the moment.
As opposed to running migrations from your models (symfony) you must create the migrations first, the you can use the models to seed database tables if they have foreign keys.
I use the Jeffrey Way Generators https://github.com/JeffreyWay/Laravel-4-Generators
to speed up the process so for example if I have a users table and a profile table (many to many) then I would perform these tasks on command line:
php artisan generate:migration create_users_table --fields="username:string, password:string, email:string"
php artisan generate:migration create_profiles_table --fields="name:string, lastname:string, phone:string"
php artisan migrate
php artisan generate:pivot users profiles
php artisan migrate
Then you can create your models (you can also generate an entire CRUD resource or Scaffold)
php artisan generate:model user
php artisan generate:model profile
Then in your User Model
public function profile()
{
return $this->belongsToMany('Profile');
}
In your Profile Model
public function user()
{
return $this->belongsToMany('User');
}
Yes, there are some plugins / commands that speed up the development.
For example Jeffrey Way's Laravel-4-Generators
I'm currently building a new application which runs on an existing database - which is already in production. This new app is built in Laravel 4 and has a few migrations to make schema changes that are required.
Requirements are to use Percona Toolkits pt-online-schema-change to issue schema changes, however I cannot find anywhere how to use this from within a migration - just the standard CLI interface. I need some way to tie together the schema change within the migration and pt-online-schema-change.
I don't want to loose all the benefits that come with writing migrations or using the Laravel schema builder. I was hoping there is a simple way I'm not seeing to use Percona Toolkit within them. I have thought of using exec() but I'd prefer to avoid this if possible.
When "Googling" periodically over the past few weeks, I could not find anything which resembles using Percona Toolkit within a migration. Surely this is a problem that has been solved already?
If my approach is flawed, please tell me! :)
You probably will be able to execute it like this in your migrations:
public function up()
{
exec('pt-online-schema-change --alter "ADD COLUMN c1 INT" D=sakila,t=actor', $output, $return);
if ( ! $return) {
throw \Exception('Error migrating '.__FILE__);
}
}