Developing extensions

Dcat Admin supports the installation of extensions to help enrich your backend functionality.

It should be noted that the original extensions for Laravel Admin cannot be used directly in Dcat Admin, but most of them can be used with a few minor tweaks and can be migrated.

If you want to add your own features or components to Dcat Admin, you can make a Dcat Admin extension to help other users of Dcat Admin, and improve the quality of the extension in the feedback from others.

In this document, we will take developing an Operation Log Extension as an example to teach you how to develop an extension step by step, and distribute it to others to use. dcat-admin/operation-log).

Before you start

Before you start developing extensions, if you are in a linux environment, please create a dcat-admin-extensions directory in the project root directory manually and set readable writeable permissions, the extensions will be installed in the dcat-admin-extensions directory.

  1. ProjectDirectory/dcat-admin-extensions extension installation directory, which can be changed according to the configuration parameter admin.extensions.dir
  2. public/vendor extends the static resource distribution directory
  3. resources/lang language package directory

1. Create extensions

The Dcat Admin extension is a standard composer extension package that can be installed via composer or directly via the system’s internal local installation feature. We can create a new extension by command or by interface.

  1. Create extensions by command
  1. php artisan admin:ext-make ExtensionPackageName --namespace=namespace --theme

Command parameter description

  • name extension package name, the extension name is a standard composer package name, please uniformly use lowercase letters + centerline (-) style naming, standard format such as dcat-admin/operation-log, the first part can be a personal name, the second part can be to the extension package General words for the function
  • --namespace= Extended package namespace, automatically generated by default according to the package name, e.g. your package name is jiangqh/operation-log, then the default namespace is Jiangqh/OperationLog.
  • --theme whether it is a theme extension or not

So in the current example we run the command to generate the extensions

  1. # `--namespace`
  2. php artisan admin:ext-make dcat-admin/operation-log --namespace="Dcat\Admin\OperationLog"
  1. Create extensions from the administration page

Open the extension management page http://localhost/admin/auth/extensions, then click on the table below the first line of the quickly create , and then enter the extension package name and namespace can be, in the actual development is also more recommended to use the interface to create extensions, so more convenient!

After the extension is created, you can see an additional directory dcat-admin/extensions/dcat-admin/operation-log in the extension folder:

  1. ├── README.md
  2. ├── composer.json # composer configuration file
  3. ├── version.php # Extension Package Version Management Document
  4. ├── logo.png # logo
  5. ├── updates # Table migration files for each version of the extension package
  6. ├── resources
  7. ├── lang # language pack
  8. ├── assets # static resource
  9. ├── css
  10. └── index.css # css sample file
  11. └── js
  12. └── index.js # js sample file
  13. └── views
  14. └── index.blade.php # View sample file
  15. └── src
  16. ├── OperationLogServiceProvider.php # Extension package service provider
  17. ├── Setting.php # Extension Settings Form
  18. ├── Models # Model Directory
  19. └── Http
  20. ├── routes.php # Extension Routing File
  21. ├── Middleware # Extensions Middleware Directory
  22. └── Controllers # Extensions Controller Directory
  23. └── OperationLogController.php

Then you can also set the extension’s logo and the extension name, which will be displayed on the extension management page after you set it, making your extension more memorable!

Extension logo

The extension logo must be placed in the extension’s root directory, and the file name must be logo.png, with a recommended size of 100x100.

Extension name

The extension name needs to be modified with the alias parameter in composer.json, if not set then the package name is displayed by default

2. Enable extensions

Once the extension has been created, you can see the newly created extension on the admin page http://localhost/admin/auth/extensions as follows

Developing extensions - 图1

Then we click on the Update to version 1.0.0 and Enable buttons for the extension to make this extension work. The newly created extension will generate a default controller, in this example we can try to access http://localhost:8000/admin/operation-log, if it works then the extension is enabled for success.

3. Functional development

The main function of this extension is to record the user’s operation records, and then provide a page to view the records, and then we can create the default extension file to clean up the unused, clean up the directory structure as follows

  1. ├── README.md
  2. ├── composer.json # composer configuration file
  3. ├── version.php # Extension Package Version Management Document
  4. ├── logo.png # logo
  5. ├── updates # Table migration files for each version of the extension package
  6. ├── resources
  7. └── lang # language pack
  8. └── src
  9. ├── OperationLogServiceProvider.php # Extension package service provider
  10. ├── Setting.php # Extension Settings Form
  11. ├── Models # Model Directory
  12. └── Http
  13. ├── routes.php # Extension Routing File
  14. ├── Middleware # Extensions Middleware Directory
  15. └── Controllers # Extensions Controller Directory
  16. └── OperationLogController.php

Now let’s get down to the business of feature development.

Create migration file (migration)

