mr-timofey/laravel-admin-api

管理面板的API后端

0.5.4 2020-05-10 11:21 UTC

README

基于 vue-admin-front 包的API后端,用于管理面板。

演示.

要求

  • PHP 7.1
  • Laravel 5

安装

npm i -D vue-admin-front
composer require mr-timofey/laravel-admin-api

遵循依赖包的安装说明:用于图像处理的 mr-timofey/laravel-aio-images,用于授权的 mr-timofey/laravel-simple-tokens

对于 Laravel <= 5.4,将 MrTimofey\LaravelAdminApi\ServiceProvider 添加到您的 app.providers 配置中。

php artisan vendor:publish --provider="MrTimofey\LaravelAdminApi\ServiceProvider"

查看 config/admin_api.php 以获取进一步的包配置说明。

遵循 vue-admin-front 快速入门指南

出于开发目的,您还可以执行 npm i -D concurrently 并将此脚本添加到您的 npm 脚本中

{
	"scripts": {
		"dev": "concurrently --kill-others -n \" api ,admin\" -c \"blue,white\" \"php artisan serve\" \"npm run admin:dev\""
	}
}

它将在端口 8000 上运行开发 PHP 服务器,并在端口 8080 上运行 vue-admin-front 开发服务器。

身份验证和授权

此包使用 mr-timofey/laravel-simple-tokens 维护身份验证和授权逻辑。

您可以通过在 admin_api.api_middlewareadmin_api.api_guard 配置中设置适当的 auth:{guard name} 中间件和守卫名称来更改用于 API 的守卫。

如果您想禁用授权,请删除 auth 中间件。

您还可以通过重新绑定 auth 控制器类来完全替换身份验证和授权逻辑:app()->bind(\MrTimofey\LaravelAdminApi\Http\Controllers\Auth::class, YourController::class)

模型配置

Admin API 将尝试通过使用模型的首字母大写属性名来猜测属性类型并生成字段名

  • $visible 用于获取在实体索引页面上显示的字段列表(如果未显式设置)
  • $fillable 用于获取编辑的字段列表(如果未显式设置)
  • $hidden 字段将接收一个 password 字段类型
  • $dates 字段将接收一个 datetime 字段类型
  • $casts 将直接设置字段类型(不用担心,vue-admin-front 通过别名支持任何 Eloquent 兼容的类型)
  • belongsTo、hasMany 和 belongsToMany 关系将正常工作

您还可以实现一个 MrTimofey\LaravelAdminApi\Contracts\ConfiguresAdminHandler 接口并定义一个 configureAdminHandler($handler) 方法来使事情更具可控性。

可用的字段类型及其选项在 vue-admin-front 字段类型文档 中描述。同样,对于模型索引页面的字段格式化也在 vue-admin-front 显示类型文档 中描述。

使用示例

<?php

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Http\Request;
use MrTimofey\LaravelAdminApi\Contracts\ConfiguresAdminHandler;
use MrTimofey\LaravelAdminApi\ModelHandler;

class Post extends Model implements ConfiguresAdminHandler
{
    protected $casts = [
        'published' => 'bool'
    ];

