Developing extensions

New Release Preview

Dcat Admin plans to go live with the plug-in marketplace feature in 2.0 version, which will refactor the entire extension functionality to enhance the user experience. The new extension system will allow users to install, update and uninstall plug-ins with just a few clicks of the mouse from the administration page. The new extension system will allow users to install, update and uninstall plug-ins with just a few mouse clicks from the administration page.

The Dcat Admin team will work hard to build an ecosystem that benefits both developers and users, thanks for your support!

Start

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 are using Dcat Admin to add some of your own features or components, you can make a Dcat Admin extension, which can help other Dcat Admin users and improve the quality of the extension in other people’s feedback.

This document will take the development of a Dry Fish Camp extension as an example, step-by-step development of an extension, and released to others to use, the final results of the reference [Demo] ().

Creating Composer Packages

The Dcat Admin package will be installed with composer, so first create a composer package, you can use the built-in admin:extend command to generate an extension skeleton.

When running the command, you may be prompted to enter a directory to store your extensions, you can add a configuration 'extension_dir' => admin_path('Extensions') in config/admin.php so that the extensions will be stored in app/Admin/ Extensions directory, but you can also put it in any other directory.

  1. php artisan admin:ext-make dcat-admin-extensions/gank --namespace="Dcat\Admin\Extension\Gank"

The dcat-admin-extensions/gank is the package name, and the namespace option is the top-level namespace used by the package, after running this command, the directory dcat-admin-extensions/gank will be generated in the extension directory set in config/admin.php and the following document structure:

  1. ├── LICENSE
  2. ├── README.md
  3. ├── composer.json
  4. ├── bootstrap.php
  5. ├── database
  6. ├── migrations
  7. └── seeds
  8. ├── resources
  9. ├── assets
  10. └── views
  11. └── index.blade.php
  12. ├── routes
  13. └── web.php
  14. └── src
  15. ├── Setting.php
  16. ├── GankServiceProvider.php
  17. └── Http
  18. └── Controllers
  19. └── GankController.php

bootstrap.php is used to register the extension, the code in this file does not need any modification; resources is used to place the view files and static resource files; src is mainly used to place the logical code; routes/web.php is used to store the routing settings for this extension; database is used to place the database migrations. Files and data seeders.

Functional development

The functionality of this extension is primarily used to display the contents of the gank.io interface, integrated into Dcat Admin, which will have a route and a controller with no database files, templates, or static resource files, and we can clean up any files or directories that we don’t use, and the cleaned up directory file will be.

  1. ├── LICENSE
  2. ├── README.md
  3. ├── composer.json
  4. ├── bootstrap.php
  5. ├── routes
  6. └── web.php
  7. └── src
  8. ├── Setting.php
  9. ├── GankServiceProvider.php
  10. └── Http
  11. └── Controllers
  12. └── GankController.php

After generating the extension framework, you may need to debug while developing, so refer to the following local installation, first install the extension into the system, continue development

Adding routes

First add a route, a route configuration is already generated automatically in routes/web.php.

  1. <?php
  2. use Dcat\Admin\Extension\Gank\Http\Controllers;
  3. Route::get('gank', Controllers\GankController::class.'@index');

The access path http://localhost:8000/admin/gank will be handled by the index method of the Dcat\Admin\Extension\Gank\Http\Controllers\GankController controller.

Setting Extended Properties

src/Gank.php is used as an extension class to set the properties of the extension.

  1. <?php
  2. namespace Dcat\Admin\Extension\Gank;
  3. use Dcat\Admin\Extension;
  4. class Gank extends Extension
  5. {
  6. // Extended aliases for getting configuration information in configuration files
  7. const NAME = 'gank';
  8. // service provider class name, just use the auto-generated one, no need to change it.
  9. public $serviceProvider = GankServiceProvider::class;
  10. // Static resource directory, which can be deleted if no static resources are needed.
  11. // public $assets = __DIR__.'/../resources/assets';
  12. // composer configuration file path, just use the default.
  13. public $composerJson = __DIR__.'/../composer.json';
  14. // custom properties
  15. public static $categoryColorsMap = [
  16. 'App' => 'var(--purple)',
  17. 'Front End' => 'var(--primary)',
  18. 'Recommendation' => 'var(--primary-dark)',
  19. 'Welfare' => 'var(--blue)',
  20. 'Explosion' => 'var(--danger)',
  21. 'Android' => 'var(--purple-dark)',
  22. 'iOS' => 'var(--info)',
  23. 'Break' => 'var(--warning)',
  24. ];
  25. }

