🔥 Concept
This dynamic theme manager brings theme support to Laravel projects. Theme Manager manages multiple theme at same time and you won't lose build-in Laravel features. This package uses custom middleware for overwriting view path with selected theme.
Add theme-manager
middleware alias to your web
or custom
route chain.
Then Theme Manager can manipulate the views.
Installation
⚠️ This package compatible only Laravel 8 and above.
To get the latest version of Laravel Theme Manager
, simply require the project using
Composer
:
$ composer require laravel-ready/theme-manager
Publish configs
Run artisan command:
$ php artisan vendor:publish --tag=theme-manager-config
and you can find theme-manager.php
file in config
folder.
Middleware
Add theme-manager
middleware alias to your base route in {route}.php or app/Providers/RouteServiceProvider.php
Method 1: routes/{web}.php
We can use it in web.php
or any-custom.php
file but
these route files should work with web middleware web
.
Route::prefix('/')->middleware(['theme-manager', 'another-mw'])->group(function (){
Route::get('', [LandingController::class, 'index'])->name('home');
Route::get('my-page', [LandingController::class, 'anyPage'])->name('my-page');
});
Method 2: RouteServiceProvider.php
You can find RouteServiceProvider.php
in app/Providers
folder.
Also, this method affects sub-routes. If you want to use a specific route or group use the method 1.
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
...
Route::middleware(['web', 'theme-manager'])
->namespace("{$this->namespace}\\Web")
->group(base_path('routes/web.php'));
Route::middleware(['web', 'theme-manager'])
->namespace("{$this->namespace}\\Admin")
->group(base_path('routes/admin.php'));
});
}
🚀 Usage
Middleware
Theme Manager works with vendor/theme
pair.
We can define default themes in routes and also you can restrict with the route specific theme group
.
⚠️ Parameter ordering does not matter.
Parameter | Description | Usage |
---|---|---|
theme
|
Specify theme alias |
theme-manager: theme=vendor-x/theme-y
|
vendor
|
Restrict with specific vendor |
theme-manager: group=admin
|
Combined usage examples:
-
theme-manager: theme=admin/my-theme, vendor=admin
- theme: default theme
- vendor: default vendor
-
theme-manager: vendor=admin
-
In this way, the
theme
is not defined because the theme will be set with service class but thevendor
field is required for using the default theme option.
-
In this way, the
Todo: connect to own title If you want to add a theme you must add group alias because all themes depends to own group. Also to use multiple default theme you first must define group. See multiple and default theme sections for more example.
Service
Theme loading and other options are depends to your logic. You can use ThemeManager
service in controller, custom middleware etc.
use LaravelReady\ThemeManager\Services\Theme;
use LaravelReady\ThemeManager\Services\ThemeManager;
⚠️ Remember: framework and packages work with order and follow priorities.
Service class depends on ThemeManagerMiddleware
and won't work in controller methods.
Because we are overwriting blade paths in middleware.
This depends on the case, if you want to change to active theme or real-time actions will not work. And still, you can use static methods like update, delete, etc.
So we need to use service methods before the controller method fires or in the controller constructor
.
Scan installed themes
Returns theme collection. After themes are scanned, adds to cache.
ThemeManager::scanThemes()
Get current theme
Returns current Theme details.
ThemeManager::getCurrentTheme()
Get target theme
Returns requested Theme details.
ThemeManager::getTheme()
Set current theme
setTheme
is required vendor/theme
pair.
ThemeManager::setTheme('vendor-x/theme-y')
Set theme status
setThemeStatus
is required vendor/theme
pair.
ThemeManager::setThemeStatus('vendor-x/theme-y', true|false)
or update all themes
ThemeManager::setThemeStatusAll(true|false)
// TODO: Add 'Theme' methods
Views
We can call regular views with return view('welcome')
.
If you want to call the theme view use theme::
alias like return view('theme::welcome')
in the controller.
theme::
alias is auniversal gateway for Theme Manager.
When you use the setTheme
method Theme Manager finds theme views and applies them, then Laravel renders.
⚠️ #1 You can't use theme::
alias like theme::theme-name...
.
You can only define themes with ThemeManager
service class and middleware. This package focused to dynamic theming.
⚠️ #2 View paths are must be the same for each theme. If you want to change the view path for the specific theme you have to change all themes for the target group. Otherwise, the target view is going to be broken on runtime because the path changed for other themes. Laravel throws view path not found exception.
class AnyController extends Controller
{
public function __construct() {
ThemeManager::addDefaultTheme(['vendor-x/red-swan']);
$theme = request()->query('theme', 'vendor-x/green-energy');
ThemeManager::setTheme($theme, 'web');
}
public function index(){
// laravel native
return View('web.welcome');
}
public function anyPage(){
...
// our view path of templates
return View('theme::pages.home.index');
}
}
Directives
Directive | Description | Parameters |
---|---|---|
@asset
|
Get theme asset URL |
0 : Asset path,
1 : Print theme version number (default true )
|
@assetLoad
|
Get theme asset content as string |
0 : Asset path,
1 : Fallback asset (default null )
|
@svg
|
Get SVG content as string |
0 : SVG file name,
1 : Class name (default null ),
2 : CSS style (default null )
|
-
@asset
-
@asset('css/base.css')
-
@asset('css/base.css', true|false)
-
@asset('js/app.js')
-
@asset('images/user/avatar-01.jpg')
-
@asset('favicons/favion.ico')
-
-
@assetLoad
-
@assetLoad('css/base.css')
-
@assetLoad('html/any-template.html')
-
@assetLoad('images/svg/sunshine.svg', 'images/svg/moonshine.svg')
-
-
@svg
-
@svg('chevron-left')
-
@svg('chevron-right', 'mx-auto')
-
@svg('chevron-down', 'mx-auto', 'fill: green; top: 20px; position: relative;')
-
The above asset paths css
, js
, html
are not reserved or any
custom paths are depends to your theme webpack.mix.js
configs and design approach.
⚠️ Published theme specific assets must be in
project-folder/src/public/themes/{group-alias}/{theme-alias}/
folder because
Theme Manager uses this path for directives.
Default Theme
We can show default theme when target theme is not found. Can define default themes with config file and service class.
Config file
Open theme-manager.php
( see installation part ) file then set default_theme
value.
default_theme
supports single and multiple themes.
<?php
return [
...
'default_theme' => 'vendor-x/red-swan',
...
];
or in array
<?php
return [
...
'default_theme' => [
'vendor-x/red-swan',
'egoistdev:admin-who'
],
...
];
Service class
Also we can pass default themes pass through with service class.
// add default theme/s
ThemeManager::addDefaultTheme(['vendor-x/red-swan', 'egoistdev:admin-who']);
// remove default theme/s
ThemeManager::removeDefaultTheme(['vendor-x/red-swan', 'egoistdev:admin-who']);
Both of two usage requires default vendor
definition on middleware.
Just assign default vendor field to middleware.
If theme already defined in middleware this option does not working beacuse middleware theme
definiton has high
priority.
⚠️ addDefaultTheme
and removeDefaultTheme
methods does not effects config file.
Priority
At this moment we see multiple ways to setting theme and default theme but all of them working in order.
- Middleware defined theme comes first ( if the theme is not found, goes to second check point )
- Service class defined theme ( if the theme is not found, goes to third check point )
- Default theme ( will define in config or service class )
- If default theme is not exists throws error and application breaks
✳️ Theme
Views folder and subfolder structure depends to your strategy. In this point just follow classical blade theming approach.
After new theme created you can change configs details in {themes}/group/theme/theme-configs.json
file
and you can add preview image preview.jpg
and preview.png
formats.
Then you can manage with own custom visual manager.
Commands
You can manage themes with commands.
Create new theme
$ php artisan theme-manager:make
Result:
Theme Group: (as slug. web, admin etc):
> web
Theme Vendor: (as slug):
> theme-factory
Theme Name:
> awesome-blog
Theme Description: /optional/:
> Enim laboris minim occaecat incididunt eiusmod sit excepteur reprehenderit enim consectetur Lorem.
Author Name:
> EgoistDeveloper
Author Contact Address or Email /optional/:
> https://github.com/EgoistDeveloper/
Theme "theme-factory/awesome-blog" created successfully for "web" group. Please check your "themes/theme-factory/awesome-blog" folder
List installed themes
scanThemes
methods scans folders recursively and theme listing order depends to your file system.
$ php artisan theme-manager:list
Result:
⚠️ Check the "theme-config.json" file in the own theme folder for more information.
+-------+---------+--------------+----------------------------+--------+-------+-----------------------------------+-----------------+---------+
| Index | Default | Name | Alias | Status | Group | Description | Authors | Version |
+-------+---------+--------------+----------------------------+--------+-------+-----------------------------------+-----------------+---------+
| [1] | - | Admin Who? | egoistdev/admin-who | Active | admin | Dolore officia adipisicing ven... | EgoistDeveloper | 1.0.0 |
| [2] | - | Dark Night | egoistdev/dark-night | Active | web | Find the perfect lights in dar... | EgoistDeveloper | 1.1.3 |
| [3] | - | Gentelella | egoistme/gentelella | Active | admin | Gentelella Admin is a free to... | EgoistDeveloper | 3.1.3 |
| [4] | - | awesome-blog | theme-factory/awesome-blog | Active | web | Enim laboris minim occaecat in... | EgoistDeveloper | 1.0.0 |
| [5] | - | Green Energy | vendor-x/green-energy | Active | web | Green energy is any energy typ... | EgoistDeveloper | 4.1.3 |
| [6] | Yes | Red Swan | vendor-x/red-swan | Active | web | The awesome red swan web site... | EgoistDeveloper | 1.0.1 |
+-------+---------+--------------+----------------------------+--------+-------+-----------------------------------+-----------------+---------+
Delete selected theme
$ php artisan theme-manager:destroy theme-factory/awesome-blog
Result:
This theme will be delete. Are you sure? (yes/no):
> yes
Theme "theme-factory/awesome-blog" deleted.
Set theme status
Update specific theme status.
$ php artisan theme-manager:status theme-factory/awesome-blog true|false
Update all themes statuses.
$ php artisan theme-manager:status all true|false
Folder Structure
vendor-x
, vendor-y
, and vendor-z
are theme vendors.
All themes will be in their own vendor folder. Each vendor folder contains can multiple themes.
Theme folder structure must be like this:
⚠️ Also, this folder structure required for remote theme managment. (In the future we will add support for store, update, licensing features).
.
└── src
├── app
├── bootstrap
├── config
├── database
├── ...
├── {themes}
├── vendor-x
│ ├── my-awesome-theme
│ ├── your-awesome-theme
│ ├── ...
├── vendor-y
│ ├── banana
│ ├── cerry
│ ├── apple
│ ├── orange
│ ├── ...
├── vendor-z
│ ├── other-theme
│ ├── other-other-theme
│ ├── ...
├── ...