Extending the Codebase
JournalPHP is built on standard Laravel mechanisms. You can add new functionality without forking — through Service Providers, Events, Middleware, and custom code.
Service Providers
Providers are registered in config/app.php → providers:
| Provider | Purpose |
|---|---|
AppServiceProvider | Interface bindings (AI, image moderation) |
RepositoryServiceProvider | Data and config repositories |
MetaBuilderServiceProvider | SEO meta builders |
EventServiceProvider | Events and Socialite provider registration |
HorizonServiceProvider | Horizon (email access from admin → Access, /admin-panel/system/access) |
RouteServiceProvider | Route file loading |
Adding a Service Binding
In AppServiceProvider::register():
$this->app->bind(MyServiceInterface::class, MyService::class);
// or
$this->app->singleton(AnotherService::class);Adding an OAuth Provider
- Install a package from SocialiteProviders
- Register a Listener in
EventServiceProvider:
protected $listen = [
SocialiteWasCalled::class => [
'SocialiteProviders\\MyProvider\\MyProviderExtendSocialite',
],
];- Add fields in
AuthSettingsControllerandresources/js/Admin/Pages/Settings/Auth/Edit.vue - Store Client ID / Secret in the
configtable
Supported OAuth providers: Google, Yandex, VKontakte, Facebook, Apple, GitHub. One Tap (Google, Yandex) is configured on the same page.
Repository Pattern
Adding a New Admin Panel Setting
- Migration — add a record to
config:
DB::table('config')->insert([
'key' => 'my_feature',
'value' => json_encode(['enabled' => false]),
]);Interface —
app/Repositories/Config/Interfaces/GetMyFeatureRepositoryInterface.phpImplementation —
app/Repositories/Config/GetMyFeatureRepository.phpBinding in
RepositoryServiceProvider:
$this->app->bind(
GetMyFeatureRepositoryInterface::class,
GetMyFeatureRepository::class
);Controller —
app/Http/Controllers/Admin/MyFeatureSettingsController.phpVue page —
resources/js/Admin/Pages/Settings/MyFeature.vueRoute in
routes/admin.phpSection in
config/admin_sections.php(key likesettings/my-feature) and menu item inAppSidebar.vue
Actions
New business operations as Action classes:
namespace App\Actions\MyFeature;
class DoSomethingAction
{
public function execute(DoSomethingDTO $dto): Result
{
// business logic
}
}Call from a controller:
public function store(MyRequest $request, DoSomethingAction $action)
{
$result = $action->execute(DoSomethingDTO::fromRequest($request));
return back();
}Artisan Commands
New commands go in app/Console/Commands/. They are auto-loaded via $this->load() in Kernel.php.
php artisan make:command MyCommandMiddleware
php artisan make:middleware MyMiddlewareRegister in app/Http/Kernel.php (globally or in route groups).
Events & Listeners
php artisan make:event PostPublished
php artisan make:listener NotifySubscribers --event=PostPublishedRegister in EventServiceProvider::$listen.
Observers
// AppServiceProvider::boot()
Post::observe(PostObserver::class);Adding an Admin Panel Section
- Add a key to
config/admin_sections.php:
'settings/my-section' => 'My Section',Add a menu item to
resources/js/Admin/Layout/AppSidebar.vueCreate a controller and route in
routes/admin.php:
Route::get('/admin-panel/my-section', [MySectionController::class, 'index']);- Create an Inertia page in
resources/js/Admin/Pages/
Swappable Drivers
Example: adding a new AI provider:
- Implement
AiServiceInterfacefromapp/Contracts/ - Register it in
AiServiceProviderwith a config condition - Add selection fields to AI Settings (
/admin-panel/ai-settings);DEEPSEEK_*env vars are used as fallback before admin configuration is saved
Local Packages
{
"repositories": [
{
"type": "path",
"url": "./packages/my-package"
}
]
}Register the package's Service Provider in config/app.php.
Routes
| File | Route type |
|---|---|
routes/web.php | Public and authenticated |
routes/admin.php | Admin-only |
Laravel Sanctum is installed, but routes/api.php does not exist.
Forking
The MIT license allows any modifications in a fork. For significant customizations, fork and work in a separate repository. Merge updates from the main repository via git merge upstream/master.