All plugins are registered to Composer autoloader manually. It needs a plugin.json file to provide all needed information
for auto loading.
A basic plugin structure.
plugin.json: All information about this plugin.
Example:
{
"name": "Demo",
"namespace": "Botble\\Demo\\",
"provider": "Botble\\Demo\\Providers\\DemoServiceProvider",
"author": "Sang Nguyen",
"url": "https://sangnguyen.info",
"version": "1.0",
"description": "The description for plugin demo"
}src/Plugin.php: Using to handleactivate,deactivate,removeevents for plugin.
Example:
namespace Botble\Demo;
use Schema;
use Botble\Base\Interfaces\PluginInterface;
class Plugin implements PluginInterface
{
/**
* @author Sang Nguyen
*/
public static function activate()
{
}
/**
* @author Sang Nguyen
*/
public static function deactivate()
{
}
/**
* @author Sang Nguyen
*/
public static function remove()
{
Schema::dropIfExists('demos'); // Remove table demo when removing plugin "demo"
}
}config/permissions.php: Each plugin should have a configuration for permission. Permissions are codebase so we need to define it in this file.
Example:
return [
[
'name' => 'Demo',
'flag' => 'demo.list',
],
[
'name' => 'Create',
'flag' => 'demo.create',
'parent_flag' => 'demo.list',
],
[
'name' => 'Edit',
'flag' => 'demo.edit',
'parent_flag' => 'demo.list',
],
[
'name' => 'Delete',
'flag' => 'demo.delete',
'parent_flag' => 'demo.list',
],
];database/migrations/2018_10_07_011632_create_demo_table.php: After generating a plugin, it'll create a first migration, you should modify it before activating a plugin. When activating a plugin, its migrations will run automatically.
Example:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateDemoTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('demos', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 120);
$table->tinyInteger('status')->unsigned()->default(1);
$table->timestamps();
$table->engine = 'InnoDB';
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('demos');
}
}helpers/constants.php: to define all PHP constants for this plugin. It must have a constant for its screen name.
Example:
if (!defined('DEMO_MODULE_SCREEN_NAME')) {
define('DEMO_MODULE_SCREEN_NAME', 'demo');
}resources/lang/en/demo.php: language for your plugin. If you need to translate to more languages, let add new translation file. Ex:resources/lang/vi/demo.php
Example:
return [
'name' => 'Demo',
'create' => 'New demo',
'edit' => 'Edit demo',
];routes/web.php: Routes for this plugin. You can createroutes\api.phpif you need to work on API.
Example:
Route::group(['namespace' => 'Botble\Demo\Http\Controllers', 'middleware' => 'web'], function () {
Route::group(['prefix' => config('core.base.general.admin_dir'), 'middleware' => 'auth'], function () {
Route::group(['prefix' => 'demos'], function () {
Route::get('/', [
'as' => 'demo.list',
'uses' => 'DemoController@getList',
]);
Route::get('/create', [
'as' => 'demo.create',
'uses' => 'DemoController@getCreate',
]);
Route::post('/create', [
'as' => 'demo.create',
'uses' => 'DemoController@postCreate',
]);
Route::get('/edit/{id}', [
'as' => 'demo.edit',
'uses' => 'DemoController@getEdit',
]);
Route::post('/edit/{id}', [
'as' => 'demo.edit',
'uses' => 'DemoController@postEdit',
]);
Route::get('/delete/{id}', [
'as' => 'demo.delete',
'uses' => 'DemoController@getDelete',
]);
Route::post('/delete-many', [
'as' => 'demo.delete.many',
'uses' => 'DemoController@postDeleteMany',
'permission' => 'demo.delete',
]);
});
});
});-
src/Forms/DemoForm.php: Create and update form. -
src/Http/Controllers/DemoController.php: Controller, you can create many controllers as you want. -
src/Http/Requests/DemoRequest.php: Request to validate submit form. -
src/Models/Demo.php. -
src/Providers/DemoServiceProvider.php: This is the main file of a plugin. A plugin must have this file.
Example:
public function register()
{
if (setting('enable_cache', false)) { // Check if cache is enabled or disabled.
// Binding repositories if cache is enabled.
$this->app->singleton(DemoInterface::class, function () {
return new DemoCacheDecorator(new DemoRepository(new Demo()), new Cache($this->app['cache'], DemoRepository::class));
});
} else {
// Binding repositories if cache is disabled.
$this->app->singleton(DemoInterface::class, function () {
return new DemoRepository(new Demo());
});
}
Helper::autoload(__DIR__ . '/../../helpers'); // Load all constants/helpers from helpers folder.
}
public function boot()
{
$this->setIsInConsole($this->app->runningInConsole())
->setNamespace('plugins/demo') // Set namespace of a plugin, it's used for views/lang. Example: view('plugins.demo::create'), trans('plugins.demo::demo.create')
->loadAndPublishConfigurations(['permissions']) // Load configuration from config folder.
->loadAndPublishViews()
->loadAndPublishTranslations()
->loadRoutes(); // Load route. It's equal ->loadRoutes(['web']), if you need to work on API, you can add "api" to load it.
// Register plugin menu to admin menu
Event::listen(SessionStarted::class, function () {
dashboard_menu()->registerItem([
'id' => 'cms-plugins-demo', // Id of menu. It must be unique
'priority' => 5, // Position of plugin
'parent_id' => null, // Parent ID, if it's not null, this menu will be submenu
'name' => trans('plugins.demo::demo.name'),
'icon' => 'fa fa-list',
'url' => route('demo.list'),
'permissions' => ['demo.list'], // Permission key, it's defined in /config/permisisons.php
]);
});
}-
src/Repositories: Define all needed repositories for plugin models. -
src/Tables/DemoTable.php: Using in listing page.

