fabricio872/api-modeller
fabricio872/api-modeller is a Laravel/PHP package for defining and generating API models, helping you scaffold consistent resources and speed up backend development. It streamlines model setup so you can focus on building endpoints and business logic.
This is a small, single-author package with no dependents and no release since mid-2022. Treat the source as the documentation — it is a handful of files, and reading src/ end-to-end will take less time than searching for a tutorial that does not exist.
Pin before you install. The last tag is 2022-06-29, so constrain the version explicitly and check the composer.json PHP constraint against your app (a 2022 package will likely target PHP 7.4/8.0, which matters if you are on 8.2+):
composer require fabricio872/api-modeller:"^<version-from-packagist>"
Read these first, in this order: the base model/abstract class the package ships (this is where field mapping and hydration live), the "modeller"/translator entry point that turns a decoded API response into model instances, and any interface you are expected to implement on your own classes. Those three files define the entire contract.
Confirm what it is not. There is no service provider, no facade, no publishable config, and no Laravel-specific integration. It is a plain PHP library; wiring it into the container is your job.
First use case — one read-only endpoint. Pick a single foreign API call you already make that returns an associative array you then index by string keys everywhere (a currency lookup, an address/geocode response, a carrier rate quote). Define one model class for it, hydrate it once, and replace the array plumbing in that one place. Do not start by modelling a whole third-party API surface.
One model class per foreign resource, one client per foreign API. Keep the HTTP layer yours (Guzzle or Laravel's Http facade) and hand the decoded array to the modeller. The package should never know about base URLs, auth headers, or retries.
// app/Models/Foreign/CurrencyRate.php
class CurrencyRate extends /* package base model */ {
// map remote keys -> typed properties; see src/ for the exact
// attribute/interface convention this package expects
}
// app/Services/ForeignApi/CurrencyClient.php
class CurrencyClient
{
public function rate(string $base, string $quote): CurrencyRate
{
$payload = Http::baseUrl(config('services.rates.url'))
->get("/latest", ['base' => $base, 'symbols' => $quote])
->throw()
->json();
return $this->modeller->hydrate(CurrencyRate::class, $payload);
}
}
Bind the modeller as a singleton. It is stateless configuration, so register it once in a service provider and inject it. This also gives you a single place to swap in a subclass later if you need to change hydration behaviour.
Keep foreign models out of your domain. These classes are DTOs for someone else's schema, and they will drift when that schema changes. Convert them at the boundary into your own models/entities. That single rule is what makes the package safe to adopt: an upstream field rename touches one mapper, not your controllers, Blade views, and jobs.
Hydrate collections in one call. If the remote endpoint returns a list, hydrate the whole list rather than looping one request per item — there is almost certainly no lazy loading or batching built in, so a per-item loop becomes an N+1 against a third party you do not control.
Cache aggressively. Foreign API data is a good fit for Cache::remember keyed on the request parameters, with the hydrated model serialized (or the raw payload cached and re-hydrated). You are paying a network round trip for data that usually changes hourly at most.
Test against captured fixtures. Store real JSON responses in tests/fixtures/ and hydrate from those. This is the only reliable regression test for a package that is not maintained — when an upstream API changes shape, you add a fixture and the failure is visible in CI rather than in production.
app/Support/ under the MIT licence rather than depending on Packagist — for a library this small, vendoring removes the entire supply-chain and abandonment risk.config/api-modeller.php to publish, so any base URLs, timeouts, or API keys are entirely your own config.null where you expect a string. Check how the hydration path handles absent keys before you trust a typed property — with no declare(strict_types=1) guarantees in an old package, you may get silent nulls in non-nullable properties.src/ before designing around it.{"data": {...}} vs the bare object). Log the decoded array and the hydrated model side by side; do not assume the modeller is broken.composer.json, and if you keep the dependency, add a quarterly check for whether the upstream API changed shape or whether a fork has appeared. Given the metrics, plan for the day you replace it — which is why the boundary/conversion pattern above matters more than any feature of the package itself.How can I help you explore Laravel packages today?