# Create a new package
There are two ways to create a package.
- By using Bagisto Package Generator (Recommended)
- By manually setting up all files (Expert Level)
# 1. By using Bagisto Package Generator
You need to install Bagisto Package Generator (opens new window).
If you have not installed this package then you need to go to the root folder of Bagisto and run the following command
composer require bagisto/bagisto-package-generator
Now, to generate your package you need to use the following command,
If the package directory does not exist,
php artisan package:make ACME/HelloWorld
If somehow the package directory is already present then you can use the force command as well. For that you just need to pass the '--force' command.
php artisan package:make ACME/HelloWorld --force
Now check your
packages
directory, everything is setup for you.After that, you need to register your service provider in
config/app.php
.<?php return [ ... 'providers' => [ ... ACME\HelloWorld\Providers\HelloWorldServiceProvider::class, ... ] ... ];
Add you package namespace in
psr-4
key incomposer.json
file for auto loading which is located in Bagisto root directory."autoload": { ... "psr-4": { ... "ACME\\HelloWorld\\": "packages/ACME/HelloWorld/src" ... } ... }
Run the below listed command:
composer dump-autoload php artisan optimize
php artisan vendor:publish --force -> Press the number before "ACME\HelloWorld\Providers\HelloWorldServiceProvider" and then press enter to publish all assets and configurations.
Check output in the browser
- Now start creating something cool.
# 2. By manually setting up all files
By manually setting up package, we assume that you are familiar with packages directory structures and flow. If not then you can find a basic tree structure of package below,
Basic tree structure of the package
- ACME/HelloWorld/
- publishable/assets
- css/
- images/
- js/
- src/
- Config/
- acl.php
- admin-menu.php
- Console/
- Commands/
- Contracts/
- Database/
- Migrations/
- Seeders/
- Events/
- Http/
- Controllers/
- Admin/
- HelloWorldController.php
- Shop/
- HelloWorldController.php
- Middleware/
- Requests/
- admin-routes.php
- shop-routes.php
- Listeners/
- Mail/
- Models/
- Providers/
- HelloWorldServiceProvider.php
- ModuleServiceProvider.php
- Repositories/
- Resources/
- assets/
- images/
- js/
- app.js
- sass/
- admin.scss
- default.scss
- velocity.scss
- lang/
- views/
- admin/
- layouts/
- style.blade.php
- index.blade.php
- shop/
- default/
- index.blade.php
- velocity/
- index.blade.php
- package.json
- webpack.mix.js
Let's start with first step by creating the packages folder.
# Step-1
In
packages
folder, create a folder with your company name and inside that create a folder with your package name. Let's sayACME/HelloWorld
. So, your basic structure will look like this,- packages/ - ACME/HelloWorld/
# Step-2
In your package folder, create a folder named as
src
. This is the place where you need to put all your files related to your package. Now, your updated structure will look like this,- packages/ - ACME/HelloWorld/ - src/
# Step-3
In
src
folder, create a folder named asProviders
and inside that folder, create a file named asPackagenameServiceProvider.php
. Let's sayHelloWorldServiceProvider.php
.TIP
If you want to do this with the Bagisto Package Generator then you need to type the following command, it will generate the service provider for you.
php artisan package:make-provider HelloWorldServiceProvider ACME/HelloWorld
If somehow the file already exists then you can use
--force
to overwrite the file.Copy the below code and paste it in
HelloWorldServiceProvider.php
,<?php namespace ACME\HelloWorld\Providers; use Illuminate\Support\ServiceProvider; class HelloWorldServiceProvider extends ServiceProvider { /** * Bootstrap services. * * @return void */ public function boot() { } /** * Register services. * * @return void */ public function register() { } }
# Step-4
Now, register your service provider in
config/app.php
which is located in Bagisto root directory.<?php return [ ... 'providers' => [ ... ACME\HelloWorld\Providers\HelloWorldServiceProvider::class, ... ] ... ];
# Step-5
Add your package namespace in
psr-4
key incomposer.json
file for auto loading which is located in Bagisto root directory."autoload": { ... "psr-4": { ... "ACME\\HelloWorld\\": "packages/ACME/HelloWorld/src" ... } ... }
Run
composer dump-autoload
.
# Step-6
Now, you need to add routing & views in your package.
For routes: Create a
Http
folder inpackages/ACME/HelloWorld/src
and create two files named asadmin-routes.php
andshop-routes.php
. So the updated structure will look like below,Updated directory structure
- packages/ - ACME/HelloWorld/ - src/ ... - Http/ - admin-routes.php - shop-routes.php
admin-routes.php
: This file is for the admin routes. Add below codes to this file,<?php Route::group(['middleware' => ['web', 'admin']], function () { Route::prefix(config('app.admin_url'))->group(function () { // all admin routes will place here }); });
shop-routes.php
: This file is for the shop routes. Add below codes to this file,<?php Route::group(['middleware' => ['web', 'theme', 'locale', 'currency']], function () { // all shop routes will be place here });
TIP
If you don't want to do it manually, then you can use our Bagisto Package Generator. For that you need to use this command,
For admin-routes.php,
php artisan package:make-admin-route ACME/HelloWorld
For shop-routes.php,
php artisan package:make-shop-route ACME/HelloWorld
For views: Create
Resources
folder inpackages/ACME/HelloWorld/src
path. InResources
folder, create another folder named asviews
. Now, in theviews
folder, we need to create a two more folder i.e.admin
andshop
. So updated structure will look like this,Updated directory structure
- packages/ - ACME/HelloWorld/ - src/ ... - Resources/ ... - views/ - admin/ - shop/
Inside each folder i.e.
admin
andshop
create a file named asindex.blade.php
. Add some data toindex.blade.php
,admin/index.blade.php
<h2>Hello World Admin</h2>
shop/index.blade.php
<h2>Hello World Shop</h2>
Now, we need to register our routes and views to service provider’s boot method i.e.
packages/ACME/HelloWorld/src/Providers/HelloWorldServiceProvider.php
<?php namespace ACME\HelloWorld\Providers; use Illuminate\Support\ServiceProvider; class HelloWorldServiceProvider extends ServiceProvider { /** * Bootstrap services. * * @return void */ public function boot() { $this->loadRoutesFrom(__DIR__ . '/../Http/admin-routes.php'); $this->loadRoutesFrom(__DIR__ . '/../Http/shop-routes.php'); $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'helloworld'); } /** * Register services. * * @return void */ public function register() { } }
# Step-7
Now, we need to create a route and render a view on that route.
Go to
packages/ACME/HelloWorld/src/Http/shop-routes.php
file and create a route to render view.<?php Route::group(['middleware' => ['web', 'theme', 'locale', 'currency']], function () { // all shop routes will be place here Route::view('/hello-world', 'helloworld::shop.index'); });
Same for admin routes in file
packages/ACME/HelloWorld/src/Http/admin-routes.php
.<?php Route::group(['middleware' => ['web', 'admin']], function () { // all admin routes will place here Route::view('/admin/hello-world', 'helloworld::admin.index'); });
Now, check your route in your browser,
Admin Output
Shop Output
# Step-8
Now, we are going to create a language file for our package. For this create a
lang
folder in thepackages/ACME/HelloWorld/src/Resources
path.In
lang
folder, you can create a different folder for language translations like for English 'en', Hindi ‘hn’ etc. Moving forward, we will create a folder nameen
(say language code) and in that folder, create a file name asapp.php
to perform language translation.Updated directory structure
- packages/ - ACME/HelloWorld/ - src/ ... - Resources/ ... - lang/ - en/ - app.php
Now, we need to register the language file to the service provider.
<?php namespace ACME\HelloWorld\Providers; use Illuminate\Support\ServiceProvider; class HelloWorldServiceProvider extends ServiceProvider { /** * Bootstrap services. * * @return void */ public function boot() { $this->loadRoutesFrom(__DIR__ . '/../Http/admin-routes.php'); $this->loadRoutesFrom(__DIR__ . '/../Http/shop-routes.php'); $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'helloworld'); $this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'helloworld'); } /** * Register services. * * @return void */ public function register() { } }
Now we can write a translation in
app.php
like below,<?php return [ 'hello-world' => [ 'name' => 'Prateek Srivastava' ] ];
Add below code to your blade file.
{{ __('helloworld::app.hello-world.name') }}
Admin Output
Shop Output
# Step-9
Now we will add CSS, JS and images to our package.
In
Resources
folder creates a folder nameassets
& createsass
,js
andimages
folder.In sass folder, add file app.scss
In js folder, add file app.js
Updated directory structure
- packages/
- ACME/HelloWorld/
- src/
...
- Resources/
- assets/
- sass/
- app.scss
- js/
- app.js
- images/
To add assets, create
package.json
andwebpack.mix.js
file inside the root of your package i.e.packages/ACME/HelloWorld
.Copy below code to
package.json
,{ "scripts": { "dev": "npm run development", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch-poll": "npm run watch -- --watch-poll", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" }, "devDependencies": { "cross-env": "^7.0.2", "laravel-mix": "^5.0.1", "laravel-mix-merge-manifest": "^0.1.2" } }
Copy below code to
webpack.mix.js
,const mix = require("laravel-mix"); if (mix == "undefined") { const { mix } = require("laravel-mix"); } require("laravel-mix-merge-manifest"); if (mix.inProduction()) { var publicPath = "publishable/assets"; } else { var publicPath = "../../../public/vendor/webkul/helloworld/assets"; } mix.setPublicPath(publicPath).mergeManifest(); mix.disableNotifications(); mix .js([__dirname + "/src/Resources/assets/js/app.js"], "js/helloworld.js") .copyDirectory( __dirname + "/src/Resources/assets/images", publicPath + "/images" ) .sass( __dirname + "/src/Resources/assets/sass/app.scss", "css/helloworld.css" ) .options({ processCssUrls: false, }); if (mix.inProduction()) { mix.version(); }
After doing this go to the root of your package i.e.
packages/ACME/HelloWorld
and runnpm install
which will install all dependencies.Now,
app.js
andapp.scss
is ready. Write all your css and js here.When you done with your changes, then run
npm run prod
which will compiled all your css, js and images to the publishable folder. Then register your publishable inHelloWorldServiceProvider
,TIP
You can use
npm run watch
also, this will watch all your changes and put all your changes to the public path. When you done with all your changes then runnpm run prod
to compile all your changes and move to publishable folder.<?php namespace ACME\HelloWorld\Providers; use Illuminate\Support\ServiceProvider; class HelloWorldServiceProvider extends ServiceProvider { /** * Bootstrap services. * * @return void */ public function boot() { $this->loadRoutesFrom(__DIR__ . '/../Http/admin-routes.php'); $this->loadRoutesFrom(__DIR__ . '/../Http/shop-routes.php'); $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'helloworld'); $this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'helloworld'); $this->publishes([ __DIR__ . '/../../publishable/assets' => public_path('vendor/webkul/helloworld/assets'), ], 'public'); } /** * Register services. * * @return void */ public function register() { } }
After doing this we need to add an event listener so that admin layouts include our CSS. For this we need to add an Event Listener in service provider. But before adding event, let's create a
layouts
folder inpackages/ACME/Test/src/Resources/views/admin
and inside that create a file calledstyle.blade.php
& mention compiled CSS path inside this file.<link rel="stylesheet" href="{{ asset('vendor/webkul/helloworld/assets/css/helloworld.css') }}" />
For Event Listener: Add facade 'Event' into your
HelloWorldServiceProvider.php
file,<?php namespace ACME\HelloWorld\Providers; use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider; /** * HelloWorldServiceProvider */ class HelloWorldServiceProvider extends ServiceProvider { /** * Bootstrap services. * * @return void */ public function boot() { $this->loadRoutesFrom(__DIR__ . '/../Http/admin-routes.php'); $this->loadRoutesFrom(__DIR__ . '/../Http/shop-routes.php'); $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'helloworld'); $this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'helloworld'); $this->publishes([ __DIR__ . '/../../publishable/assets' => public_path('vendor/webkul/helloworld/assets'), ], 'public'); Event::listen('bagisto.admin.layout.head', function($viewRenderEventManager) { $viewRenderEventManager->addTemplate('helloworld::admin.layouts.style'); }); } /** * Register services. * * @return void */ public function register() { } }
Till now, we configured our package HelloWorld and now we need to extend the default layout of our admin panel by using
@extends('admin::layouts.master')
in filepackages/ACME/HelloWorld/src/Resources/views/admin/index.blade.php
. Below is the simple template which you can copy to yourindex.blade.php
file,@extends('admin::layouts.master') @section('page_title') Package HelloWorld @stop @section('content-wrapper') <div class="content full-page dashboard"> <div class="page-header"> <div class="page-title"> <h1>Package HelloWorld</h1> </div> <div class="page-action"></div> </div> <div class="page-content"></div> </div> @stop
If you don’t want to include this one then you can create your own master file which includes your packages CSS & JS.
Run
php artisan vendor:publish --all --force
. This will move all your publishable assets to their respective directory which you mentioned in the service provider.
# Step-10
Now we will add Database to our package. Create a
Database
folder inpackages/ACME/HelloWorld/src
path and insideDatabase
folder createMigrations
andSeeders
folder.Now, we need to add migrations to our service provider to load them.
<?php namespace ACME\HelloWorld\Providers; use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider; class HelloWorldServiceProvider extends ServiceProvider { /** * Bootstrap services. * * @return void */ public function boot() { $this->loadRoutesFrom(__DIR__ . '/../Http/admin-routes.php'); $this->loadRoutesFrom(__DIR__ . '/../Http/shop-routes.php'); $this->loadViewsFrom(__DIR__ . '/../Resources/views', 'helloworld'); $this->loadTranslationsFrom(__DIR__ . '/../Resources/lang', 'helloworld'); $this->publishes([ __DIR__ . '/../../publishable/assets' => public_path('vendor/webkul/helloworld/assets'), ], 'public'); Event::listen('bagisto.admin.layout.head', function($viewRenderEventManager) { $viewRenderEventManager->addTemplate('helloworld::helloworld.layouts.style'); }); $this->loadMigrationsFrom(__DIR__ .'/../Database/Migrations'); } /** * Register services. * * @return void */ public function register() { } }
Now start adding your migration files.