matheus-carvalho/crud-generator 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

matheus-carvalho/crud-generator

Composer 安装命令:

composer require matheus-carvalho/crud-generator

包简介

Generate a CRUD with Model, Controller, routes, FormRequest and views based on given Migration.

README 文档

README

Crud Generator provides a complete experience of develop an entire CRUD only writing the migration file.

Installing via Composer

composer require matheus-carvalho/crud-generator

Publish the CSS and Config folder

php artisan vendor:publish

Usage

  1. Create your migration and fill up the fields.
  2. Open a cmd on project root and type:
php artisan generate:crud table_name ResourceName

Simple example

  1. Creating the migration.
php artisan make:migration create_categories_table
  1. Filling up the migration.
public function up()
{
    Schema::create('categories', function (Blueprint $table) {
        $table->id();

        $table->string('name');
        $table->text('description')->nullable();

        $table->timestamps();
    });
}
  1. Generating the CRUD.
php artisan generate:crud categories Category

Available column types example

  1. Creating the migration.
php artisan make:migration create_awesome_products_table
  1. Filling up the migration.
public function up()
{
    Schema::create('awesome_products', function (Blueprint $table) {
        $table->id();

        $table->string('name');
        $table->text('description');
        $table->double('price');
        $table->integer('quantity')->nullable();
        $table->dateTime('best_before')->nullable();
        $table->date('production_date')->nullable();
        $table->time('production_time')->nullable();
        $table->boolean('is_active');
        $table->foreignId('category_id')->constrained()->cascadeOnDelete();

        $table->timestamps();
    });
}
  1. Generating the CRUD.
php artisan generate:crud awesome_products AwesomeProduct

Tips

  • The combination of foreignId() and constrained() methods is essential to make foreign keys work.
  • The cascadeOnDelete() method is optional.
  • Take note on snake_case naming pattern.

Options

Option params Description
table string Table name (snake_case).
resource string Resource name (PascalCase) which will be used to name all files.
--style [default, none] Specifies the style. Default = default.
--language [br, en] Specifies the language. Default = en.

Configs

After you had published the css and config folders, you can navigate to config/crudgenerator.php and edit some configs, they are:

Config Default Description
language en Specifies the language of texts inside the files. Accepts 'br' for 'Português brasileiro' or 'en' for 'English'.
style default Specifies the style of views. Accepts 'default' for default css file or 'none' for raw html.
pagination_per_page 5 Specifies the number of elements should be rendered on each page at index's table. Accepts any positive value.
  • After you edit any config, please be sure of run the php artisan config:cache command to apply your changes.

Output

After running the php artisan generate:crud awesome_products AwesomeProduct command, you'll be able to find these files in your project:

App\Http\Controllers\AwesomeProductController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\AwesomeProductRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
use App\Models\AwesomeProduct;
use App\Models\Category;

class AwesomeProductController extends Controller
{
	public function index(): View
	{
		$perPage = 5;
		$items = AwesomeProduct::paginate($perPage);
		return view('awesome_product.index', compact('items'));
	}

	public function create(): View
	{
		$categoryList = Category::all();
		return view('awesome_product.create', compact('categoryList'));
	}

	public function edit($id): View
	{
		$item = AwesomeProduct::find($id);
		$categoryList = Category::all();
		return view('awesome_product.create', compact('categoryList', 'item'));
	}

	public function store(AwesomeProductRequest $request): RedirectResponse
	{
		$data = $request->validated();
		$insert = AwesomeProduct::create($data);
		if (!$insert) {
			return redirect()->back()->with('error', 'Error inserting AwesomeProduct');
		}

		return redirect()->route('indexAwesomeProduct')->with('message', 'AwesomeProduct inserted successfully');
	}

	public function update(AwesomeProductRequest $request, int $id): RedirectResponse
	{
		$data = $request->validated();

		$item = AwesomeProduct::find($id);
		$update = $item->update($data);
		if (!$update) {
			return redirect()->back();
		}

		return redirect()->route('indexAwesomeProduct');
	}

	public function destroy(int $id): RedirectResponse
	{
		$item = AwesomeProduct::find($id);
		$delete = $item->delete();
		if (!$delete) {
			return redirect()->back()->with('error', 'Error deleting AwesomeProduct');
		}

		return redirect()->route('indexAwesomeProduct')->with('message', 'AwesomeProduct deleted successfully');
	}
}
App\Models\AwesomeProduct.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * @method static find($id)
 * @method static create(array $data)
 * @method static paginate(int $perPage)
 */
