Skip to content

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:

ProviderPurpose
AppServiceProviderInterface bindings (AI, image moderation)
RepositoryServiceProviderData and config repositories
MetaBuilderServiceProviderSEO meta builders
EventServiceProviderEvents and Socialite provider registration
HorizonServiceProviderHorizon (email access from admin → Access, /admin-panel/system/access)
RouteServiceProviderRoute file loading

Adding a Service Binding

In AppServiceProvider::register():

php
$this->app->bind(MyServiceInterface::class, MyService::class);
// or
$this->app->singleton(AnotherService::class);

Adding an OAuth Provider

  1. Install a package from SocialiteProviders
  2. Register a Listener in EventServiceProvider:
php
protected $listen = [
    SocialiteWasCalled::class => [
        'SocialiteProviders\\MyProvider\\MyProviderExtendSocialite',
    ],
];
  1. Add fields in AuthSettingsController and resources/js/Admin/Pages/Settings/Auth/Edit.vue
  2. Store Client ID / Secret in the config table

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

  1. Migration — add a record to config:
php
DB::table('config')->insert([
    'key' => 'my_feature',
    'value' => json_encode(['enabled' => false]),
]);
  1. Interfaceapp/Repositories/Config/Interfaces/GetMyFeatureRepositoryInterface.php

  2. Implementationapp/Repositories/Config/GetMyFeatureRepository.php

  3. Binding in RepositoryServiceProvider:

php
$this->app->bind(
    GetMyFeatureRepositoryInterface::class,
    GetMyFeatureRepository::class
);
  1. Controllerapp/Http/Controllers/Admin/MyFeatureSettingsController.php

  2. Vue pageresources/js/Admin/Pages/Settings/MyFeature.vue

  3. Route in routes/admin.php

  4. Section in config/admin_sections.php (key like settings/my-feature) and menu item in AppSidebar.vue

Actions

New business operations as Action classes:

php
namespace App\Actions\MyFeature;

class DoSomethingAction
{
    public function execute(DoSomethingDTO $dto): Result
    {
        // business logic
    }
}

Call from a controller:

php
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.

bash
php artisan make:command MyCommand

Middleware

bash
php artisan make:middleware MyMiddleware

Register in app/Http/Kernel.php (globally or in route groups).

Events & Listeners

bash
php artisan make:event PostPublished
php artisan make:listener NotifySubscribers --event=PostPublished

Register in EventServiceProvider::$listen.

Observers

php
// AppServiceProvider::boot()
Post::observe(PostObserver::class);

Adding an Admin Panel Section

  1. Add a key to config/admin_sections.php:
php
'settings/my-section' => 'My Section',
  1. Add a menu item to resources/js/Admin/Layout/AppSidebar.vue

  2. Create a controller and route in routes/admin.php:

php
Route::get('/admin-panel/my-section', [MySectionController::class, 'index']);
  1. Create an Inertia page in resources/js/Admin/Pages/

Swappable Drivers

Example: adding a new AI provider:

  1. Implement AiServiceInterface from app/Contracts/
  2. Register it in AiServiceProvider with a config condition
  3. Add selection fields to AI Settings (/admin-panel/ai-settings); DEEPSEEK_* env vars are used as fallback before admin configuration is saved

Local Packages

Via Composer path repository:

json
{
    "repositories": [
        {
            "type": "path",
            "url": "./packages/my-package"
        }
    ]
}

Register the package's Service Provider in config/app.php.

Routes

FileRoute type
routes/web.phpPublic and authenticated
routes/admin.phpAdmin-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.

Released under the MIT License.