erdiko/core
Erdiko core is a lightweight PHP framework providing MVC scaffolding, routing, validation, and reusable components for building web applications. It bundles configurable services, database access, and templating so developers can ship structured PHP apps quickly.
The first thing a Laravel developer needs to internalize: erdiko/core is not a Laravel package. It is the core of a standalone PHP micro-framework. composer require erdiko/core inside a Laravel app will install code, but there is no service provider, no facade, no config publishing, and no integration surface. You do not "use" it in Laravel; you either run it as its own application or you don't run it at all.
Minimal steps to get your bearings:
composer.json first. It pins the 2017 dependency stack (slim/slim 2.x, Twig 1.x/2.x, Monolog, Doctrine DBAL, Symfony components). That pin list is the real compatibility contract — check it against your PHP version before anything else.public/index.php (or the skeleton app's front controller). That single file shows you bootstrapping: autoload → Erdiko\Core\Application (or Bootstrap::boot()) → run().src/Erdiko/Core/Application.php, Bootstrap.php, Controller.php, View.php, Config.php, and Model/DBMySQL.php. That is 80% of the framework in six files.app/config/ next. application.json, routes.json, and any environment-specific overrides are where behavior actually lives.First use case to prove the loop: define a controller action, wire a route in app/config/routes.json, render a Twig view, and return JSON from a second action. If you can do that, you understand the framework. Do it inside a Docker container on PHP 5.6 or 7.1 — not your host's PHP 8.
// public/index.php (typical shape)
require __DIR__ . '/../vendor/autoload.php';
$app = new \Erdiko\Core\Application();
$app->run();
// app/controllers/Hello.php
namespace app\controllers;
use Erdiko\Core\Controller;
class Hello extends Controller
{
public function getIndex()
{
return $this->getView('hello/index', ['name' => 'World']);
}
}
Actions are HTTP-method prefixed (getIndex, postSave), not Laravel-style __invoke or Route::get closures. That mental shift trips people up immediately.
Bootstrapping as the primary pattern. Everything flows from the front controller. There is no kernel, no HTTP kernel lifecycle, no middleware stack in the Laravel sense — Slim 2 handles request dispatch and Erdiko wraps it. If you need cross-cutting behavior (auth, logging), you either subclass Controller or hook the bootstrap, not a pipeline.
Routing via config, not code. Routes live in app/config/routes.json (or a PHP array), mapping paths to controller\action strings. There is also a default /controller/action/args convention when no explicit route matches. Keep route definitions in config and treat them as the app's contract — there is no route:list equivalent to introspect them, so document them yourself.
Controllers returning views or data. Erdiko\Core\Controller gives you helpers for views, requests, and responses. The idiom is to return either a rendered View object or a JSON/response object. Keep controllers thin — the framework's View/Theme layer wants presentation data, and its models want persistence, and there is no Eloquent to blur the line for you.
Config is JSON files with merge order. Erdiko::getConfig('application') pulls merged config from app/config/, with environment-specific files layered on top. This is the closest analogue to Laravel's config/*.php, but without caching, without env() helpers, and without validation — a typo in JSON silently changes behavior. Read the config class before assuming override order.
Models are DBAL/PDO wrappers, not ORM. Erdiko\Core\Model\DBMySQL wraps a Doctrine DBAL connection. You write SQL. There are no migrations, no relationships, no query builder sugar worth relying on. If you're porting from Laravel, this is where most of the day-to-day friction lives.
DI via erdiko/di. Later Erdiko versions add a lightweight container (Erdiko\DI\Container). Bind services there rather than instantiating in controllers, but understand it is a registry, not Laravel's auto-resolving container — no contextual binding, no interface autowiring.
Integration with a Laravel codebase (if you must). Do not embed the framework. Run the Erdiko app as a separate service and communicate over HTTP or a shared database. If you only need one utility (image handling, mailer), copy that class into your Laravel app rather than pulling the whole core — the transitive dependency pin is the problem, not the individual class.
Testing. PHPUnit works, but the static Erdiko:: accessor and global config make pure unit testing awkward. Test controllers through the front controller (integration-style) and keep business logic in plain classes you can instantiate directly.
Erdiko:: facade is a trap. It is a global registry, not a container. Every call to Erdiko::getConfig() or similar is hidden state that makes tests order-dependent. Wrap it behind an injected interface in any code you intend to keep.ErrorHandler is opinionated; if debugging feels blind, check application.json for the environment flag and the error handler config before assuming the framework is broken.db/migrations/ folder of numbered .sql files and apply them in order — it is the only sane substitute.routes.json. On the plus side, no route:clear incantation; on the downside, no performance lever.Theme/View layer; services go in erdiko/di. There is no event dispatcher worth building on.composer.lock, base your container image on php:7.1-cli (or 5.6), and add your own audit for the pinned Symfony/Slim/Twig CVEs. Upgrading those dependencies independently is not supported.View/templates → Blade, DBAL models → Eloquent or a repository layer over the same SQL. Because the framework is small, a strangler-fig rewrite is realistic; because it is archived, it is also overdue.How can I help you explore Laravel packages today?