Advanced Usage Guide
This guide covers advanced patterns and customization techniques for the Alxarafe microframework.
Module Creation
Modules are the primary organizational unit in Alxarafe. A module is a directory within Modules/ (application) or src/Modules/ (framework core) following the PSR-4 namespace convention:
- Namespace:
Modules\{ModuleName}\Controller. - Directory:
Modules/{ModuleName}/Controller/. - Naming: Files must be named
{Action}Controller.php.
Bare Minimum Module
To register a new module, you only need one controller with a #[ModuleInfo] attribute in any of its classes (usually the main controller).
namespace Modules\Blog\Controller;
use Alxarafe\Base\Controller\Controller;
use Alxarafe\Attribute\ModuleInfo;
#[ModuleInfo(name: 'Blog', description: 'Simple blog module', icon: 'fas fa-blog')]
class PostController extends Controller {
// ...
}Hook System
Alxarafe implements a powerful synchronous hook system (HookService) allowing you to intercept framework logic or create your own extension points.
Registering a Hook
Hooks should be registered during the application bootstrap.
use Alxarafe\Service\HookService;
use Alxarafe\Service\HookPoints;
HookService::register(
HookService::resolve(HookPoints::AFTER_SAVE, ['entity' => 'Post']),
function($post) {
// Clear blog cache after saving a post
Cache::forget('blog_posts');
}
);Creating Custom Hooks
You can define your own hooks in your business logic:
// Execute an action hook
HookService::execute('blog.before_publish', $post);
// Use a filter hook to modify a value
$content = HookService::filter('blog.content_filter', $content);Custom Fields & Components
The programmatic UI assembly can be extended by creating custom AbstractField or AbstractContainer subclasses.
Creating a Custom Field
- Extend
Alxarafe\Component\AbstractField. - Implement
getType(). - Create a matching Blade template in
templates/form/{component_name}.blade.php.
namespace Modules\MyModule\Component;
use Alxarafe\Component\AbstractField;
class ColorPicker extends AbstractField {
protected string $component = 'colorpicker';
public function getType(): string { return 'color'; }
}View Prioritization
When ViewController::render($view) is called, the framework searches for the template in the following order:
- Theme:
APP_PATH/themes/{ActiveTheme}/templates/{view}.blade.php - Module (App):
APP_PATH/Modules/{CurrentModule}/Templates/{view}.blade.php - App Shared:
APP_PATH/templates/{view}.blade.php - Module (Core):
ALX_PATH/src/Modules/{CurrentModule}/Templates/{view}.blade.php - Framework Core:
ALX_PATH/templates/{view}.blade.php
This hierarchy allows you to override core framework UI without modifying the vendor/ or framework core files.
JWT & API Security
Alxarafe uses JSON Web Tokens (JWT) for stateless API authentication.
Token Lifecycle
- Login: POST to
/api/admin/loginreturns a JWT signed with thesecurity.jwt_secret_keyfromconfig.json. - Authorization: Include the token in the request header:
Authorization: Bearer <token>. - Verification:
ApiDispatcherautomatically validates the signature and expiration.
Securing Endpoints
Use the #[RequireRole] or #[RequirePermission] attributes on your API controller methods.
#[ApiRoute(path: 'posts', method: 'POST')]
#[RequirePermission(permission: 'Blog.Post.doCreate')]
public function createAction($data) {
// ...
}Internationalization (i18n)
Translations are handled by Alxarafe\Lib\Trans and stored in YAML files.
Directory Structure
Modules/Blog/Lang/en.yamlModules/Blog/Lang/es.yaml
Usage in Code
Trans::_('key', ['param' => 'value']);Usage in Blade
{{ $me->trans('key') }}Hierarchy Fallback
The translator resolves keys in the following order:
- Destination locale (e.g.,
es_ES). - Parent locale (e.g.,
es). - Fallback locale (e.g.,
en).