This file is used to set some properties of the extension, $name is the alias of the extension, if the extension has a view file to render, you must specify the $views property of the extension, similarly if the extension has a static resource file to publish, you must set the $assets property, if you need to add a menu button in the left sidebar, set the $ The menu attribute can be removed as needed.

Then open src/GankServiceProvider.php. This ServiceProvider will run when the extension is enabled (no need for the developer to add it) and will be used to register some of the extension’s services into the system.

Load view

If this extension requires a view file to be loaded, add the following code to the boot method of src/GankServiceProvider.php:

  1. $extension = Gank::make();
  2. if ($extension->views) {
  3. $this->loadViewsFrom($extension->views, 'gank');
  4. }

The first parameter of the loadViewsFrom method is the view property set in the extension class src/Gank.php, the second parameter is the namespace of the view file directory, after setting gank, use view('gank::index') to load resources/views in the controller. View file under the directory.

Introduce static resources

If you have static resource files that need to be introduced into your project, put them in the resources/assets directory, such as resources/assets/foo.js and resources/assets/bar.css files.

Then set the $assets attribute in the extension src/Gank.php.

  1. public $assets = __DIR__.'/../resources/assets';

After installation, the file will be copied to the public/vendor/dcat-admin-extensions/gank directory.

Then we can add the following code where we need to use these static resources

{tip} Since Dcat Admin supports loading static resources on demand, it is not recommended to introduce static resources directly into ServiceProvider or bootstrap.php, as this will slow down the loading time of all pages.

  1. use Dcat\Admin\Admin;
  2. Admin::js('vendor/dcat-admin-extensions/gank/phpinfo/foo.js');
  3. Admin::css('vendor/dcat-admin-extensions/gank/phpinfo/bar.css');

This completes the introduction of static resources, which can be ignored in the gank extension since there are no static resources to introduce.

Adding menus

There are two ways to add menus.

  • Set the $menu attribute in src/Gank.php, this way the menu is written into the menu table, which is easier for the user to control
  • Use the Admin::menu interface to add menus by way of arrays, which is more convenient and supports adding multi-level menus.

The second way to add a menu is used here, adding the following code to the boot method of src/GankServiceProvider.php.

  1. Admin::menu()->add([
  2. [
  3. 'id' => 1,
  4. 'title' => 'Dry Fish Camp',
  5. 'icon' => ' fa-newspaper-o',
  6. 'uri' => 'gank',
  7. 'parent_id' => 0,
  8. 'permission_id' => 'gank', // Binding privileges
  9. 'roles' => [['slug' => 'gank']], // Binding Roles
  10. ],
  11. [
  12. 'id' => 2,
  13. 'title' => 'All dry goods',
  14. 'icon' => 'fa-smile-o',
  15. 'uri' => 'gank',
  16. 'parent_id' => 1,
  17. 'permission_id' => 'gank', // Binding privileges
  18. 'roles' => [['slug' => 'gank']], // Binding Roles
  19. ],
  20. ]);

The final src/GankServiceProvider.php code is as follows:

  1. <?php
  2. namespace Dcat\Admin\Extension\Gank;
  3. use Dcat\Admin\Admin;
  4. use Illuminate\Support\ServiceProvider;
  5. class GankServiceProvider extends ServiceProvider
  6. {
  7. /**
  8. * {@inheritdoc}
  9. */
  10. public function boot()
  11. {
  12. $extension = Gank::make();
  13. if ($extension->views) {
  14. $this->loadViewsFrom($extension->views, 'gank');
  15. }
  16. if ($extension->lang) {
  17. $this->loadTranslationsFrom($extension->lang, 'gank');
  18. }
  19. if ($extension->migrations) {
  20. $this->loadMigrationsFrom($extension->migrations);
  21. }
  22. $this->app->booted(function () use ($extension) {
  23. $extension->routes(__DIR__.'/../routes/web.php');
  24. });
  25. // Add Menu
  26. $this->registerMenus();
  27. }
  28. protected function registerMenus()
  29. {
  30. Admin::menu()->add([
  31. [
  32. 'id' => 1,
  33. 'title' => `Dry Fish Camp`,
  34. 'icon' => ' fa-newspaper-o',
  35. 'uri' => 'gank',
  36. 'parent_id' => 0,
  37. 'permission_id' => 'gank', // Binding privileges
  38. 'roles' => [['slug' => 'gank']], // Binding Roles
  39. ],
  40. [
  41. 'id' => 2,
  42. 'title' => 'All dry goods',
  43. 'icon' => 'fa-smile-o',
  44. 'uri' => 'gank',
  45. 'parent_id' => 1,
  46. 'permission_id' => 'gank', // Binding privileges
  47. 'roles' => [['slug' => 'gank']], // Binding Roles
  48. ],
  49. ]);
  50. }
  51. }

