Summary
The features.media_library flag in config/ink.php switches the featured-image field on PostResource from FileUpload to SpatieMediaLibraryFileUpload. However, the package's Post model does not implement Spatie\MediaLibrary\HasMedia or use InteractsWithMedia — so enabling the flag with spatie/laravel-medialibrary installed will crash at upload time (no getMedia() / addMediaFromRequest() etc.).
Repro
In a host app:
```bash
composer require relaticle/ink spatie/laravel-medialibrary
```
```php
// config/ink.php
'features' => [
'media_library' => true,
],
```
Open Filament admin → create post → attach featured image → save. Crashes:
```
Method Relaticle\Ink\Models\Post::addMediaFromRequest does not exist
```
Why it's tricky
You can't conditionally implement an interface in PHP. Three options:
Option A — always implement HasMedia (simplest, most invasive)
Add implements HasMedia + use InteractsWithMedia to Models\Post.php and add spatie/laravel-medialibrary to `composer.json`'s `require` (or at least `suggest` + a hard runtime check).
Pros: zero-config for users who enable the flag.
Cons: forces medialibrary as a hard dep on all consumers (a few MB of vendor) even when they don't use it.
Option B — provide a swappable model
Introduce `Ink::usePostModel(YourPost::class)` (mirrors how `Sanctum::usePersonalAccessTokenModel()` works). Consumers who want MediaLibrary extend the base `Post` and add the trait themselves:
```php
class Post extends \Relaticle\Ink\Models\Post implements HasMedia
{
use InteractsWithMedia;
}
```
Pros: clean architecture, no forced dep, consistent with Laravel ecosystem patterns.
Cons: users have to write 6 lines of glue to enable a "feature flag."
Option C — remove the flag, document the override
Drop `features.media_library` from config. Document that consumers who want MediaLibrary should override `PostResource::featuredImageField()` (or the whole resource) in their app.
Pros: least invasive.
Cons: loses the drop-in story.
Recommendation
Option B. Patterns like `Sanctum::usePersonalAccessTokenModel()` and `Jetstream::useTeamModel()` are well-established in Laravel-land. The 6 lines of glue are the right place to pay the conditional-trait cost.
Sketch
```php
// src/Ink.php (new)
namespace Relaticle\Ink;
class Ink
{
public static string $postModel = Models\Post::class;
public static string $categoryModel = Models\Category::class;
public static string $tagModel = Models\Tag::class;
public static function usePostModel(string \$model): void
{
static::\$postModel = \$model;
}
}
```
Then PostResource / MCP tools / etc. read `Ink::$postModel` instead of hardcoding `Models\Post::class`.
Discovered while
Wiring `relaticle/ink` into Relaticle (`relaticle/relaticle` PR #210). We have `spatie/laravel-medialibrary` installed and would benefit from `SpatieMediaLibraryFileUpload` for featured images, but the flag isn't usable as-is.
Summary
The
features.media_libraryflag inconfig/ink.phpswitches the featured-image field onPostResourcefromFileUploadtoSpatieMediaLibraryFileUpload. However, the package'sPostmodel does not implementSpatie\MediaLibrary\HasMediaor useInteractsWithMedia— so enabling the flag withspatie/laravel-medialibraryinstalled will crash at upload time (nogetMedia()/addMediaFromRequest()etc.).Repro
In a host app:
```bash
composer require relaticle/ink spatie/laravel-medialibrary
```
```php
// config/ink.php
'features' => [
'media_library' => true,
],
```
Open Filament admin → create post → attach featured image → save. Crashes:
```
Method Relaticle\Ink\Models\Post::addMediaFromRequest does not exist
```
Why it's tricky
You can't conditionally implement an interface in PHP. Three options:
Option A — always implement HasMedia (simplest, most invasive)
Add
implements HasMedia+use InteractsWithMediatoModels\Post.phpand addspatie/laravel-medialibraryto `composer.json`'s `require` (or at least `suggest` + a hard runtime check).Pros: zero-config for users who enable the flag.
Cons: forces medialibrary as a hard dep on all consumers (a few MB of vendor) even when they don't use it.
Option B — provide a swappable model
Introduce `Ink::usePostModel(YourPost::class)` (mirrors how `Sanctum::usePersonalAccessTokenModel()` works). Consumers who want MediaLibrary extend the base `Post` and add the trait themselves:
```php
class Post extends \Relaticle\Ink\Models\Post implements HasMedia
{
use InteractsWithMedia;
}
```
Pros: clean architecture, no forced dep, consistent with Laravel ecosystem patterns.
Cons: users have to write 6 lines of glue to enable a "feature flag."
Option C — remove the flag, document the override
Drop `features.media_library` from config. Document that consumers who want MediaLibrary should override `PostResource::featuredImageField()` (or the whole resource) in their app.
Pros: least invasive.
Cons: loses the drop-in story.
Recommendation
Option B. Patterns like `Sanctum::usePersonalAccessTokenModel()` and `Jetstream::useTeamModel()` are well-established in Laravel-land. The 6 lines of glue are the right place to pay the conditional-trait cost.
Sketch
```php
// src/Ink.php (new)
namespace Relaticle\Ink;
class Ink
{
public static string $postModel = Models\Post::class;
public static string $categoryModel = Models\Category::class;
public static string $tagModel = Models\Tag::class;
}
```
Then PostResource / MCP tools / etc. read `Ink::$postModel` instead of hardcoding `Models\Post::class`.
Discovered while
Wiring `relaticle/ink` into Relaticle (`relaticle/relaticle` PR #210). We have `spatie/laravel-medialibrary` installed and would benefit from `SpatieMediaLibraryFileUpload` for featured images, but the flag isn't usable as-is.