← Back to Core Modules | ← Back to Table of Contents |
4.5 View Patterns
This section documents the View layer architecture and patterns used throughout the KMP system. The View layer handles presentation logic, template rendering, helper utilities, and reusable UI components through CakePHP’s view cells.
Overview
The KMP view system is built on CakePHP’s MVC architecture with several enhancements:
- AppView: Base view class with UI framework integration
- KmpHelper: Custom helper for KMP-specific UI components
- View Cells: Reusable UI components for complex widgets
- Template System: Hierarchical template structure with layouts
- Bootstrap Integration: UI framework integration through BootstrapUI plugin
4.5.1 View Classes
AppView - Base View Class
The AppView
class serves as the foundation for all views in the KMP system, providing consistent initialization of helpers, UI components, and application-specific functionality.
AjaxView - AJAX Response View
The AjaxView
extends AppView
specifically for AJAX responses, providing JSON response handling and the ajax
layout.
Architecture
<?php
namespace App\View;
class AjaxView extends AppView
{
protected string $layout = 'ajax';
public function initialize(): void
{
parent::initialize();
$this->response = $this->response->withType('application/json');
}
}
Features
- Automatic JSON response type: Sets response content type to
application/json
- AJAX-specific layout: Uses
ajax.php
layout for minimal output - Inherits AppView functionality: All helpers and configuration from AppView
4.5.2 AppView - Base View Class
The AppView
class serves as the foundation for all views in the KMP system, providing consistent initialization of helpers, UI components, and application-specific functionality.
Architecture
<?php
namespace App\View;
use BootstrapUI\View\UIViewTrait;
use Cake\View\View;
class AppView extends View
{
use UIViewTrait; // Bootstrap UI integration
public function initialize(): void
{
// Helper initialization and configuration
}
}
Key Features
Helper Integration
The AppView automatically loads essential helpers:
- AssetMix.AssetMix: Asset versioning and compilation integration
- Authentication.Identity: User authentication context
- Bootstrap.Modal: Modal dialog components
- Bootstrap.Navbar: Navigation components
- Url: URL generation and manipulation
- Kmp: Custom KMP-specific helper
- ADmad/Glide.Glide: Image processing and optimization
- Tools.Format: Text formatting utilities
- Tools.Time: Time formatting utilities
- Templating.Icon: Icon rendering utilities
- Templating.IconSnippet: Icon snippet utilities
UI Framework Setup
Uses UIViewTrait
to integrate Bootstrap components with automatic:
- Form styling and validation
- Component rendering
- CSS class management
- Responsive design patterns
Configuration Management
Provides centralized configuration for:
- Asset compilation settings
- Image processing options
- UI component defaults
- Security settings
Usage Patterns
All controllers automatically use AppView unless explicitly overridden:
// In controller - automatic AppView usage
public function index()
{
// View variables set here are available in templates
$this->set('data', $this->getData());
}
// Template automatically receives AppView instance with all helpers loaded
4.5.3 KmpHelper - Custom View Helper
The KmpHelper
provides KMP-specific UI components and utilities that extend standard CakePHP functionality.
Core Functionality
Block Management
Manages view content blocks for dynamic template composition:
// Start a content block (note: templates use 'KMP' alias)
$this->KMP->startBlock('sidebar');
// Content goes here...
$this->KMP->endBlock();
Note: In templates, the helper can be accessed as both $this->Kmp
(original case) and $this->KMP
(uppercase), as CakePHP supports both naming conventions. Both are commonly used throughout KMP templates.
Data Conversion Utilities
Provides data format conversion for UI display:
// Convert array data to CSV format
$csvData = $this->Kmp->makeCsv($arrayData);
// Boolean display with icons
$statusIcon = $this->Kmp->bool($isActive, $this->Html);
Advanced Form Controls
Creates complex form components not available in standard CakePHP:
// Auto-complete control with AJAX search
echo $this->Kmp->autoCompleteControl(
$this->Form,
'member_name', // Input field name
'member_id', // Hidden result field
'/members/search', // AJAX endpoint
'Select Member', // Label
true, // Required
false, // Allow custom values
2, // Minimum characters
['class' => 'custom-input'] // Additional attributes
);
// Combo box with predefined options
echo $this->Kmp->comboBoxControl(
$this->Form,
'branch_name',
'branch_id',
$branches, // Data array
'Select Branch',
true, // Required
true, // Allow other values
['data-validation' => 'branch']
);
Navigation Integration
Renders application navigation using view cells:
// Render main application navigation
echo $this->Kmp->appNav($navigationStructure, $currentUser, $navbarState);
Application Settings Access
Provides template-level access to application configuration:
// Get single setting
$siteName = $this->Kmp->getAppSetting('site.name', 'KMP');
// Get multiple related settings
$emailSettings = $this->Kmp->getAppSettingsStartWith('email.');
Asset Management Integration
Provides direct access to AssetMix functionality for versioned assets:
// Get versioned script URL
$scriptUrl = $this->Kmp->getMixScriptUrl('app.js', $this->Url);
// Get versioned style URL
$styleUrl = $this->Kmp->getMixStyleUrl('app.css', $this->Url);
Integration Patterns
With CakePHP Forms
// Standard form with KMP enhancements (note template alias KMP vs Kmp)
echo $this->Form->create($member);
echo $this->Form->control('sca_name');
echo $this->KMP->autoCompleteControl(
$this->Form,
'branch_search',
'branch_id',
'/branches/autocomplete'
);
echo $this->Form->button('Save');
echo $this->Form->end();
With Bootstrap Components
// Enhanced form with Bootstrap styling
echo $this->Form->create($entity, ['class' => 'needs-validation']);
// KMP helper automatically integrates with Bootstrap styling
echo $this->KMP->comboBoxControl(/* parameters */);
// Boolean display with Bootstrap icons
echo $this->KMP->bool($entity->active, $this->Html, [
'class' => 'text-success'
]);
Security Considerations
The KmpHelper includes security features:
- Input sanitization for all form controls
- CSRF token integration for AJAX requests
- XSS prevention in data display
- Safe HTML generation for all components
4.5.4 View Cells - Reusable UI Components
View cells provide reusable, testable components for complex UI widgets that require their own logic and templates.
AppNavCell - Application Navigation
Renders the main application navigation with dynamic content and permissions.
Architecture
<?php
namespace App\View\Cell;
use App\Model\Entity\Member;
use Cake\View\Cell;
class AppNavCell extends Cell
{
public function display(array $appNav, Member $user, array $navBarState = []): void
{
$this->set(compact('appNav', 'user', 'navBarState'));
}
}
Features
- Permission-based visibility: Menu items shown based on user permissions
- Dynamic badges: Shows counts for pending items (notifications, approvals, etc.)
- State persistence: Remembers expanded/collapsed states
- Responsive design: Adapts to mobile and desktop layouts
- Plugin integration: Automatically includes plugin navigation items
Usage
// In template or helper
echo $this->cell('AppNav', [
$navigationStructure, // Navigation menu structure
$currentUser, // Current user entity for permissions
$navbarState // Saved navbar state (expanded sections, etc.)
]);
Template Integration
The cell uses its own template file (templates/cell/AppNav/display.php
):
// Cell template has access to all variables passed to display()
<nav class="navbar navbar-expand-lg">
<?php foreach ($appNav as $section): ?>
<?php if ($this->Identity->can('view', $section)): ?>
<!-- Navigation item rendering -->
<?php endif; ?>
<?php endforeach; ?>
</nav>
NavigationCell - Dynamic Navigation Widget
Provides automatic navigation rendering based on the NavigationRegistry system that organizes menu items hierarchically.
Architecture
<?php
namespace App\View\Cell;
use App\Services\NavigationRegistry;
use Cake\View\Cell;
class NavigationCell extends Cell
{
public function display(): void
{
// Automatically gets navigation items from NavigationRegistry
// based on current user and request parameters
$menuItems = NavigationRegistry::getNavigationItems($user, $params);
$menu = $this->organizeMenu($menuItems);
$this->set(compact('menu'));
}
}
Features
- Automatic navigation generation: Uses NavigationRegistry to get available menu items
- Permission-based filtering: Only shows items user has permission to access
- Hierarchical organization: Organizes items into parent/child/grandchild structure
- Active state detection: Automatically highlights current page/section
- Plugin integration: Includes navigation items from all active plugins
- Dynamic menu structure: Three-level hierarchy (parent/children/sublinks)
Usage
// Automatic navigation rendering - no parameters needed
echo $this->cell('Navigation');
// The cell automatically:
// - Gets current user from request identity
// - Fetches navigation items from NavigationRegistry
// - Organizes items into hierarchical structure
// - Sets active states based on current URL
Note: The NavigationCell::display() method takes no parameters. All data is gathered automatically from the request context and NavigationRegistry.
NotesCell - Notes and Comments Widget
Renders notes, comments, and activity feeds with rich formatting and interaction capabilities.
Features
- Rich text display: Markdown rendering with security filtering
- User attribution: Shows note authors with timestamps
- Interactive elements: Reply, edit, delete actions based on permissions
- Activity tracking: Integration with audit logs and activity feeds
- File attachments: Support for attached files and documents
Usage
// Member profile notes with private note access and creation ability
echo $this->cell('Notes', [
$entity->id, // Entity ID
'Member', // Entity type
true, // View private notes (boolean)
true // Can create notes (boolean)
]);
// Read-only activity feed - no private notes or creation
echo $this->cell('Notes', [
$warrant->id, // Entity ID
'Warrant', // Entity type
false, // No private notes (boolean)
false // Cannot create notes (boolean)
]);
Cell Development Patterns
Standard Cell Structure
<?php
namespace App\View\Cell;
use Cake\View\Cell;
class CustomCell extends Cell
{
// Default options
protected $_defaultConfig = [
'limit' => 10,
'format' => 'list'
];
public function display(array $data = [], array $options = []): void
{
// Merge options with defaults
$options = array_merge($this->_defaultConfig, $options);
// Process data
$processedData = $this->processData($data, $options);
// Set template variables
$this->set(compact('processedData', 'options'));
}
private function processData(array $data, array $options): array
{
// Data processing logic
return $data;
}
}
Template Organization
templates/cell/CustomCell/
├── display.php # Default template
├── list.php # List format template
├── grid.php # Grid format template
└── mobile.php # Mobile-specific template
Integration with Controllers
// In controller
public function view($id)
{
$entity = $this->getEntity($id);
// Cell data can be prepared in controller
$cellData = [
'entity' => $entity,
'permissions' => $this->Authorization->getPermissions($entity),
'options' => $this->getViewOptions()
];
$this->set('cellData', $cellData);
}
4.5.5 Template Architecture
The KMP template system follows CakePHP’s hierarchical structure with application-specific enhancements.
Layout Hierarchy
templates/layout/
├── default.php # Main application layout
├── ajax.php # AJAX response layout
├── error.php # Error page layout
├── turbo_frame.php # Turbo frame layout
├── email/ # Email templates layout
└── TwitterBootstrap/ # Bootstrap-specific layouts
Template Organization
templates/
├── Members/ # Member-related templates
│ ├── index.php # Member listing
│ ├── view.php # Member profile
│ ├── add.php # Member registration
│ └── edit.php # Member editing
├── element/ # Reusable template elements
│ ├── forms/ # Form components
│ ├── navigation/ # Navigation components
│ └── widgets/ # UI widgets
└── cell/ # View cell templates
├── AppNav/ # Navigation cell templates
├── Navigation/ # Generic navigation templates
└── Notes/ # Notes cell templates
Element System
Reusable template elements for common UI patterns:
Form Elements
// templates/element/forms/member_form.php
<div class="member-form">
<?= $this->Form->create($member, ['class' => 'needs-validation']) ?>
<?= $this->Form->control('sca_name', [
'label' => 'SCA Name',
'required' => true,
'help' => 'Your name in the SCA'
]) ?>
<?= $this->Kmp->autoCompleteControl(
$this->Form,
'branch_search',
'branch_id',
'/branches/autocomplete',
'Home Branch'
) ?>
<?= $this->Form->button('Save', ['class' => 'btn btn-primary']) ?>
<?= $this->Form->end() ?>
</div>
Navigation Elements
// templates/element/navigation/sidebar.php
<nav class="sidebar">
<?php foreach ($navigation as $item): ?>
<?php if ($user->checkCan('access', $item['resource'])): ?>
<a href="<?= $this->Url->build($item['url']) ?>"
class="nav-link <?= $item['active'] ? 'active' : '' ?>">
<?= $this->Html->icon($item['icon']) ?>
<?= h($item['title']) ?>
</a>
<?php endif; ?>
<?php endforeach; ?>
</nav>
Responsive Design Patterns
Templates use Bootstrap’s responsive grid system:
<div class="container-fluid">
<div class="row">
<div class="col-md-3 d-none d-md-block">
<!-- Sidebar - hidden on mobile -->
<?= $this->element('navigation/sidebar') ?>
</div>
<div class="col-md-9">
<!-- Main content - full width on mobile -->
<main role="main">
<?= $this->fetch('content') ?>
</main>
</div>
</div>
</div>
4.5.6 Asset Integration
The view layer integrates with the asset compilation system for optimized delivery.
AssetMix Integration
// In templates - automatic asset versioning
<?= $this->AssetMix->css('app') ?>
<?= $this->AssetMix->script('app') ?>
// Multiple script files in order
<?= $this->AssetMix->script('manifest') ?>
<?= $this->AssetMix->script('core') ?>
<?= $this->AssetMix->script('controllers') ?>
<?= $this->AssetMix->script('index') ?>
Image Processing
// Responsive images with Glide
<?= $this->Glide->image('member-photos/' . $member->photo, [
'w' => 300,
'h' => 300,
'fit' => 'crop',
'fm' => 'webp'
]) ?>
// Multiple sizes for responsive design
<picture>
<source media="(min-width: 768px)"
srcset="<?= $this->Glide->image($photo, ['w' => 800]) ?>">
<source media="(min-width: 480px)"
srcset="<?= $this->Glide->image($photo, ['w' => 600]) ?>">
<img src="<?= $this->Glide->image($photo, ['w' => 400]) ?>"
alt="<?= h($alt) ?>" class="img-fluid">
</picture>
4.5.7 Security Patterns
The view layer implements comprehensive security measures.
Input Sanitization
// Automatic HTML escaping
<?= h($userInput) ?>
// Safe HTML with allowed tags
<?= $this->Text->stripTags($content, ['p', 'br', 'strong', 'em']) ?>
// URL validation
<?= $this->Url->build($this->request->getPath()) ?>
CSRF Protection
// Forms automatically include CSRF tokens
<?= $this->Form->create($entity) ?>
<!-- CSRF token automatically added -->
// Manual CSRF token for AJAX
<meta name="csrf-token" content="<?= $this->request->getAttribute('csrfToken') ?>">
Permission-Based Rendering
// Show content based on permissions
<?php if ($user->checkCan("edit", $member)): ?>
<a href="<?= $this->Url->build(['action' => 'edit', $member->id]) ?>"
class="btn btn-primary">Edit</a>
<?php endif; ?>
// Conditional content with fallback
<?php if ($user->checkCan("view_sensitive", $member)): ?>
<p>Sensitive information: <?= h($member->sensitive_data) ?></p>
<?php else: ?>
<p><em>Restricted information</em></p>
<?php endif; ?>
4.5.8 Performance Optimization
View rendering optimizations for large datasets and complex UIs.
Caching Strategies
// Cache expensive view cells
<?= $this->cell('ExpensiveWidget', $data, [
'cache' => [
'key' => 'widget_' . $user->id,
'duration' => '+1 hour'
]
]) ?>
// Cache template fragments
<?php if (($content = $this->cache(['key' => 'member_list'], '+30 minutes')) === null): ?>
<?php $this->cache(['key' => 'member_list'], '+30 minutes'); ?>
<!-- Expensive content generation -->
<?php $this->cache(); ?>
<?php else: ?>
<?= $content ?>
<?php endif; ?>
Lazy Loading
// Stimulus controller for lazy loading
<div data-controller="lazy-load"
data-lazy-load-url-value="/members/partial">
<div class="loading-placeholder">Loading...</div>
</div>
Efficient Data Display
// Pagination for large datasets
<?= $this->Paginator->counter() ?>
<table class="table">
<?php foreach ($members as $member): ?>
<tr>
<td><?= h($member->sca_name) ?></td>
<td><?= h($member->branch->name) ?></td>
<td>
<?php if ($this->Identity->can('view', $member)): ?>
<?= $this->Html->link('View', ['action' => 'view', $member->id]) ?>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?= $this->Paginator->numbers() ?>
4.5.9 Testing View Components
Comprehensive testing strategies for view layer components.
Helper Testing
// Test case for KmpHelper
class KmpHelperTest extends TestCase
{
public function testAutoCompleteControl()
{
$helper = new KmpHelper($this->View);
$result = $helper->autoCompleteControl(
$this->Form,
'member_search',
'member_id',
'/members/search'
);
$this->assertStringContainsString('data-controller="auto-complete"', $result);
$this->assertStringContainsString('data-auto-complete-url-value="/members/search"', $result);
}
}
View Cell Testing
// Test case for AppNavCell
class AppNavCellTest extends TestCase
{
public function testDisplayWithPermissions()
{
$cell = new AppNavCell();
$user = $this->getMockUser();
$nav = $this->getNavigationStructure();
$cell->display($nav, $user);
$result = $cell->render();
$this->assertStringContainsString('Members', $result);
}
}
Template Testing
// Integration test for template rendering
class MemberViewTest extends IntegrationTestCase
{
public function testViewRendersCorrectly()
{
$member = $this->getTestMember();
$this->get("/members/view/{$member->id}");
## 4.5.6 Templates & Layouts
### Layout System Architecture
KMP uses a hierarchical layout system built on CakePHP's template architecture, providing flexible page structure and consistent user experience across the application.
#### Layout Hierarchy
app/templates/layout/
├── default.php # Base HTML layout with asset management
├── ajax.php # Minimal layout for AJAX responses
├── turbo_frame.php # Turbo Frame specific layout
├── error.php # Error page layout
└── TwitterBootstrap/ # Specialized Bootstrap layouts
├── dashboard.php # Administrative dashboard layout
├── view_record.php # Record viewing optimized layout
├── register.php # Registration process layout
├── signin.php # Authentication layout
└── cover.php # Landing page layout
### Core Layouts
#### Default Layout (`default.php`)
The primary layout template providing the base HTML structure for standard pages.
**Features:**
- Block-based content organization with configurable sections
- Laravel Mix asset integration with automatic versioning
- Bootstrap UI framework support with responsive design
- CSRF protection and security headers
- Turbo framework integration for enhanced navigation
- Configurable meta tags and application settings
**Block Structure:**
```php
// HTML element configuration
$this->fetch('html'); // <html> element with language config
$this->fetch('title'); // Page title with branding
$this->fetch('meta'); // Meta tags and favicon
$this->fetch('css'); // Stylesheet loading
$this->fetch('topscript'); // JavaScript core assets
// Body structure
$this->fetch('tb_body_start'); // <body> opening with attributes
$this->fetch('tb_flash'); // Flash message display
$this->fetch('content'); // Main page content
$this->fetch('modals'); // Modal dialog container
$this->fetch('script'); // Additional JavaScript
$this->fetch('tb_body_end'); // </body> closing
Asset Loading Strategy:
// Core assets loaded in head
echo $this->AssetMix->script('manifest'); // Webpack manifest
echo $this->AssetMix->script('core'); // Core utilities
echo $this->AssetMix->script('controllers'); // Stimulus controllers
echo $this->AssetMix->script('index'); // Application entry point
echo $this->AssetMix->css('app'); // Main stylesheet bundle
Dashboard Layout (TwitterBootstrap/dashboard.php
)
Administrative interface layout optimized for member management and administrative workflows.
Features:
- Responsive dashboard interface with collapsible sidebar
- Dynamic header with configurable links and branding
- Integrated navigation system with permission-based menus
- Session extension management with automatic keepalive
- Bootstrap 5 responsive grid system integration
Layout Structure:
<body data-controller="session-extender">
<header class="navbar navbar-dark sticky-top">
<!-- Logo, header links, sign out -->
</header>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2">
<!-- Navigation cell with permissions -->
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10">
<!-- Main dashboard content -->
</main>
</div>
</div>
</body>
Header Configuration:
// Dynamic header links from app settings
$headerLinks = $this->KMP->getAppSettingsStartWith("KMP.HeaderLink.");
// Configuration format:
'KMP.HeaderLink.Reports' => '/reports|btn-primary',
'KMP.HeaderLink.Help.no-label' => '/help|btn-outline-secondary'
View Record Layout (TwitterBootstrap/view_record.php
)
Specialized layout optimized for detailed record viewing with enhanced readability and context.
Features:
- Full-width record display with responsive design
- Contextual navigation with record awareness
- Enhanced spacing and typography for data presentation
- Print-friendly styling considerations
AJAX Layout (ajax.php
)
Minimal layout for AJAX responses and partial content delivery.
Purpose:
- AJAX endpoint responses returning HTML fragments
- Partial page updates and dynamic content loading
- Modal dialog content loading
- Turbo frame content delivery
<?php
// Renders only the content without HTML wrapper
echo $this->fetch("content");
Turbo Frame Layout (turbo_frame.php
)
Optimized for Turbo Drive frame responses with zero overhead.
Features:
- Direct content rendering without wrapper elements
- Turbo Drive frame compatibility
- JavaScript controller state preservation
- Maintains Stimulus.js controller connections
Template Elements
Core Form Controls
Auto Complete Control (element/autoCompleteControl.php
)
Advanced autocomplete functionality with AJAX search capabilities.
echo $this->element('autoCompleteControl', [
'inputField' => 'member',
'resultField' => 'member_id',
'url' => '/members/autocomplete',
'label' => 'Select Member',
'required' => true,
'allowOtherValues' => false,
'minLength' => 2
]);
Features:
- AJAX-powered search with configurable endpoints
- Keyboard navigation (arrow keys, enter, escape)
- Custom value entry support
- Visual feedback with loading indicators
- Bootstrap styling and responsive design
Controller Name: Uses data-controller='ac'
(not ‘auto-complete’)
Combo Box Control (element/comboBoxControl.php
)
Dropdown selection with search/filter capability for predefined data sets.
echo $this->element('comboBoxControl', [
'inputField' => 'status',
'resultField' => 'status_id',
'data' => [
'active' => 'Active',
'inactive' => 'Inactive',
'pending' => 'Pending'
],
'label' => 'Member Status',
'allowOtherValues' => false
]);
Features:
- No AJAX required (embedded JSON data)
- Disabled option support with visual indicators
- Complex data format support
- Keyboard navigation and accessibility
Controller Name: Uses data-controller='ac'
(same controller as autoCompleteControl)
Navigation Components
Turbo Active Tabs (element/turboActiveTabs.php
)
Dynamic tabbed interface with Turbo Frame integration and lazy loading.
echo $this->element('turboActiveTabs', [
'tabs' => [
[
'id' => 'overview',
'label' => 'Overview',
'turboUrl' => '/member/123/overview',
'badge' => 5,
'badgeClass' => 'badge-warning'
],
[
'id' => 'details',
'label' => 'Details',
'turboUrl' => '/member/123/details',
'selected' => true
]
],
'tabGroupName' => 'memberTabs',
'updateUrl' => true
]);
Features:
- Bootstrap tabs with Turbo Frame content loading
- Lazy loading of tab content
- URL state management and browser history
- Badge support for notifications and counters
- Automatic tab selection logic
Copyright Footer (element/copyrightFooter.php
)
Reusable footer with configurable links and branding.
echo $this->element('copyrightFooter', []);
Features:
- Dynamic footer links from application settings
- Automatic copyright year generation
- GitHub Issue Submitter integration
- Responsive Bootstrap layout
Template Organization Patterns
Controller-Specific Templates
Templates are organized by controller in the app/templates/
directory:
app/templates/
├── Members/
│ ├── index.php # Member listing
│ ├── view.php # Member profile
│ ├── add.php # Member registration
│ ├── view_card.php # Member ID card
│ └── auto_complete.php # AJAX autocomplete
├── Branches/
│ ├── index.php # Branch listing
│ ├── view.php # Branch details
│ └── add.php # Branch creation
└── ...
Element Organization
Reusable template components are organized by function:
app/templates/element/
├── autoCompleteControl.php # Form control elements
├── comboBoxControl.php
├── turboActiveTabs.php # UI components
├── copyrightFooter.php
├── nav/ # Navigation components
│ ├── nav_parent.php
│ ├── nav_child.php
│ └── badge_value.php
├── members/ # Entity-specific elements
├── branches/
└── ...
Responsive Design Patterns
Mobile-First Approach
All layouts use Bootstrap’s mobile-first responsive utilities:
// Dashboard sidebar responsive behavior
<nav class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<!-- Collapsible on mobile, fixed on desktop -->
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<!-- Adaptive main content area -->
</main>
Responsive Form Controls
Form elements adapt to screen size with Bootstrap classes:
// Auto-complete control responsive styling
<div class="position-relative mb-3 kmp_autoComplete">
<input class="form-control" type="text">
<ul class="list-group position-absolute col-12">
<!-- Responsive dropdown positioning -->
</ul>
</div>
Asset Integration
Laravel Mix Integration
Templates integrate with Laravel Mix for optimized asset delivery:
// Default layout asset loading
echo $this->AssetMix->css('app'); // Main CSS bundle
echo $this->AssetMix->script('manifest'); // Webpack runtime
echo $this->AssetMix->script('core'); // Core utilities
echo $this->AssetMix->script('controllers');// Stimulus controllers
echo $this->AssetMix->script('index'); // App entry point
Dynamic Asset Loading
// Conditional asset loading
if ($this->request->getParam('controller') === 'Reports') {
echo $this->AssetMix->css('reports');
echo $this->AssetMix->script('reports');
}
Security Patterns
Output Escaping
All dynamic content is properly escaped:
// Safe output in templates
<h1><?= h($member->sca_name) ?></h1>
<div class="description"><?= h($member->description) ?></div>
// Raw HTML only when explicitly safe
<div class="content"><?= $this->KMP->renderSafeHtml($content) ?></div>
CSRF Protection
Forms include CSRF tokens automatically:
// CSRF meta tag in layout
echo $this->Html->meta('csrf-token', $this->request->getAttribute('csrfToken'));
// Form helper automatically includes CSRF fields
echo $this->Form->create($member);
Performance Optimization
Block Management
Efficient content block usage:
// Conditional block rendering
if (!$this->fetch('title')) {
echo $this->KMP->startBlock('title');
echo $this->KMP->getAppSetting('KMP.ShortSiteTitle');
$this->KMP->endBlock();
}
Lazy Loading
Turbo Frames enable lazy loading:
<turbo-frame id="member-details" loading="lazy" src="/members/123/details">
Loading member details...
</turbo-frame>
Development Guidelines
Template Best Practices
- Separation of Concerns: Keep logic in controllers, presentation in templates
- Reusability: Use elements for common UI patterns
- Accessibility: Include proper ARIA labels and semantic HTML
- Performance: Minimize database queries in templates
- Security: Always escape dynamic content
Layout Selection Guidelines
- Default Layout: Standard pages with full navigation
- Dashboard Layout: Administrative interfaces requiring sidebar navigation
- View Record Layout: Detailed record viewing with enhanced readability
- AJAX Layout: Partial content updates and modal dialogs
- Turbo Frame Layout: Progressive enhancement with Turbo Drive
Element Development
- Document Parameters: Clearly document all element variables
- Default Values: Provide sensible defaults for optional parameters
- Error Handling: Graceful degradation for missing data
- Testing: Test elements with various data combinations
- Accessibility: Ensure keyboard navigation and screen reader support
Testing Templates
Integration Testing
public function testMemberViewTemplate()
{
$member = $this->Members->get(1);
$this->get('/members/view/1');
$this->assertResponseOk();
$this->assertResponseContains($member->sca_name);
$this->assertLayout('TwitterBootstrap/view_record');
$this->assertTemplate('Members/view');
}
Element Testing
public function testAutoCompleteElement()
{
$result = $this->View->element('autoCompleteControl', [
'inputField' => 'test',
'resultField' => 'test_id',
'url' => '/test/autocomplete',
'label' => 'Test Field'
]);
$this->assertStringContainsString('data-controller="ac"', $result);
$this->assertStringContainsString('/test/autocomplete', $result);
}
$this->assertResponseOk();
$this->assertResponseContains($member->sca_name);
$this->assertResponseContains('Member Profile');
} } ```
Best Practices
Development Guidelines
- Separation of Concerns: Keep business logic in controllers/models, presentation logic in views
- Security First: Always escape output, validate input, check permissions
- Performance: Use caching for expensive operations, lazy load when appropriate
- Accessibility: Include ARIA labels, keyboard navigation, semantic HTML
- Responsive Design: Mobile-first approach with progressive enhancement
Code Organization
- Helper Organization: Group related methods in helpers, document all public methods
- Cell Usage: Use cells for complex widgets that need their own logic
- Template Structure: Keep templates focused, use elements for reusable components
- Asset Management: Optimize assets, use versioning, minimize HTTP requests
Testing Strategy
- Unit Tests: Test helpers and cell logic in isolation
- Integration Tests: Test complete view rendering with real data
- UI Tests: Test JavaScript interactions and responsive design
- Accessibility Tests: Validate ARIA labels and keyboard navigation
← Back to Core Modules | ← Back to Table of Contents |