    public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }

    public function tags(): BelongsToMany
    {
        return $this->belongsToMany(Tag::class);
    }

    public function scopeOnlyDrafts(Builder $q): Builder
    {
        return $q->whereRaw('draft IS TRUE');
    }

    public function configureAdminHandler(ModelHandler $handler): void
    {
        $handler->setTitle('Posts')
            ->setCreateTitle('Creating new post')
            // placeholders can be used, see more: https://mr-timofey.gitbooks.io/vue-admin/placeholders.html
            ->setItemTitle('Editing post #{{ id }}')

            // allow only these methods (everything is allowed by default)
            ->allowActions(['index', 'item', 'create', 'update', 'destroy'])
            // ...or use policies instead
            ->usePolicies(true,
                // optional policy method prefix (Policy::adminActionIndex, Policy::adminActionCreate, etc.)
                'adminAction')

            ->addPreQueryModifier(function(Builder $q, Request $req): void {
                // modify index query just after Model::newQuery() is called
                $user = $req->user();
                if ($user->role !== 'god') {
                    $q->where('author_user_id', $user->getKey());
                }
            })
            ->addPostQueryModifier(function(Builder $q,Request $req): void {
                // modify index query just before execution
                // useful if you want to set default sort order
                $q->orderByDesc('created_at');
            })
            // automatically search with LIKE
            ->setSearchableFields(['title', 'summary'])
            // ...or/and set custom search callback
            ->setSearchCallback(function(
                Builder $q,
                Request $req,
                array $searchableFields): void {
                    $q->searchLikeAGod($req->get('search'));
                })

            // index page filters
            ->setFilterFields([
                // auto relation filter
                'category',
                // see more about available prefix modifiers in ModelHandler::applyFilters phpdoc
                '>~created_at' => [
                    'title' => 'Created after',
                    'type' => 'datetime'
                ],
                // checkbox, applies scopeOnlyDrafts when checked
                'drafts' => [
                    'scope' => 'onlyDrafts',
                    'type' => 'switcher'
                ]
            ])

			// index page table columns
            ->setIndexFields([
                'id',
                'title',
                // will be automatically formatted as datetime if $this->timestamps === true
                // or if $this->dates includes 'created_at' field
                'created_at',
                // you can provide only title this way
                'updated_at' => 'Last update date and time'
            ])

			// item creating/editing form fields
            ->setItemFields([
                'title',
                // this just works
                'category', // categories should be added to api_admin.models config
                // this should just work as well but we want some customizations
                'tags' => [
                    'title' => 'Attach tags',
                    // 'type' => 'relation', // not necessary if field name is same as a relation method
                    // 'entity' => 'tags', // tags should be added to api_admin.models config
                    // placeholders can be used, see more: https://mr-timofey.gitbooks.io/vue-admin/placeholders.html
                    'display' => '{{ name }}',
                    // relation widget will allow user to create new tags in-place
                    'allowCreate' => true,
                    // this field will be filled with the widget's search box input text
                    'createField' => 'name',
                    // fill some other fields with fixed values while creating new tag
                    'createDefaults' => ['description' => 'New tag'],
                    // customize suggestions query
                    'queryParams' => [
                        'sort' => ['sort' => 'asc']
                    ]
                ],
                'content' => ['type' => 'wysiwyg'],
                // $casts => ['published' => 'bool'] will automatically set the right field type for you (checkbox)
                'published'
            ])

            // creating/editing validation rules (use $this to refer to the currently editing model instance)
            ->setValidationRules([
                'tags' => ['array', 'between:3,8'],
                'category' => ['required'],
                'some_unique_field' => [
                    'required',
                    'unique,' . $this->getTable() . ',some_unique_field' .
                    	($this->exists ? (',' . $this->getKey() . ',' . $this->getKeyName()) : '')
				]
            ])
            // ...or/and defined custom validation callback
            ->setValidationCallback(
                /**
                 * @throws \Illuminate\Validation\ValidationException
                 */
                function(
                    \Illuminate\Http\Request $req,
                    array $rules,
                    array $messages,
                    // gathered from item fields configuration
                    array $titles
                ) {
                    $req->validate([ /* whatever */ ]);
                })
			// override default error messages
            ->setValidationMessages([
                'category.required' => 'No category - no post'
            ]);
    }
}

事件

行政面板内的每个操作都可以通过 Laravel 的事件系统进行跟踪和处理。可用事件

<?php

namespace MrTimofey\LaravelAdminApi\Events;

// abstract base class for all events (holds user identifier)
ModelEvent::class;

// single model instance action events
SingleModelEvent::class; // abstract base class for single model instance action events (holds item identifier)
ModelCreated::class;
ModelUpdated::class; // holds attributes changes, more info in phpdoc of this class
ModelDestroyed::class;

// bulk destroy (holds destroyed instances' identifiers)
BulkDestroyed::class;

跟踪 ModelUpdated 事件的更改

默认情况下,ModelUpdated 将仅跟踪实例属性(使用 Eloquent 的 Model::getDirty() 方法)和关系更改。

您可以通过实现 MrTimofey\LaravelAdminApi\Contracts\HasCustomChanges 接口并定义 getCustomChanges() 方法来丰富 ModelUpdated::$changes 字段,以跟踪您想要跟踪的任何附加信息。默认格式是返回数组 ['field_name' => [$oldValue, $newValue], ...]