Blueprint is an open-source tool for rapidly generating multiple Laravel components from a single, human readable definition.
Watch a quick demo of Blueprint in action and continue reading this document to get started.
You can install Blueprint via composer using the following command:
composer require --dev laravel-shift/blueprint
Blueprint will automatically register itself using package discovery.
Blueprint requires a Laravel application running version 6.0 or higher.
While Blueprint may be more flexible in a future version, it currently assumes a standard project structure using the default App
namespace.
Blueprint adds multiple artisan commands. The most commonly used command is the blueprint:build
command to generate the Laravel components:
php artisan blueprint:build [draft]
The draft file contains a definition of the components to generate. By default, the blueprint:build
command attempts to load a draft.yaml
file from the project root folder.
Use Blueprint's artisan
commands you may generate multiple Laravel components from a single definition called a draft file.
Within this draft file you define models and controllers using an expressive, human-readable YAML syntax.
Let's review the following draft file:
models:
Post:
title: string:400
content: longtext
published_at: nullable timestamp
controllers:
Post:
index:
query: all
render: post.index with:posts
store:
validate: title, content
save: post
send: ReviewNotification to:post.author with:post
dispatch: SyncMedia with:post
fire: NewPost with:post
flash: post.title
redirect: post.index
From these simple 20 lines of YAML, Blueprint will generate all of the following Laravel components:
- A model class for
Post
complete withfillable
,casts
, anddates
properties, as well as relationships methods. - A migration to create the
posts
table. - A factory intelligently setting columns with fake data.
- A controller class for
PostController
withindex
andstore
actions complete with code generated for each statement. - Routes for the
PostController
actions. - A form request of
StorePostRequest
validatingtitle
andcontent
based on thePost
model definition. - A mailable class for
ReviewNotification
complete with apost
property set through the constructor. - A job class for
SyncMedia
complete with apost
property set through the constructor. - An event class for
NewPost
complete with apost
property set through the constructor. - A Blade template of
post/index.blade.php
rendered byPostController@index
.
While this draft file only defines a single model and controller, you may define multiple models and controllers.
Within the models
section of a draft file you may define multiple models. Each model begins with a name followed by a list of columns. Columns are key: value
pairs where key
is the column name and value
defines its attributes.
Expanding on the example above, this draft file defines multiple models:
models:
Post:
title: string:400
content: longtext
published_at: nullable timestamp
Comment:
content: longtext
published_at: nullable timestamp
# additional models...
From this definition, Blueprint creates two models: Post
and Comment
, respectively. You may continue to define additional models.
Blueprint recommends defining the model name in its StudlyCase, singular form to follow Laravel naming conventions. For example, Post
instead of post
or posts
.
Similarly, column names will be used as-is. The attributes of these columns may be any of the column types and column modifiers available in Laravel. You may define these as-is or using lowercase.
For complex attributes, you may use a key:value
pair. From these example above, string:400
defines a string
column type with a maximum length of 400
characters. Other examples include enum:'foo','bar','baz'
or decimal:10,2
.
By default, each model will automatically be defined with an id
and timestamps columns. To disable these columns you may define them with a false
value. For example, timestamps: false
.
Blueprint also offers additional shorthands which will be expanded into valid YAML. Shorthands include an id
data type, as well as defining soft deleting models.
For example:
models:
Comment:
user_id: id
softDeletes
# ...
Using these shorthands, Blueprint will generate a Comment
class using the SoftDeletes
trait. It will also create a user_id
column with the appropriate data type for an integer foreign key.
Blueprint also inspects columns and assigns them to fillable
, casts
, and dates
properties, as well as generate relationships methods.
By default, all columns except for id
and timestamps will be added to the fillable
property.
Where appropriate, Blueprint will cast columns to integer
, boolean
, and decimal
types. Any date columns will be added to the dates
properties.
Columns which use an id
data type or end with _id
will be used to generate belongsTo
relationships. By default, Blueprint uses the column name prefix for the related model. If you define a relationship for a different model, you may use a id:model
syntax.
For example:
models:
Post:
author_id: id:user
# ...
Similar to models
, you may also define multiple controllers
. Within the controllers
section you define a controller by name. Each controller may define multiple actions
which contain a list of statements.
Expanding on the example above, this draft file defines multiple controllers:
controllers:
Post:
index:
query: all
render: post.index with:posts
create:
render: post.create
store:
validate: title, content
save: post
redirect: post.index
Comment:
show:
render: comment.show with:show
# additional controller...
From this definition, Blueprint will generate two controllers. A PostController
with index
, create
, and store
actions. And a CommentController
with a show
action.
While you may specify the full name of a controller, Blueprint will automatically suffix names with Controller
.
Blueprint encourages you to define resource controllers. Doing so allows Blueprint to infer details and generate even more code automatically.
Blueprint comes with an expressive set of statements which implicitly define additional components to generate. Each statement is a key: value
pair.
The key
defines the type of statement to generate. Currently, Blueprint supports the following types of statements:
- validate
-
Generates a form request with rules based on the referenced model definition. Blueprint accepts a
value
containing a comma separated list of column names.For example:
validate: title, content, author_id
Blueprint also updates the type-hint of the injected request object.
- find
-
Generates an Eloquent
find
statement. If thevalue
provided is a qualified reference, Blueprint will expand the reference to determine the model. Otherwise, Blueprint will attempt to use the controller to determine the related model. - query
-
Generates an Eloquent query statement using
key:value
pairs provided invalue
. Keys may be any of the basic query builder methods forwhere
clauses and ordering.For example:
query: where:title where:content order:published_at limit:5
Currently, Blueprint supports generating query statements for
all
,get
,pluck
, andcount
. - save/delete
-
Generates an Eloquent statement for saving a model. Blueprint uses the controller action to infer which statement to generate.
For example, for a
store
controller action, Blueprint will generate aModel::create()
statement. Otherwise, a$model->save()
statement will be generated.Similarly, within a
destroy
controller action, Blueprint will generate a$model->delete()
statement. Otherwise, aModel::destroy()
statement will be generated. - flash
-
Generates a statement to flash data to the session. Blueprint will use the
value
as the session key and expands the reference as the session value.For example:
flash: post.title
- render
- Generates a `return view();` statement complete with a template reference and data.
For example:
view: post.show with:post
When the template does not exist, Blueprint will generate the Blade template for the view.
- redirect
- Generates a `return redirect()` statement using the `value` as a reference to a named route passing any data as parameters.
For example:
redirect: post.show with:post
- dispatch
-
Generates a statement to dispatch a Job using the
value
to instantiate an object and pass any data.For example:
dispatch: SyncMedia with:post
If the referenced job class does not exist, Blueprint will create one using any data to define properties and a
__construct
method which assigns them. - fire
-
Generates a statement to dispatch a Event using the
value
to instantiate the object and pass any data.For example:
fire: NewPost with:post
If the referenced event class does not exist, Blueprint will create one using any data to define properties and a
__construct
method which assigns them. - send
-
Generates a statement to send a Mailable using the
value
to instantiate the object, specify the recipient, and pass any data.For example:
send: ReviewNotification to:post.author with:post
If the referenced mailable class does not exist, Blueprint will create one using any data to define properties and a
__construct
method which assigns them.
For convenience, Blueprint will use the name of a controller to infer the related model. For example, Blueprint will assume a PostController
relates to a Post
model.
Blueprint also supports a dot (.
) syntax for more complex references. This allows you to define values which reference columns on other models.
For example, to find a User
model within the PostController
you may use:
controllers:
Post:
show:
find: user.id
# ...
While these references will often be used within Eloquent and query
statements, they may be used in other statements as well. When necessary, Blueprint will convert these into variable references using an arrow (->
) syntax.
Beyond the blueprint:build
command, Blueprint provides additional commands:
- blueprint:erase
-
Erases the components created by the last build and warns about any updated components.
While this command is helpful, it's better to run the
blueprint:build
command from a clean working state and use Git commands likereset
andclean
to undo the last build. - blueprint:trace
-
Loads definitions for existing models into the Blueprint cache file (
.blueprint
) so you may reference them in your draft file.
Contributions may be made by submitting a Pull Request against the master
branch. Any submissions should be complete with tests and adhere to the PSR-2 code style.
You may also contribute by opening an issue to report a bug or suggest a new feature.