as3/modlr
A Laravel package for building modular applications. Modlr helps split large projects into self-contained modules with their own routes, views, migrations, config, and service providers, making code easier to organize, extend, and maintain.
as3/modlr is a thin, opinionated REST layer that maps MongoDB collections to EmberJS-compatible JSON endpoints. It is not an ODM with a rich schema layer — think "collection in, JSON out" — so the fastest path is to wire it up once and let it do CRUD for you.
Minimal setup:
composer require as3/modlr
# ensure ext-mongodb (and, if you use the legacy driver path, ext-mongo) is installed
php -m | grep -i mongo
First place to look is the repository README and src/ — the public surface is small, and the constructor options plus the request-dispatch entry point are the only things you really need to internalize. There is no generated documentation site, so treat the examples in the README as the canonical reference and read the class that handles routing/dispatch directly when behaviour is unclear.
Typical bootstrap:
require 'vendor/autoload.php';
use Modlr\Modlr;
$api = new Modlr([
'mongodb' => 'mongodb://127.0.0.1:27017',
'database' => 'myapp',
]);
$api->handle($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
Your first use case should be the simplest possible resource: create a posts collection, insert one document by hand (db.posts.insertOne({title: "hi"})), and GET /posts. If that returns { "posts": [ { "id": "...", "title": "hi" } ] }, the _id→id mapping and pluralization are working and you can build from there. If it returns an empty body or a 404, the problem is almost always routing (the collection name in the URL must match the pluralized collection name) or the connection config, not your document.
One optional extra worth knowing on day one: if you deploy behind NewRelic, install the NewRelic PHP extension and 0.3.24+ will report API errors to NR for you — no extra wiring.
Collection-as-resource. The core pattern is that every MongoDB collection becomes a REST resource automatically. Name your collections the way your Ember models are named (pluralized, lowercase) and you get index/show/create/update/delete for free. Resist the urge to add a mapping layer; if the front end calls /articles, name the Mongo collection articles.
Ember Data payload shape. Responses follow the default Ember RESTAdapter conventions: a single record is wrapped in { "post": { ... } } and a list in { "posts": [ ... ] }. The primary key comes back as id (stringified from _id). This is the whole reason to pick this package over a generic Mongo REST tool — keep your client on the default RESTAdapter/JSONAPISerializer-style config and you avoid a custom serializer.
Sideloading related data. For belongsTo/hasMany relationships, the usual approach is to store related IDs on the document and let Modlr emit them as post_ids / post_id, then use query parameters on your client requests to fetch included records. If you need true sideloading (included / root-level arrays), do it in a small serializer wrapper around the library's output rather than patching the library.
Filtering and query params. Treat query-string filtering as a front-end concern that you translate: either let the client pass the fields Modlr understands, or put a thin controller in front that whitelists parameters and builds the Mongo query. Never pass raw $_GET into a query — Mongo query operators in user input are an injection vector ($where, $gt, etc.).
Integration behind Slim/Lumen. Because Modlr is small, the most maintainable pattern is to mount it inside an existing router rather than letting it own the whole request. Route /api/{resource}[/{id}] to a controller action, instantiate Modlr with a shared connection, and let it handle the payload while Slim handles auth, CORS, and logging. This keeps middleware (JWT checks, rate limiting) out of the library.
Observability. 0.3.24 adds automatic error reporting to NewRelic when the NR PHP extension is present — this is the only built-in observability hook. If you aren't on NewRelic, nothing changes: continue wrapping handle() with your own structured logging, Sentry integration, or metrics middleware around the library boundary.
Embedding vs. referencing. For day-to-day work, embed small child documents (tags, addresses) directly in the parent — they round-trip through Modlr untouched. Use references only for large or independently-queryable collections, and remember that referencing means extra requests from Ember unless you sideload.
Custom endpoints. Modlr handles the CRUD shape; anything else (aggregations, dashboards, auth) belongs in your own controller that reuses the same Mongo connection/database handle. Don't fight the library to add endpoints it wasn't built for.
mongodb driver API drift; PHP 8.1+ may produce deprecation notices or hard failures. Check composer.json for the PHP constraint before adopting on a modern stack.ext-mongodb is a hard requirement, and the library may still reference the legacy MongoClient classes depending on the code path. Verify which driver it targets by grepping for MongoClient vs MongoDB\Driver\Manager before debugging connection errors — a "could not connect" is often a missing extension, not a bad URI.modlr.newrelic toggle or config key. If you expect errors in NR and see none, check extension_loaded('newrelic') first — and note that the underlying Mongo exception detail may still not reach NR if it's swallowed before being classified as an API error._id serialization. ObjectIds are stringified to id on read, but on write you must not send an ObjectId back. When a client PUTs a document with id, ensure the library reconstructs the ObjectId for the _id filter; if updates silently no-op, this is the first thing to check.handle() in a try block and log the underlying Mongo exception — the library still tends to swallow the useful message in the response body.[] rather than a clear "unknown resource" error. Seed your collections (or at least create indexes) in a bootstrap script so 404s mean what you think they mean.GET /posts?author_id=x is a collection scan without an index on author_id. Add your indexes before you ship, not after the first slow query.Bottom line for day-to-day use: reach for as3/modlr when you have a small Ember front end and want trivial CRUD against Mongo without writing controllers — it does that one job cleanly. Treat it as a starting point you will wrap, not a framework you will extend; the surrounding application still owns auth, validation, indexing, and serialization. 0.3.24's NewRelic hook is a nice freebie for observability if you already run the agent, but it doesn't change the overall posture: wrap it, pin it, and plan for an escape hatch.
How can I help you explore Laravel packages today?