Adding custom installation logic

If you want to perform some custom logic when importing extensions, you can add the following code to src/Gank.php.

Please make sure that the import command is executed repeatedly without error.

  1. ...
  2. public function import(Command $command)
  3. {
  4. parent::import($command); // TODO: Change the autogenerated stub
  5. // Write your import logic here
  6. $command->info('Import success');
  7. }

Code logic development

This extension mainly calls the interface provided by gank.io, and then displays the data.

We need to add a new data warehouse file to capture data from gank.io, creating the file src/Repositories/Ganks.php.

  1. <?php
  2. namespace Dcat\Admin\Extension\Gank\Repositories;
  3. use Dcat\Admin\Grid;
  4. use Dcat\Admin\Repositories\Repository;
  5. use Illuminate\Pagination\LengthAwarePaginator;
  6. use Illuminate\Support\Collection;
  7. class Ganks extends Repository
  8. {
  9. protected $api = 'http://gank.io/api/data/{category}/{limit}/{page}';
  10. protected $searchApi = 'http://gank.io/api/search/query/{key}/category/{category}/count/{limit}/page/{page}';
  11. /**
  12. * Inquiry Form Data
  13. *
  14. * @param Grid\Model $model
  15. * @return Collection
  16. */
  17. public function get(Grid\Model $model)
  18. {
  19. $currentPage = $model->getCurrentPage();
  20. $perPage = $model->getPerPage();
  21. // Get filter parameters
  22. $category = $model->filter()->input(Grid\Filter\Scope::QUERY_NAME, 'all');
  23. $keyword = trim($model->filter()->input('keyword'));
  24. $api = $keyword ? $this->searchApi : $this->api;
  25. $client = new \GuzzleHttp\Client();
  26. $response = $client->get(str_replace(
  27. ['{category}', '{limit}', '{page}', '{key}'],
  28. [$category, $perPage, $currentPage, $keyword],
  29. $api
  30. ));
  31. $data = collect(
  32. json_decode((string)$response->getBody(), true)['results'] ?? []
  33. );
  34. $total = $keyword ? 400 : ($category == 'all' ? 1000 : 500);
  35. $paginator = new LengthAwarePaginator(
  36. $data,
  37. $category == '福利' ? 680 : $total,
  38. $perPage, // Enter the number of lines per page
  39. $currentPage // Pass in the current page number
  40. );
  41. $paginator->setPath(\url()->current());
  42. return $paginator;
  43. }
  44. public function getKeyName()
  45. {
  46. return '_id';
  47. }
  48. }