class AwesomeProduct extends Model
{
	protected $table = 'awesome_products';

	protected $fillable = [
		'name',
		'description',
		'price',
		'quantity',
		'best_before',
		'production_date',
		'production_time',
		'is_active',
		'category_id'
	];

	public static $notNullableBooleans = [
		'is_active'
	];

	public function Category(): BelongsTo
	{
		return $this->belongsTo('App\Models\Category', 'category_id', 'id');
	}
}
App\Http\Requests\AwesomeProductRequest.php
<?php

namespace App\Http\Requests;

use App\Models\AwesomeProduct;
use Illuminate\Foundation\Http\FormRequest;

class AwesomeProductRequest extends FormRequest
{
	/**
	 * Determine if the user is authorized to make this request.
	 *
	 * @return bool
	 */
	public function authorize(): bool
	{
		return true;
	}

	public function validationData(): array
	{
		$data = parent::validationData();

		foreach (AwesomeProduct::$notNullableBooleans as $notNullableBoolean) {
			$data[$notNullableBoolean] = $data[$notNullableBoolean] ?? false;
		}

		return $data;
	}

	/**
	 * Get the validation rules that apply to the request.
	 *
	 * @return array
	 */
	public function rules(): array
	{
		return [
			'name' => 'required',
			'description' => 'required',
			'price' => 'required',
			'is_active' => 'required',
			'quantity' => 'nullable',
			'best_before' => 'nullable',
			'production_date' => 'nullable',
			'production_time' => 'nullable',
			'category_id' => 'required|integer|min:1'
		];
	}

	public function messages(): array
	{
		return [
			'required' => 'The :attribute field is required.',
			'min' => 'You must select the :attribute.'
		];
	}
}
routes\web.php
[...]
use App\Http\Controllers\AwesomeProductController;
[...]
Route::get('/awesome-products', [AwesomeProductController::class, 'index'])->name('awesome_products.index');
Route::get('/awesome-products/create', [AwesomeProductController::class, 'create'])->name('awesome_products.create');
Route::get('/awesome-products/edit/{id}', [AwesomeProductController::class, 'edit'])->name('awesome_products.edit');
Route::post('/awesome-products', [AwesomeProductController::class, 'store'])->name('awesome_products.store');
Route::put('/awesome-products/{id}', [AwesomeProductController::class, 'update'])->name('awesome_products.update');
Route::delete('/awesome-products/{id}', [AwesomeProductController::class, 'destroy'])->name('awesome_products.delete');
resources\views\awesome_product\create.blade.php
<link href="{{asset('css/crudgenerator/default.css')}}" rel='stylesheet'>

<title>Create AwesomeProduct</title>

<div class="container">
	<div class="mt-20">
		<ul class="breadcrumb">
			<li><a href="{{ route('awesome_products.index') }}">AwesomeProduct</a></li>
			<li class='active'>Create AwesomeProduct</li>
		</ul>
	</div>
	<form method="post" 
		@if(isset($item))
			action="{{ route('awesome_products.update', $item->id) }}">
			{!! method_field('PUT') !!}
		@else
			action="{{ route('awesome_products.store') }}">
		@endif
		{!! csrf_field() !!}
		<div class="form-group">
			<label for="name">Name</label>
			<input class="form-control" id="name" name="name" value="{{isset($item) ? $item->name : old('name')}}" type="text">
			@error('name')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>
		<div class="form-group">
			<label for="description">Description</label>
			<textarea class="form-control" id="description" name="description">{{isset($item) ? $item->description : old('description')}}</textarea>
			@error('description')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>
		<div class="form-group">
			<label for="price">Price</label>
			<input class="form-control" id="price" name="price" value="{{isset($item) ? $item->price : old('price')}}" type="number" step="0.01">
			@error('price')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>
		<div class="form-group">
			<label for="quantity">Quantity</label>
			<input class="form-control" id="quantity" name="quantity" value="{{isset($item) ? $item->quantity : old('quantity')}}" type="number">
			@error('quantity')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>
		<div class="form-group">
			<label for="best_before">Best before</label>
			<input class="form-control" id="best_before" name="best_before" value="{{isset($item) ? str_replace(' ', 'T', $item->best_before) : old('best_before')}}" type="datetime-local">
			@error('best_before')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>
		<div class="form-group">
			<label for="production_date">Production date</label>
			<input class="form-control" id="production_date" name="production_date" value="{{isset($item) ? $item->production_date : old('production_date')}}" type="date">
			@error('production_date')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>
		<div class="form-group">
			<label for="production_time">Production time</label>
			<input class="form-control" id="production_time" name="production_time" value="{{isset($item) ? $item->production_time : old('production_time')}}" type="time">
			@error('production_time')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>
		<div class="form-group">
			<label for="is_active">Is active</label>
			<input class="form-check-input" id="is_active" name="is_active" type="checkbox" value="true"
				@if(isset($item) && $item->is_active)
					checked
				@endif
			>
			@error('is_active')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>
		<div class="form-group">
			<label for="category_id">Category</label>
			
			<select name="category_id" id="category_id" class="form-control">
				<option value="0">Select the Category</option>
				@foreach($categoryList as $category)
					<option value="{{$category->id}}"
						@if((isset($item) && $category->id == $item->category_id)||$category->id == old('category_id')) selected @endif
					>
						{{$category->name}}
					</option>
				@endforeach
			</select>
			@error('category_id')
				<div class="alert alert-danger">{{ $message }}</div>
			@enderror
		</div>

		<button class="btn btn-success">Save</button>
	</form>
