Theme MVC Pattern
Botble CMS themes follow the MVC (Model-View-Controller) pattern, allowing you to create custom functionality within your theme while maintaining a clean separation of concerns.
Theme Structure
When developing a theme, you can start by using the default theme called Ripple or create a new theme using the theme generator command:
php artisan cms:theme:create <your-theme-name>This will create a new theme with the following structure:
platform/themes/<your-theme-name>/
├── assets/ # Theme assets (CSS, JS, images)
├── functions/ # Theme functions
│ ├── functions.php # Main functions file
│ ├── shortcodes.php # Theme shortcodes
│ └── theme-options.php # Theme options
├── layouts/ # Theme layouts
│ └── default.blade.php # Default layout
├── partials/ # Theme partials
├── routes/ # Theme routes
│ └── web.php # Web routes
├── src/ # Theme PHP classes
│ ├── Http/
│ │ └── Controllers/ # Theme controllers
│ └── Models/ # Theme models
├── views/ # Theme views
├── composer.json # Composer configuration
├── config.php # Theme configuration
└── theme.json # Theme metadataTheme Namespace
Each theme has its own namespace defined in the composer.json file. For example, if your theme is named "Ripple", the namespace will be Theme\Ripple\. This namespace is used for all PHP classes within your theme.
Models
You can create custom models in the platform/themes/<your-theme>/src/Models directory. These models follow standard Laravel Eloquent patterns.
Example model (platform/themes/<your-theme>/src/Models/CustomPost.php):
namespace Theme\YourTheme\Models;
use Illuminate\Database\Eloquent\Model;
class CustomPost extends Model
{
protected $table = 'posts';
protected $fillable = [
'name',
'content',
'status',
];
}Views
Theme views are located in the platform/themes/<your-theme>/views directory. These views use Laravel's Blade templating engine.
Example view (platform/themes/<your-theme>/views/custom-page.blade.php):
<div class="container">
<h1>{{ $title }}</h1>
<div class="content">
{!! $content !!}
</div>
</div>To render a view from your controller:
return Theme::scope('custom-page', ['title' => 'My Page', 'content' => 'Page content']);Controllers
Theme controllers are located in the platform/themes/<your-theme>/src/Http/Controllers directory. These controllers should extend the Botble\Theme\Http\Controllers\PublicController class.
Example controller (platform/themes/<your-theme>/src/Http/Controllers/YourThemeController.php):
namespace Theme\YourTheme\Http\Controllers;
use Botble\Theme\Facades\Theme;
use Botble\Theme\Http\Controllers\PublicController;
use Illuminate\Http\Request;
class YourThemeController extends PublicController
{
public function getCustomPage(Request $request)
{
$title = 'Custom Page';
$content = 'This is a custom page.';
return Theme::scope('custom-page', compact('title', 'content'));
}
public function getAjaxData(Request $request)
{
// Process AJAX request
$data = ['success' => true, 'message' => 'Data loaded successfully'];
return $this->httpResponse()->setData($data);
}
}Routes
Theme routes are defined in the platform/themes/<your-theme>/routes/web.php file. These routes are automatically loaded when the theme is active.
Example routes file (platform/themes/<your-theme>/routes/web.php):
<?php
use Botble\Base\Http\Middleware\RequiresJsonRequestMiddleware;
use Botble\Theme\Facades\Theme;
use Illuminate\Support\Facades\Route;
use Theme\YourTheme\Http\Controllers\YourThemeController;
Theme::registerRoutes(function (): void {
Route::group(['controller' => YourThemeController::class], function (): void {
// Regular routes
Route::get('custom-page', 'getCustomPage')->name('public.custom-page');
// AJAX routes
Route::middleware(RequiresJsonRequestMiddleware::class)
->group(function (): void {
Route::get('ajax/data', 'getAjaxData')->name('public.ajax.data');
});
});
});
// This loads the default theme routes
Theme::routes();Using Theme Functions
Theme functions are defined in the platform/themes/<your-theme>/functions directory. These functions can be used to customize your theme's behavior.
Theme Options
Theme options are defined in functions/theme-options.php:
<?php
use Botble\Theme\Events\RenderingThemeOptionSettings;
app('events')->listen(RenderingThemeOptionSettings::class, function (): void {
theme_option()
->setField([
'id' => 'custom_setting',
'section_id' => 'opt-text-subsection-general',
'type' => 'text',
'label' => __('Custom Setting'),
'attributes' => [
'name' => 'custom_setting',
'value' => null,
'options' => [
'class' => 'form-control',
'placeholder' => __('Enter custom setting'),
],
],
]);
});Shortcodes
Theme shortcodes are defined in functions/shortcodes.php:
<?php
use Botble\Shortcode\Compilers\ShortcodeCompiler;
use Botble\Theme\Facades\Theme;
shortcode()->register('custom-shortcode', __('Custom Shortcode'), __('Custom Shortcode Description'), function (ShortcodeCompiler $shortcode) {
return Theme::partial('shortcodes.custom-shortcode', ['title' => $shortcode->title]);
});Accessing Theme Assets
You can access theme assets using the Theme::asset() helper:
// Get URL to a theme asset
Theme::asset()->url('css/style.css');
// Add a CSS file to the theme
Theme::asset()->usePath()->add('custom-style', 'css/custom-style.css');
// Add a JS file to the footer
Theme::asset()->container('footer')->usePath()->add('custom-script', 'js/custom-script.js');Theme Configuration
Theme configuration is defined in the config.php file. This file allows you to define event listeners for various theme events:
<?php
use Botble\Theme\Theme;
return [
'events' => [
// Before rendering the theme
'beforeRenderTheme' => function (Theme $theme): void {
// Add theme assets
$theme->asset()->usePath()->add('main-css', 'css/main.css');
$theme->asset()->container('footer')->usePath()->add('main-js', 'js/main.js');
},
// Before rendering a specific layout
'beforeRenderLayout' => [
'default' => function (Theme $theme): void {
// Add layout-specific assets
},
],
],
];