First we need to create a table migration file, run the command php artisan make:migration CreateOperationLogTable, and then write the contents of the file as follows

  1. <?php
  2. use Illuminate\Database\Migrations\Migration;
  3. use Illuminate\Database\Schema\Blueprint;
  4. use Illuminate\Support\Facades\Schema;
  5. class CreateOperationLogTable extends Migration
  6. {
  7. // Here you can specify your database connection
  8. public function getConnection()
  9. {
  10. return config('database.connection') ?: config('database.default');
  11. }
  12. public function up()
  13. {
  14. if (! Schema::hasTable('admin_operation_log')) {
  15. Schema::create('admin_operation_log', function (Blueprint $table) {
  16. $table->bigIncrements('id')->unsigned();
  17. $table->bigInteger('user_id');
  18. $table->string('path');
  19. $table->string('method', 10);
  20. $table->string('ip');
  21. $table->text('input');
  22. $table->index('user_id');
  23. $table->timestamps();
  24. });
  25. }
  26. }
  27. public function down()
  28. {
  29. Schema::dropIfExists('admin_operation_log');
  30. }
  31. }

Then move the file to the updates directory and rename it to create_opration_log_table.php. Finally, we need to modify the `version.php extension’s version management file to include the name of the migration file:

  1. <?php
  2. return [
  3. '1.0.0' => [
  4. 'Version Change Description 1',
  5. 'Version Change Description 2',
  6. 'create_opration_log_table.php', // Migrate file names and automatically run when installing or updating versions.
  7. ],
  8. ];

For a more detailed description of versioning for extensions, go to the Extensions - Versioning section.

Models, Controllers, and Routing

Create the model file extended directory /src/Models/OperationLog and click on OperationLog.php for the model contents. OperationLog.php) view.

Then modify our controller extension directory /src/Http/Controllers/OperationLogController.php by clicking on LogController.php. operation-log/blob/master/src/Http/Controllers/LogController.php) view.

Finally, our routing file needs to be modified so that your route does not conflict with other routes as much as possible.

  1. use Dcat\Admin\OperationLog\Http\Controllers;
  2. use Illuminate\Support\Facades\Route;
  3. Route::get('auth/operation-logs', Controllers\OperationLogController::class.'@index')->name('dcat-admin.operation-log.index');
  4. Route::delete('auth/operation-logs/{id}', Controllers\OperationLogController::class.'@destroy')->name('dcat-admin.operation-log.destroy');

Language packs

In this example, we take en and zh_CN as examples, create en/log.php and zh_CN/log.php files in extensions/resources/lang directory, and write the following content

  1. // en
  2. return [
  3. 'title' => 'Operation Log',
  4. 'setting_title' => 'Operation Log',
  5. ];
  6. // zh_CN
  7. return [
  8. 'title' => '操作日志',
  9. 'setting_title' => '操作日志',
  10. ];

Finally, the contents of the language pack can be accessed from the controller in the following way, for more information on multilingualism you can refer to the official lavel documentation

  1. use Dcat\Admin\OperationLog\OperationLogServiceProvider;
  2. OperationLogServiceProvider:trans('log.title');
  3. OperationLogServiceProvider:trans('log.setting_title');

Define menu

Next we also need to generate a menu for our extension, open the extensions directory /src/OperationLogServiceProvider.php and change the content as follows

  1. class OperationLogServiceProvider extends ServiceProvider
  2. {
  3. // 定义菜单
  4. protected $menu = [
  5. [
  6. 'title' => 'Operation Log',
  7. 'uri' => 'auth/operation-logs',
  8. 'icon' => '', // Icon can be left blank.
  9. ],
  10. ];
  11. public function settingForm()
  12. {
  13. return new Setting($this);
  14. }
  15. }

If you want to register a menu with hierarchies, you can do so in the following way

  1. // Registration Menu
  2. protected $menu = [
  3. [
  4. 'title' => 'Operation Log',
  5. 'uri' => '',
  6. 'icon' => 'feather icon-x',
  7. ],
  8. [
  9. 'parent' => 'Operation Log', // Specify parent menu
  10. 'title' => 'List',
  11. 'uri' => 'auth/operation-logs',
  12. ],
  13. ];

Test extensions

After all the above steps are completed, we can start testing the above features to verify if there are any errors before proceeding with the subsequent development.

Since we already installed and enabled the extension when we first created it, here we have to uninstall the current extension and then update to 1.0.0 version again so that the data tables and menus will be created.

{tip} The Uninstall function will delete the extension’s data or data tables, so please be careful to avoid data loss!!!!

Open the extension management page http://域名/admin/auth/extensions, find the current extension, mouse over the extension line, click the Uninstall button and confirm, then click the Update to version 1.0.0 and Enable buttons again. Finally F5 Refresh your browser to see the newly created menu, click on the menu to access the operation logs management page admin/auth/operation-logs.

Registration middleware

Now our extension also needs a middleware to record user actions, create the file in the Extension directory /src/Http/Middleware/LogOperation.php and click on LogOperation.php to see it.

Then we need to register the middleware to make it work, open the extensions directory /src/OperationLogServiceProvider.php, and modify the content as follows

  1. class OperationLogServiceProvider extends ServiceProvider
  2. {
  3. protected $middleware = [
  4. 'middle' => [ // Registered Middleware
  5. LogOperation::class,
  6. ],
  7. ];
  8. protected $menu = [
  9. [
  10. 'title' => 'Operation Log',
  11. 'uri' => 'auth/operation-logs',
  12. ],
  13. ];
  14. public function settingForm()
  15. {
  16. return new Setting($this);
  17. }
  18. }

The middleware registered in the $middleware attribute will be merged into the configuration parameter admin.route.middleware.

  1. before The middleware will be the first to execute.
  2. middle The middleware executes between admin.auth (in login authentication) and admin.permission (permission determination) middleware.
  3. after The middleware will be executed at the end.

In this example, it is clear that logging user actions in the operations log requires logging logged-in user information, so the middleware must be executed after the admin.auth middleware in order to get the logged-in user data. And permissionless operations also need to be logged, so they must be performed before the admin.permission middleware, so only middleware of the type middle must be registered to meet these requirements!

After registering the middleware, we feel free to visit other pages in the system (except for the operation log management page), and then visit the operation log management page, you can see the user’s operation log, and here the plug-in is basically developed.

Configuration parameters (settings)

In the current example, we need to allow the user to configure some custom parameters (e.g. configure routes that don’t require logging of operations), so we also need a `configuration form'' that allows the user to configure the parameters directly from the page. We need to return this configuration form object in theOperationLogServiceProviderclass assettingForm`.

  1. class OperationLogServiceProvider extends ServiceProvider
  2. {
  3. ...
  4. // Return the configuration form object, or delete the method if you don't need to save the configuration parameters.
  5. public function settingForm()
  6. {
  7. return new Setting($this);
  8. }
  9. }

Then we need to modify the configuration form class extended directory /src/Setting.php as follows

  1. namespace Dcat\Admin\OperationLog;
  2. use Dcat\Admin\Extend\Setting as Form;
  3. use Dcat\Admin\OperationLog\Models\OperationLog;
  4. use Dcat\Admin\Support\Helper;
  5. class Setting extends Form
  6. {
  7. // Return form popup TITLE
  8. public function title()
  9. {
  10. return $this->trans('log.title');
  11. }
  12. // Formatting the values of configuration parameters to be saved
  13. protected function formatInput(array $input)
  14. {
  15. // Convert to array, note that if it is an array when saved here, it will be an array when read out.
  16. $input['except'] = Helper::array($input['except']);
  17. $input['allowed_methods'] = Helper::array($input['allowed_methods']);
  18. return $input;
  19. }
  20. public function form()
  21. {
  22. // Defining Form Fields
  23. $this->tags('except');
  24. $this->multipleSelect('allowed_methods')
  25. ->options(array_combine(OperationLog::$methods, OperationLog::$methods));
  26. $this->tags('secret_fields');
  27. }
  28. }

After the above settings are completed, we can save the custom parameters in the extension management page

Developing extensions - 图2

The configuration parameters can be read as follows, and can be used in the middleware LogOperation

  1. use Dcat\Admin\OperationLog\OperationLogServiceProvider;
  2. // 读取配置参数
  3. $except = OperationLogServiceProvider::setting('except');
  4. $allowedMethods = OperationLogServiceProvider::setting('allowed_methods');
  5. $secretFields = OperationLogServiceProvider::setting('secret_fields');

Service registration and initialization

Since the current example does not use the service registration and initialization related functions, so this part of the content is skipped, students who need related information can refer to extension-f.md#service chapter.

View (view)

Since the current example does not use the function of custom static resources, so this part of the content is skipped first, students with related needs can refer to the extension - view chapter.

Static resources

Since there is no custom static resource in this example, we will skip this part first, if you need it, you can refer to extension - static resources.

Modify composer.json & README.md

After the code is complete, you need to modify the contents of composer.json, replace description, keywords, license, authors with your own information, and don’t forget to complete README.md to supplement the documentation and other related information.

Release extensions

Upload Application Marketplace

Developers can publish extensions to the Marketplace, and then users can install them directly from the App Store.

Upload to Github

Log in to your Github, create a repository, and then follow the instructions on the page to push your code up.

  1. git init
  2. git remote add origin https://github.com/<your-name>/<your-repository>.git
  3. git add .
  4. git commit -am "Initial commit."
  5. git push origin master

Posted to Packagist.org

Next is to publish your project to Packagist.org, if you don’t have an account, register one, then open Submit in the top navigation, fill in the repository address and submit it.

By default, Packagist.org is not automatically updated when you push new code, so you need to create a GitHub service hook. You can also update it manually by clicking the Update button on the page, but I recommend doing this automatically!

After committing, due to the delay in synchronization time, you may not be able to find your project when installing with composer, you may need to wait for the synchronization to complete.

Once the release is complete, you can install your extension via composer!