italofantone/commentable
A Laravel package that adds polymorphic commenting to Eloquent models. Attach comments to any model via a simple trait, with a customizable comment model and straightforward integration into existing applications.
Install and publish
composer require <vendor>/<package>:^1.2
php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider"
php artisan migrate
Publish tags are usually split — publish config first, then migrations, so the migration picks up your user-table settings rather than the package defaults.
Look here first
config/<package>.php — this is now the single source of truth for the user model binding (new in 1.2.1). Confirm the key (typically user_model or models.user) points at the right class before doing anything else.Vendor\Package\PackageServiceProvider — 1.2.1 moved configuration integration here (mergeConfigFrom + publish registration). Read register() and boot() to understand the boot order, because that ordering now matters for model resolution.User model to implement.First use case
Wire the package to your User model, then read a related collection through the package's relationship with eager loading enabled:
// config/<package>.php
'user_model' => App\Models\User::class,
$users = config('<package>.user_model')::query()
->with('<packageRelationship>')
->paginate(50);
If that renders without extra queries per row, the 1.2.1 relationship-loading optimization is doing its job and you're on the happy path.
Dynamic user model — configure, don't hardcode
The whole point of the 1.2.1 change is that you should never use App\Models\User inside your package integration code. Resolve through config:
// app/Providers/AppServiceProvider.php
public function register(): void
{
$this->app->bind(
\Vendor\Package\Contracts\UserResolver::class,
fn () => new (config('<package>.user_model'))
);
}
This is what makes multi-guard apps (admin vs. customer), multi-tenant setups, and test doubles work without forking the package.
Relationship loading — lean on eager loading, not lazy 1.2.1 optimizes how the package loads its relationships, but the optimization only pays off when you give it a set to work with. Standard pattern:
// Good: one query for the parents, one for the relation
$posts = Post::with('user.<packageRelationship>')->get();
// Bad: the optimization can't batch what it never sees coming
$posts->each(fn ($p) => $p->user-><packageRelationship>);
Service provider integration — publish in staging, cache in production
Because config is now merged in the provider, the package boots with sane defaults even if you never publish. In staging, publish and diff against the package's config/<package>.php so you know exactly which keys you own. In production, run php artisan config:cache as part of deploy — the merged defaults are baked in either way.
Testing pattern Override the model binding per-test rather than globally:
protected function setUp(): void
{
parent::setUp();
config(['<package>.user_model' => Tests\Fixtures\CustomUser::class]);
}
Then assert query counts with DB::enableQueryLog() or DB::listen() to lock in the 1.2.1 eager-loading behaviour as a regression test.
user_model in .env or config and forget php artisan config:cache → you'll still resolve the old class, with confusing "relation not found" errors. Clear cache on every deploy that touches this key.UserResolver in a package register() that runs after this one, you'll get the wrong instance. Do bindings in AppServiceProvider::register() and never in boot().users (or has a non-standard primary key type — UUID/ULID), regenerate the package migration rather than editing it after the fact. The package's user_model config doesn't rewrite the migration's FK target.Model::preventLazyLoading(! app()->isProduction()) while integrating. The 1.2.1 optimization can mask a latent N+1 in your code by making the package's own relation cheap.config('...user_model')::query() is opaque to PHPStan/Psalm. Add a @return class-string<Model> phpdoc, or wrap it in a small repository class, so with('<packageRelationship>') doesn't degrade to mixed.user_model to a model that is the package's related model (e.g. a User-to-User follow graph) is supported, but relationship names can collide. Alias them explicitly in your with() calls.Config::set() calls you made in a service provider are now redundant and may execute before the package merges its defaults — remove them and re-test on a clean config:cache.How can I help you explore Laravel packages today?