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 handle activate
, deactivate
, remove
events 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 create routes\api.php
if 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' => '[email protected]',
]);
Route::get('/create', [
'as' => 'demo.create',
'uses' => '[email protected]',
]);
Route::post('/create', [
'as' => 'demo.create',
'uses' => '[email protected]',
]);
Route::get('/edit/{id}', [
'as' => 'demo.edit',
'uses' => '[email protected]',
]);
Route::post('/edit/{id}', [
'as' => 'demo.edit',
'uses' => '[email protected]',
]);
Route::get('/delete/{id}', [
'as' => 'demo.delete',
'uses' => '[email protected]',
]);
Route::post('/delete-many', [
'as' => 'demo.delete.many',
'uses' => '[email protected]',
'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.