</div>
resources\views\awesome_product\index.blade.php
<link href="{{asset('css/crudgenerator/default.css')}}" rel='stylesheet'>

<title>AwesomeProduct</title>

<div class="container">
	<div class="row justify-content-around align-items-center mt-20">
		<div>
			<p class="list-header">AwesomeProduct List</p>
		</div>
		<div>
			<a href="{{route('awesome_products.create')}}" class="btn btn-success">New &#10004;</a>
		</div>
	</div>
	<div class="row">

	@if (session('message'))
		<div class='alert alert-success w-100'>
			{{ session('message') }}
		</div>
	@endif
	</div>

	<div class="row overflow-auto">
		<table class="list-table table-stripped mt-20 w-100">
			<thead>
				<tr>
					<th>Name</th>
					<th>Description</th>
					<th>Price</th>
					<th>Quantity</th>
					<th>Best before</th>
					<th>Production date</th>
					<th>Production time</th>
					<th>Is active</th>
					<th>Category</th>
					<th>Actions</th>
				</tr>
			</thead>
			<tbody>
			@forelse ($items as $item)
				<tr>
					<td>{{$item->name}}</td>
					<td>{{$item->description}}</td>
					<td>{{$item->price}}</td>
					<td>{{$item->quantity}}</td>
					<td>{{$item->best_before}}</td>
					<td>{{$item->production_date}}</td>
					<td>{{$item->production_time}}</td>
					<td>{{$item->is_active}}</td>
					<td>{{$item->Category->name}}</td>
					<td class="row justify-content-start align-items-center">
						<div class="action-button">
							<a href="{{route('awesome_products.edit', $item->id)}}" class="btn btn-warning" title="Edit"> &#9998; </a>
						</div>
						<div class="action-button">
							<form title="Delete" method="post" action="{{route('awesome_products.delete', $item->id)}}">
								{!! method_field('DELETE') !!} {!! csrf_field() !!}
								<button class="btn btn-danger"> &times; </button>
							</form>
						</div>
					</td>
				</tr>
			@empty <tr> <td colspan="100%">No AwesomeProduct found!</td> </tr>
			@endforelse
			</tbody>
		</table>
		{{$items->links('pagination.crudgenerator')}}
	</div>
</div>
resources\views\pagination\crudgenerator.blade.php
@if ($paginator->hasPages())
	<ul class="pager w-100">
		@if ($paginator->onFirstPage())
			<li class="disabled"><span>← Previous</span></li>
		@else
			<li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">← Previous</a></li>
		@endif

		@foreach ($elements as $element)
			@if (is_string($element))
				<li class="disabled"><span>{{ $element }}</span></li>
			@endif

			@if (is_array($element))
				@foreach ($element as $page => $url)
					@if ($page == $paginator->currentPage())
						<li class="active my-active"><span>{{ $page }}</span></li>
					@else
						<li><a href="{{ $url }}">{{ $page }}</a></li>
					@endif
				@endforeach
			@endif
		@endforeach

		@if ($paginator->hasMorePages())
			<li><a href="{{ $paginator->nextPageUrl() }}" rel="next">Next →</a></li>
		@else
			<li class="disabled"><span>Next →</span></li>
		@endif
	</ul>
	<small class="pager-info">Showing {{$paginator->firstItem()}} to {{$paginator->lastItem()}} of {{$paginator->total()}} results</small>
@endif

统计信息

  • 总下载量: 141
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 23
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 22
  • Watchers: 0
  • Forks: 5
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2022-01-12

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固