• Stars
    star
    114
  • Rank 308,031 (Top 7 %)
  • Language
    PHP
  • License
    MIT License
  • Created over 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A web Setup Wizard for Laravel application.

Laravel Wizard

Latest Version on Packagist Software License GitHub Tests Action Status Style CI Build Status Total Downloads

A web setup wizard for Laravel application.

This package is adapted from smajti1/laravel-wizard.

Laravel wizard main image.

Table of Contents

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 generates the UserWizardController, NameStep, and EmailStep class, and appends 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.php attribute append_route to false.

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 some 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, and start to use the Laravel Wizard.

If you want to get the layout see Laravel UI layouts/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 the 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

To use the database wizard cache driver, you will need a database table to hold the cache data of the wizard. Generate a migration that creates this table, and runs 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 it to your WizardController wizardOptions property:

protected $wizardOptions = [
    'cache' => false,
];

If disabled 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 your wizard controller, you can use the cache, driver, connection, and 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 a 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, and SecondStep has age and phone fields. you can use the data method of step to get step data:

$name = $firstStep->data('name');
// 'Lucas'

$data = $secondStep->data();
// ['age' => '30', 'phone' => '0900111222']

Or you can use the 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 to use another step, you need to use it:

From wizard:

$stepRepo = $wizard->stepRepo();

From step:

$stepRepo = $step->getRepo();

Get the previous step:

$prevStep = $step->prev();
// same as:
$prevStep = $step->getRepo()->prev();

Get the next step:

$prevStep = $step->next();
// same as:
$nextStep = $step->getRepo()->next();

Step repository all can use method detailed reference: 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 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 and can be changed at will.

Save data on another 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 the 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 the 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 the route and not confirm generate step.

php artisan make:wizard User NameStep,EmailStep

Make controller:

The make:wizard:controller command only generates the WizardController, NameStep, and 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 has helped you, please consider Becoming a sponsor to support my work~ and your avatar will be visible on my major projects.

Become a Patron

Credits

License

MIT LICENSE

More Repositories

1

headlessui-float

Easily use Headless UI with Floating UI to position floating elements.
TypeScript
229
star
2

Laravel-shop

(目前沒有維護,僅支持 PHP 7.2) 用 Laravel 5.8 開發的簡易商城,前端介面採用 Bootstrap 4。
PHP
33
star
3

inertia-plugin

The plugin page loader for Inertia.js
TypeScript
23
star
4

inertia-laravel-ssr-head

Simple SSR Head for Inertia.js Laravel. No Headless Chrome, Node.js or PHP V8 Extension.
PHP
18
star
5

laravel-newebpay

Laravel 串接藍新金流套件
PHP
14
star
6

laravel-form-builder-bs4

The Laravel form builder's bootstrap 4 template.
PHP
14
star
7

bootstrap-steps

A simple Bootstrap 4 steps plugin, support mobile client.
SCSS
14
star
8

hexschool-2021-weblayout-tailwindcss

用 Tailwind CSS 刻六角學院 2021 募資網站
Vue
12
star
9

lightning

【依賴過舊,不建議使用】關於我用 Laravel 寫 SPA 卻不寫 API 的那檔事 - 系列範例,使用和 Laravel + Vue.js + Inertia.js + Tailwind CSS 構建的簡易部落格平台。
PHP
10
star
10

readme-anime-list

自動更新 README 追番列表的 GitHub Action 套件
JavaScript
9
star
11

laravel-line-bot

(暫停維護) 在 Laravel 中快速開發 Line Bot
PHP
7
star
12

chatgpt-linebot

ChatGPT (GPT-3.5) LINE 聊天機器人
JavaScript
6
star
13

jquery-plugin-bsModal

bsModal is jQuery plugin, generate bootstrap 4 modal, And crop&upload image modal.
JavaScript
5
star
14

jquery-plugin-c-share

The share to community buttons.
JavaScript
4
star
15

infinite-storage-glitch-docker

Dockerfile
3
star
16

aniGamerPlus-windows

(停止同步更新) 巴哈姆特動畫瘋自動下載工具 Windows 版
3
star
17

headlessui-float-docs

Documentation for Headless UI Float.
Vue
2
star
18

laravel-up

Upgrade your Laravel application from Laravel source git repository.
TypeScript
2
star
19

laravelconf-2021-livewire-inertiajs-slide

Livewire vs Inertia.js | 關於如何選擇全端框架這檔事 簡報
Vue
2
star
20

vscode-settings

My VS Code settings and extensions
2
star
21

bootstrap-vue-arsenic

JavaScript
2
star
22

laravel-form-field-type

Fast set the form fields of the Laravel form builder.
PHP
1
star
23

di-book-example-php

依賴注入:原理、實作與設計模式 - 範例 PHP 版本 (Lucas)
1
star
24

laravel-docs-lang-switch

快速切換 Laravel 文檔語言 的 Tampermonkey 腳本
JavaScript
1
star
25

laravelconf-2021-inertia-example

Inertia.js 範例 - Livewire vs Inertia.js | 關於如何選擇全端框架這檔事
PHP
1
star
26

phptheday-inertiajs-demo-front

Vue
1
star
27

html-css-js-refs

1
star
28

laravel-crud-page

Fast generate CRUD pages, controllers.
PHP
1
star
29

inertia-laravel-ssr-page-cache

1
star
30

laravel-without-api-and-inertiajs-30days

關於我用 Laravel 寫 SPA 卻不寫 API 的那檔事 系列文章
1
star
31

laravel-open-graph

Setting Open Graph for Laravel.
PHP
1
star
32

laravel-glide

Glide image manipulation for Laravel.
PHP
1
star
33

preset

Lucas 的 Presets 集合
TypeScript
1
star
34

bsite-chrome-extension

一個簡易的封鎖頁面 Chrome Extension
TypeScript
1
star
35

bootstrap-admin-layout

A simple Bootstrap 4 admin panel layout component, support mobile client.
JavaScript
1
star
36

youku-m3u8-parser

下載優酷影片小工具 (解析 m3u8 檔、下載影片)
JavaScript
1
star
37

purge-icons-vue

PurgeIcons's vue icon component
JavaScript
1
star
38

phptheday-inertiajs-demo

PHP 也有 Day 56: 前端渲染的後端應用 - 用 Inertia 拉近 Laravel 和 Vue.js 的距離 - 範例
PHP
1
star
39

laravelconf-2021-livewire-example

Livewire 範例 - Livewire vs Inertia.js | 關於如何選擇全端框架這檔事
PHP
1
star
40

star-note-lucas

星星的筆記.Lucas
Vue
1
star