Development Guidelines
Overview
ValPress follows a set of strict yet flexible development guidelines to ensure the CMS remains performant, secure, and maintainable. By adhering to these standards, developers can create plugins and themes that integrate seamlessly with the core application and other extensions.
Why It Matters
A consistent coding style and architectural approach prevent technical debt and minimize conflicts between different plugins or themes. Following these guidelines ensures that your code is:
- Interoperable: Works well with the ValPress core and other ecosystem components.
- Maintainable: Easy for you and other developers to understand and update.
- Secure: Protected against common web vulnerabilities.
- Performant: Optimized for high-traffic environments.
How It Works
ValPress leverages Laravel's modern PHP features while maintaining a WordPress-inspired hook system. The architecture promotes decoupling—where components interact through events (actions) and filters rather than direct dependencies. This allows the core to boot, load plugins, and then initialize the theme in a predictable sequence.
Usage
When developing for ValPress, you should integrate these guidelines into your daily workflow:
- Follow Coding Standards: Adhere to PSR-12 and Laravel-specific naming conventions.
- Use Localization: Wrap all user-facing strings in
__()or@lang. - Manage Assets Correctly: Use the
ScriptManagerinstead of hardcoding<script>or<link>tags. - Prioritize Hooks: Use actions and filters to modify behavior rather than overriding core files.
- Validate Updates: Implement
ValidatesUpdateonsrc/Plugin.phporsrc/Theme.phpwhen your extension has update prerequisites. See Plugin Update Validation and Repair Actions.
Code Examples
Correct Asset Enqueueing
Avoid using @push or @stack in your views if the assets should be managed globally. Instead, use the ScriptManager in your plugin or theme's
functions.php.
// In your plugin's main file or theme functions.php
add_action('admin_enqueue_scripts', function () {
// Register and enqueue a CSS file
ScriptManager::registerStyle(
'my-custom-admin-css',
asset('plugins/my-plugin/assets/css/admin.css'),
['version' => '1.0.0']
);
// Register and enqueue a JS file with dependencies
ScriptManager::registerScript(
'my-custom-admin-js',
asset('plugins/my-plugin/assets/js/admin.js'),
['deps' => ['jquery', 'valpress-core'], 'footer' => true]
);
});
Proper Localization
Never hardcode strings. This allows ValPress to automatically support multiple languages.
// In a Controller or Helper
return response()->json([
'message' => __('Record updated successfully!'),
]);
// In a Blade Template
<button type="submit">
{{ __('Save Changes') }}
</button>
Secure Data Handling
Always validate user input and sanitize output to prevent XSS and SQL injection.
// Handling a form submission in a plugin controller
public function store(Request $request)
{
// 1. Validation (Laravel way)
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
]);
// 2. Interaction via Eloquent (Auto-sanitization for DB)
$post = Post::create($validated);
// 3. Filtering output (Use Blade's {{ }} for auto-escaping)
return view('my-plugin::admin.success', compact('post'));
}
Advanced Usage
Decoupling with Custom Hooks
If you are building a complex plugin, provide your own hooks so other developers can extend your functionality without modifying your plugin code.
// Inside your plugin's logic
$data = [
'id' => 1,
'status' => 'pending',
];
// Allow other plugins to modify this data before processing
$data = apply_filters('my_plugin_before_process_data', $data);
// Execute the process
MyService::process($data);
// Notify other components that processing is complete
do_action('my_plugin_after_process_data', $data);
Performance: Efficient Queries
Avoid "N+1" query problems by using Eager Loading when fetching content.
// ❌ Bad: Causes a query for every post to get the author
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name;
}
// ✅ Good: One query for posts, one for authors
$posts = Post::with('author')->get();
Best Practices
- Prefix Everything: Use a unique prefix for your hooks, functions, and CSS classes (e.g.,
acme_) to avoid collisions. - Stay in the Sandbox: Keep your plugin assets inside
public/plugins/{slug}/assets. - Use Type Hinting: Leverage PHP 8+ type hinting for better IDE support and error catching.
- Keep it DRY: Use Laravel's Service Classes for complex logic instead of stuffing everything into
plugin.php. - Documentation: Comment your hooks clearly using PHPDoc tags so others know what parameters are passed.
Common Mistakes
- Modifying Core: Never edit files in
app/Coreorresources/views/admin. Your changes will be lost during updates. - Direct Database Queries: Avoid
DB::statement()unless absolutely necessary. Use Eloquent or the Query Builder for better security and abstraction. - Ignoring CSRF: Always include
@csrfin your forms. ValPress (via Laravel) will reject any POST request without a valid token. - Hardcoding URLs: Use
route(),asset(), orvalpress_get_permalink()instead of hardcoded strings likehttp://mysite.com/page.
Summary
Developing for ValPress means embracing the Laravel ecosystem while respecting the extensible nature of a CMS. By following PSR-12, using the built-in localization and asset management tools, and prioritizing hooks over direct modification, you ensure your contributions are professional, secure, and ready for production.