pinoox/pincore
Pinoox Pincore is the lightweight core of the Pinoox PHP framework, offering routing, MVC structure, dependency injection, modular packaging, and essential utilities for building fast, maintainable web applications with minimal configuration. Composer-ready and designed for simple, scalable PHP deve...
composer require pinoox/pincore. The framework boots from index.php/pinoox CLI entrypoint rather than Laravel's artisan.config/ — app.config.php, database.config.php, router.config.php define app identity and transport.apps/{package}/ — each app has app.php, router.php, Controller/, Model/, Component/, theme/, migration/.vendor/pinoox/pincore/src/ — Component/ (App, Router, Dispatch, Database, Dir), Portal/, Support/ are the extension points you will actually touch.apps/com_example/ with app.php ('package' => 'com_example', 'enable' => true).router.php using Router::get('home', 'HomeController@index').Portal/Home/ with routes.php and a controller, then hit /com_example/home (or the app's default portal).php pinoox app:list and php pinoox route:list (CLI names vary slightly by minor version — check php pinoox output).App-as-module layout. Treat each app under apps/ as a self-contained module: models, controllers, components (services), migrations, and themes live together. Cross-app calls are the normal integration path, not a smell.
Cross-app model/service usage (the v3.14.12 headline). Because sub-app PSR-4 namespaces are now auto-discovered and registered into the class loader at runtime, you can reference another app's classes directly:
use Pinoox\App\com_shop\Model\Product; // discovered, no composer edits
use Pinoox\App\com_shop\Component\Cart;
$product = Product::find($id);
$cart = App::container()->get(Cart::class);
This removes the old composer.json autoload.psr-4 block per app. In practice:
com_shop → Pinoox\App\com_shop). Discovery is name-driven, so a mismatch silently yields "class not found".app.php ('container' => [...] or via boot), not in the consumer.Portals as route bundles. Each portal (Portal/{Name}/) owns its own routes.php, controllers, and theme. Use one portal per surface (e.g. admin, api, site) rather than branching inside controllers. Portals are the cleanest place to swap themes and middleware per audience.
Universal relative discovery. Candidate folder discovery now resolves via relative paths, so keep all discovery inputs relative (default apps/ root, or a relative override in config). This is what makes the same config work on Linux, macOS, and Windows. Do not bake absolute paths (/var/www/..., C:\...) into app.config.php or discovery settings.
Routing workflow. Define routes with the Router facade in router.php, group with Router::group(['prefix' => 'v1'], ...), and resolve controller actions with Controller@method. Use route names + url() for links so portal/app prefixes stay out of templates.
Data layer. Use the framework's DB/Model layer (built on Laravel's Eloquent-style components) with per-app migrations under migration/. Keep table prefixes per app (shop_, blog_) so apps can be installed/dropped independently.
Theming. Themes are resolved through the app's theme directory with portal-scoped fallbacks (theme/{theme}/portal/{portal}/). Override templates at the most specific level and let the fallback chain handle the rest.
Testing hooks. Boot a minimal app instance in tests and pull services from the container; when you're testing cross-app behavior, assert that the namespace resolved on the first call — that catches discovery regressions early.
_ide_helper-style autoload file — don't "fix" it by re-adding composer.json entries, that reintroduces the manual step the release removed.php pinoox cache:clear or equivalent). Always clear after mkdir apps/com_new/.package name, or a folder whose casing differs from the namespace (e.g. Com_Shop vs com_shop), will resolve on Linux but fail or mis-resolve on case-insensitive macOS/Windows filesystems. Enforce lowercase package names.DIRECTORY_SEPARATOR concatenation and hard-coded leading slashes in custom code. Also be wary of symlinked apps/ directories — relative resolution can behave differently when the working directory is resolved through a symlink.composer dump-autoload -o and warm the caches so the framework isn't scanning directories on every request. Profile a cold request after upgrading to confirm no regression.composer.json PSR-4 entries is now optional but recommended; do it in the same commit as the upgrade and run a full route + container boot smoke test to catch classes that were previously resolving only via Composer.enable => true, (3) app cache cleared, (4) composer dump-autoload, (5) discovery root config relative and correct. Ninety percent of cases are step 1.Component\Dir for path resolution, Component\App for app registration/boot, and the container binding in app.php — these three cover most custom behavior you'd otherwise hack into the bootstrap.How can I help you explore Laravel packages today?