laravel-wizard
laravel-wizard copied to clipboard
A web Setup Wizard for Laravel application.
Laravel Wizard
A web setup wizard for Laravel application.
This package is adapted from smajti1/laravel-wizard.

Table of Contents
- Laravel Wizard
- Table of Contents
- Version Compatibility
- Install
- Usage
- 1. Generate controller and wizard steps
- 2. Set steps
- 3. Install wizard steps CSS package
- Cache
- Database Driver
- Disable Cache
- Controller
- Setting Configuration
- Customize View
- Step
- Get cached data
- Step repository
- Upload Files
- Skip step
- Passing data to views
- Save data on other step
- Set relationships model
- Commands
- Sponsor
- Credits
- License
Version Compatibility
| Laravel Wizard | Laravel | PHP |
|---|---|---|
| 1.0.x | 5.5 | ^7.0 |
| 1.1.x | ^5.6 | ^7.1.3 |
| 2.0.x,2.1.x | ^5.6|^6.x | ^7.1.3 |
| 2.2.x | ^5.6|^6.x|^7.x | ^7.1.3 |
| 2.3.x | >=5.6 | >=7.1.3 |
Install
Via Composer:
composer require ycs77/laravel-wizard
Publish config:
php artisan vendor:publish --tag=wizard-config
Usage
1. Generate controller and wizard steps
Now you can quickly generate the wizard controller and the wizard steps:
php artisan make:wizard User NameStep,EmailStep
This command generate the UserWizardController, NameStep, EmailStep class, and append the wizard route to routes/web.php.
routes/web.php
use App\Http\Controllers\UserWizardController;
use Illuminate\Support\Facades\Route;
use Ycs77\LaravelWizard\Facades\Wizard;
...
Wizard::routes('wizard/user', UserWizardController::class, 'wizard.user');
If you can't use auto append route, you can set
config/wizard.phpattributeappend_routetofalse.
2. Set steps
This is generated NameStep class, you can to model method set the model, to rules method set form validation, and save $data to your database via the saveData method, for example:
app/Steps/User/NameStep.php
<?php
namespace App\Steps\User;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Ycs77\LaravelWizard\Step;
class NameStep extends Step
{
/**
* The step slug.
*
* @var string
*/
protected $slug = 'name';
/**
* The step show label text.
*
* @var string
*/
protected $label = 'Name';
/**
* Set the step model instance or the relationships instance.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Relations\Relation|null
*/
public function model(Request $request)
{
return User::find(1);
}
/**
* Save this step form data.
*
* @param \Illuminate\Http\Request $request
* @param array|null $data
* @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Relations\Relation|null $model
* @return void
*/
public function saveData(Request $request, $data = null, $model = null)
{
$data = Arr::only($data, 'name');
$model->update($data);
}
/**
* Validation rules.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function rules(Request $request)
{
return [
'name' => 'required',
];
}
}
And add steps view, for example:
resources/views/steps/user/name.blade.php
<div class="form-group mb-3">
<label for="name">Name</label>
<input type="text" name="name" id="name" class="form-control {{ $errors->has('name') ? 'is-invalid' : '' }}" value="{{ old('name') ?? $step->data('name') }}">
@if ($errors->has('name'))
<span class="invalid-feedback">{{ $errors->first('name') }}</span>
@endif
</div>
resources/views/steps/user/email.blade.php
<div class="form-group mb-3">
<label for="email">E-mail</label>
<input type="email" name="email" id="email" class="form-control {{ $errors->has('email') ? 'is-invalid' : '' }}" value="{{ old('email') ?? $step->data('email') }}">
@if ($errors->has('email'))
<span class="invalid-feedback">{{ $errors->first('email') }}</span>
@endif
</div>
Next, browse the URL /wizard/user, start use the Laravel Wizard.
If you want to get the layout see Laravel UI alyouts/app.blade.php.
3. Install wizard steps CSS package
The CSS for this package default view is based on the Bootstrap Steps, use NPM installation to use:
npm install bootstrap bootstrap-steps
// or Yarn
yarn add bootstrap bootstrap-steps
Import to app.scss file and run npm run dev or yarn run dev:
resources/sass/app.scss
...
@import '~bootstrap/scss/bootstrap';
@import '~bootstrap-steps/scss/bootstrap-steps';
Cache
Database Driver
In order to use the database wizard cache driver, you will need a database table to hold the wizards cache data. To generate a migration that creates this table, run the wizard:table Artisan command:
php artisan wizard:table
php artisan migrate
Disable Cache
Set cache in config/wizard.php to false to disable cache input data:
'cache' => false,
Or set to your WizardController wizardOptions property:
protected $wizardOptions = [
'cache' => false,
];
If disable cache, the data will be saved in the data immediately after each step is sent. If you are afraid to save the data repeatedly, you can hide the Prev button, or use Model::updateOrCreate() (https://laravel.com/docs/6.x/eloquent#other-creation-methods).
Controller
Setting Configuration
Add wizardOptions property to controller, you can use cache, driver, connection, table options to override configuration.
app/Http/Controllers/UserWizardController.php
/**
* The wizard options.
*
* @var array
*/
protected $wizardOptions = [
'cache' => true,
'driver' => 'session',
'table' => 'wizards',
];
Customize View
This package layout view uses Bootstrap 5, but if you don't want to use default views, you can publish views to custom it:
php artisan vendor:publish --tag=wizard-views-bs5
If you used Bootstrap 4, you could publish the layouts:
php artisan vendor:publish --tag=wizard-views-bs4
If you used Tailwind CSS, you could publish the layouts:
php artisan vendor:publish --tag=wizard-views-tailwind
Now you can customize resources/views/vendor/wizard/*.blade.php in your laravel project.
But if you want custom-only one wizard view base view, you can copy the views from resources/views/vendor/wizard/*.blade.php to resources/views/wizards/user/*.blade.php. (user is wizardName property value on your wizard controller),
Step
Get cached data
For example, FirstStep has name and email fields, SecondStep has age and phone fields. you can use step's data method to get step data:
$name = $firstStep->data('name');
// 'Lucas'
$data = $secondStep->data();
// ['age' => '30', 'phone' => '0900111222']
Or you can use Step repository to get other step data:
$data = $secondStep->find('first')->data();
// ['name' => 'Lucas']
$name = $secondStep->find('first')->data('name');
// 'Lucas'
Step repository
Step repository saves all steps data, if you want use other step, you need to use it:
From wizard:
$stepRepo = $wizard->stepRepo();
From step:
$stepRepo = $step->getRepo();
Get previous step:
$prevStep = $step->prev();
// same as:
$prevStep = $step->getRepo()->prev();
Get next step:
$prevStep = $step->next();
// same as:
$nextStep = $step->getRepo()->next();
Step repository all can use method detailed reference: https://github.com/ycs77/laravel-wizard/blob/v2.x/src/StepRepository.php
Upload Files
Since v2.3.3 upload files in Cache and No Cache are supported, if use the Cache Mode you can cache all input data and uploaded files to save in the last step:
<?php
class LastStep extends Step
{
public function model(Request $request)
{
return $request->user();
}
public function saveData(Request $request, $data = null, $model = null)
{
$data = [
'avatar' => $this->find('has-avatar-step')->data('avatar'),
];
$data['avatar'] = $data['avatar']->store('avatar', ['disk' => 'public']);
$model->update($data);
}
}
Then add a step view to upload the avatar image:
resources/views/steps/user/has-avatar.blade.php
<div class="form-group mb-3">
<label for="avatar">Avatar</label>
<input type="file" name="avatar" id="avatar" class="form-control">
<div class="form-control d-none {{ $errors->has('avatar') ? 'is-invalid' : '' }}"></div>
@if ($errors->has('avatar'))
<span class="invalid-feedback">{{ $errors->first('avatar') }}</span>
@endif
</div>
Skip step
Note: v2.3.3+
To make Step skippable, set the $skip property to true, then this Step will be skip the validation and save data:
app/Steps/User/NameStep.php
<?php
class NameStep extends Step
{
/**
* Is it possible to skip this step.
*
* @var boolean
*/
protected $skip = true;
}
Passing data to views
Because each step is injected into the view of the step, so just add the method to return the data in the step class. For example, pass the data of the select options to view:
app/Steps/User/NameStep.php
<?php
class NameStep extends Step
{
public function getOptions()
{
return [
'Taylor',
'Lucas',
];
}
}
resources/views/steps/user/name.blade.php
<div class="form-group mb-3">
<label for="name">Select name</label>
<select id="name" name="name" class="form-control {{ $errors->has('name') ? 'is-invalid' : '' }}">
<option value="">Select...</option>
@foreach ($step->getOptions() as $option)
<option value="{{ $option }}" @if (old('name') ?? $step->data('name') === $option) @endif>{{ $option }}</option>
@endforeach
</select>
@if ($errors->has('name'))
<span class="invalid-feedback">{{ $errors->first('name') }}</span>
@endif
</div>
The getOptions method is custom, can be changed at will.
Save data on other step
Suppose there are now two Steps NameStep and EmailStep.
First, don't set the Model for all Steps, but don't use the last one:
app/Steps/User/NameStep.php
<?php
class NameStep extends Step
{
public function model(Request $request)
{
//
}
public function saveData(Request $request, $data = null, $model = null)
{
//
}
}
Next, receive all the data in the last Step and save Model:
app/Steps/User/EmailStep.php
<?php
class EmailStep extends Step
{
public function model(Request $request)
{
return new User();
}
public function saveData(Request $request, $data = null, $model = null)
{
$data = $this->getStepsData();
$model->fill($data)->save();
}
}
Set relationships model
Similarly, you can set the relationships model in model method of the Step.
use Illuminate\Support\Arr;
/**
* Set the step model instance or the relationships instance.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Relations\Relation|null
*/
public function model(Request $request)
{
return $request->user()->posts();
}
/**
* Save this step form data.
*
* @param \Illuminate\Http\Request $request
* @param array|null $data
* @param \Illuminate\Database\Eloquent\Model\Illuminate\Database\Eloquent\Relations\Relation|null $model
* @return void
*/
public function saveData(Request $request, $data = null, $model = null)
{
$data = Arr::only($data, ['title', 'content']);
$model->create($data);
}
Commands
Make wizard:
The make:wizard command and make:wizard:controller command difference, is make:wizard command will append route and no confirm generate step.
php artisan make:wizard User NameStep,EmailStep
Make controller:
The make:wizard:controller command only generate the WizardController, NameStep, EmailStep class.
php artisan make:wizard:controller UserController --steps=NameStep,EmailStep
Make step:
php artisan make:wizard:step NameStep
With step label and wizard:
php artisan make:wizard:step NameStep --label="Name" --slug=name --wizard=user
Add custom view path:
php artisan make:wizard:step NameStep --label="Name" --slug=name --view=steps.user.name --wizard=user
Sponsor
If you think this package have helped you, please consider Become a sponsor to support my work~ and your avatar will be visible on my major projects.
Credits
License
MIT LICENSE