morningtrain/php-loader
A lightweight PHP loader for Morningtrain projects that simplifies autoloading and class resolution. It offers a simple, framework-friendly API to register loaders, resolve namespaces, and keep bootstrapping clean. Ideal for Laravel apps needing flexible, explicit loading without extra overhead.
Install it with an exact constraint. With one star and zero dependents, do not rely on a floating version:
composer require morningtrain/php-loader --prefer-dist
Then pin the resolved version or commit in composer.json. If there is no stable tag, use dev-main#<commit-sha>.
Look first at:
composer.json — PHP version, autoloading, dependencies, Laravel auto-discovery.README.md — intended usage and any initialization semantics.src/Loader.php or the package’s single class — confirm:
require or require_once?new $class, a static init(), or an interface method?Because the public API is small and adoption is low, wrap it immediately behind one application-owned class. That gives you a single place to adapt if method names or behavior differ from expectations:
<?php
namespace App\Support;
use MorningTrain\PhpLoader\Loader;
final class ModuleLoader
{
public function __construct(private Loader $loader)
{
}
public function load(string $path): void
{
// Adjust this call to the actual public method in src/Loader.php.
$this->loader->load($path);
}
}
First practical use case: replace scattered bootstrap require calls in a Laravel app. For example, load modular files from app/Modules during application registration:
// AppServiceProvider::register()
$this->app->singleton(ModuleLoader::class, function () {
return new ModuleLoader(new Loader());
});
$this->app->make(ModuleLoader::class)->load(app_path('Modules'));
Keep class initialization out of register(). If the package can instantiate classes, do that in boot() after the container and config are ready.
Split “load files” from “initialize classes.” File inclusion is usually safe in register(); instantiation often needs the container, config, routes, or database. Use register() to require files and boot() to initialize discovered classes.
Use it for module bootstrapping, not autoloading. This package loads PHP files; Composer handles PSR-4 autoloading. A good pattern is one bootstrap file per module:
// app/Modules/Billing/bootstrap.php
return function (Application $app): void {
$app->register(BillingServiceProvider::class);
};
Then let your loader include all bootstrap.php files and invoke the returned closures yourself. This keeps dependency injection and ordering under your control.
If auto-initialization is supported, constrain the classes it can instantiate. Require a marker interface and a no-argument constructor:
interface Bootable
{
public function boot(): void;
}
// Only point the loader at classes implementing Bootable.
If constructors need dependencies, do not use auto-initialization. Load the file, then resolve through Laravel:
app(MyBootstrapper::class)->boot();
Control ordering explicitly. Filesystem iteration order is not guaranteed. Prefix files by priority:
00-register-core.php
10-register-billing.php
20-register-reporting.php
If the package does not sort, sort the file list before passing it in or create one aggregate bootstrap file with explicit calls.
Use environment guards. Load development-only modules conditionally:
if (app()->environment('local', 'testing')) {
$moduleLoader->load(app_path('Modules/Debug'));
}
Test with temporary fixture directories. Create files in tests/fixtures/modules, assert they were included, assert classes were or were not initialized, and clean up with require_once behavior in mind. This is especially important because the package has little external usage.
Keep a replacement path. The package is a thin wrapper around PHP inclusion. If maintenance stops, replacing it with an internal helper is trivial:
foreach (glob(app_path('Modules/*/bootstrap.php')) as $file) {
require_once $file;
}
Do that if the package adds no meaningful behavior beyond require_once.
require can fatal with “Cannot declare class.” Use the package only for side-effect files or ensure it uses require_once.app_path(), base_path(), or __DIR__-based paths.register() can fail silently or throw container errors. Move it to boot() unless the class is completely stateless.return value unless you have confirmed the loader preserves it.get_included_files() and class_exists() to verify what happened.composer dump-autoload -o and test a fresh deploy; classmap behavior differs from development.src/ before use, and consider copying the class into app/Support with MIT attribution if it is genuinely small. That is often lower risk than depending on a one-star package in a critical bootstrap path.ModuleLoader wrapper so the package remains replaceable.How can I help you explore Laravel packages today?