Modify the controller code as follows:

  1. <?php
  2. namespace Dcat\Admin\Extension\Gank\Http\Controllers;
  3. use Dcat\Admin\Extension\Gank\Gank;
  4. use Dcat\Admin\Extension\Gank\Repositories\Ganks;
  5. use Dcat\Admin\Grid;
  6. use Dcat\Admin\Layout\Content;
  7. use Dcat\Admin\Layout\Row;
  8. use Illuminate\Routing\Controller;
  9. use Dcat\Admin\Widgets\Navbar;
  10. class GankController extends Controller
  11. {
  12. public function index(Content $content)
  13. {
  14. $grid = $this->grid();
  15. $grid->disableFilter();
  16. $grid->filter()
  17. ->withoutInputBorder()
  18. ->expand()
  19. ->resetPosition()
  20. ->hiddenResetButtonText();
  21. return $content
  22. ->header('All dry goods')
  23. ->description('Share daily girl pictures and tech tricks')
  24. ->body($grid->filter())
  25. ->body(function (Row $row) {
  26. $items = array_keys(Gank::$categoryColorsMap);
  27. array_unshift($items, 'All');
  28. $navbar = Navbar::make('#', array_combine($items, $items))
  29. ->checked(request(Grid\Filter\Scope::QUERY_NAME, 'All'))
  30. ->click()
  31. ->map(function ($v) {
  32. if ($v == 'All') {
  33. $url = '?';
  34. } else {
  35. $url = '?'.Grid\Filter\Scope::QUERY_NAME.'='.$v;
  36. }
  37. return "<a href='$url'>$v</a>";
  38. })
  39. ->style('max-width:705px');
  40. $row->column(7, $navbar);
  41. })
  42. ->body($grid);
  43. }
  44. protected function grid()
  45. {
  46. $this->define();
  47. $grid = new Grid(new Ganks);
  48. $grid->number();
  49. $grid->desc('Description')->width('300px');
  50. $grid->images('Pictures')->image(150);
  51. $grid->type('Categories');
  52. $grid->who('Authors')->label();
  53. $grid->publishedAt('Published at');
  54. $grid->disableActions();
  55. $grid->disableBatchDelete();
  56. $grid->disableExport();
  57. $grid->disableCreateButton();
  58. $grid->disableFilterButton();
  59. $grid->disableQuickCreateButton();
  60. $grid->perPages([]);
  61. return $grid->filter(function (Grid\Filter $filter) {
  62. $category = $filter->input(Grid\Filter\Scope::QUERY_NAME, 'All');
  63. if ($category != 'Benefits') {
  64. $filter->like('keyword', ucfirst($category))->width('300px')->placeholder('Please enter');
  65. }
  66. });
  67. }
  68. protected function define()
  69. {
  70. Grid\Column::define('desc', function ($v) {
  71. if ($this->type == 'Benefits') {
  72. $width = '150';
  73. $height = '200';
  74. return "<img data-init='preview' src='{$this->url}' style='max-width:{$width}px;max-height:{$height}px;cursor:pointer' class='img img-thumbnail' />";
  75. }
  76. return sprintf('<a href="%s" target="_blank">%s</a>', $this->url, $v);
  77. });
  78. Grid\Column::define('publishedAt', function ($v) {
  79. return date('Y-m-d', strtotime($v));
  80. });
  81. Grid\Column::define('datetime', function ($v) {
  82. return date('Y-m-d H:i:s', strtotime($v));
  83. });
  84. Grid\Column::define('type', function ($v) {
  85. $map = Gank::$categoryColorsMap;
  86. return "<span class='label' style='background:{$map[$v]}'>$v</span>";
  87. });
  88. }
  89. }

This way a complete extension is developed.

Modify composer.json & README.md

After the code is partially complete, you need to modify the contents of composer.json, replace description, keywords, license, authors and other content with your information, and then do not forget to improve README.md, supplement the use of documentation and other related information.

Installation

After completing the extension development, you can install your extensions as follows, depending on the situation

Local installation

In the development process, you generally need to debug while developing, so first install locally as follows

Open the composer.json file in your project and add the following configuration to it

  1. "repositories": [
  2. {
  3. "type": "path",
  4. "url": "app/Admin/Extensions/dcat-admin-extensions/gank"
  5. }
  6. ]

Then run composer require dcat-admin-extensions/gank @dev to complete the installation, and if you have static files to publish, run the following command:

  1. php artisan vendor:publish --provider=Dcat\Admin\Extension\GankServiceProvider

Remote installation

If the development is complete, I hope to open source out for everyone to use, follow these steps

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

Release

Local releases can be made in the following ways

  1. git tag 0.0.1 && git push --tags

It can also be set up manually on the Releases page of Github’s repository page.

Publish 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 the synchronization time of the local mirror, you may not be able to find your project when installing with composer, you may need to wait for the synchronization to complete.

Once released, you can install your extensions through composer.

Add to https://github.com/dcat-admin-extensions If you would like to add your extensions to dcat-admin-extensions, feel free to contact me in any way you can so that more people can see and use your tools.

Importing and enabling extensions

Importing extensions

After installation, you can import extensions by running the following commands.

Generally, you don’t need to import views, database migration files, and language packs. If you want to import other files, you need to define them by the extension developer. Also this command allows repeat execution.

  1. php artisan admin:import Dcat\Admin\Extension\Gank\Gank

Enable expansion

Enabling or disabling the extension is controlled by the configuration file, open /config/admin-extension.php and add the following code:

  1. return [
  2. 'gank' => [
  3. 'enable' => true,
  4. ],
  5. ];

Visual management extensions

Visit http://localhost:8000/admin/helpers/extensions to enable or disable extensions, import extensions by page action.

If /config/admin-extension.php does not exist, the system will automatically create it.

This completes the installation, open http://localhost/admin/gank to access the extension.