composer require novius/laravel-meta
addMeta() macro to your migration:
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('text');
$table->timestamps();
$table->addMeta(); // Adds meta table and foreign key
});
HasMeta trait in your model:
use Novius\LaravelMeta\Traits\HasMeta;
class Post extends Model {
use HasMeta;
}
$post = Post::first();
$post->setMeta(['custom_field' => 'value']);
$post->meta->custom_field; // Access via relationship
For a blog post model, leverage the built-in SEO fields:
$post->seo_title = 'Optimized Title';
$post->seo_description = 'Meta description for SEO';
$post->canBeIndexedByRobots(); // Set robots meta
Model Integration:
HasMeta trait to any Eloquent model.getMetaConfig() for custom defaults (e.g., fallback titles, image paths).Metadata Operations:
$model->setMeta(['key' => 'value']) or $model->meta->key = 'value'.updateMeta() for mass assignments.setMetaRules() for custom validation logic.Querying:
$model::indexableByRobots() or $model::whereMeta('key', 'value') (via raw queries if needed).$model->with('meta') to avoid N+1 queries.Frontend Integration:
CurrentModel facade to pass metadata to views:
CurrentModel::setModel($post);
@include('laravel-meta::meta') // Renders SEO/OpenGraph tags
Nova/Filament:
NovaResourceHasMeta or FilamentResourceHasMeta traits to auto-generate admin panels for metadata fields.getSEONovaFields() or getFormSEOFields().Events:
meta.saving or meta.saved events for pre/post-processing:
$model->meta->save(function ($meta) {
$meta->normalizeKeys(); // Example custom logic
});
Testing:
HasMeta trait in unit tests:
$model = new class extends Model {
use HasMeta;
};
Performance:
addMeta() uses a JSON column, which can bloat storage and slow queries. For high-traffic models, consider a dedicated meta table with normalized columns.whereJsonContains) unless indexed. Use raw SQL or scopes for performance-critical paths.Configuration:
getMetaConfig(): If not defined, the trait uses defaults, which may not suit all use cases (e.g., fallbackTitle).ogImageDisk or ogImagePath in getMetaConfig() will break image URL generation.AGPL License:
Migration Risks:
addMeta() to an existing table requires downtime or a zero-downtime strategy (e.g., adding a new column first).Missing Metadata:
meta table exists and the foreign key is set up correctly.getMetaConfig() (e.g., undefined callbacks).SEO Tag Issues:
php artisan tinker to inspect metadata:
$post->meta->toArray(); // Check raw data
$post->og_image_url; // Should return a valid URL
Query Problems:
DB::enableQueryLog() to identify bottlenecks.Custom Metadata Types:
casts or accessors.Validation:
setMetaRules():
public function setMetaRules(): array {
return [
'seo_keywords' => 'required|string|max:255',
];
}
Query Builder:
public function scopePublished($query) {
return $query->whereMeta('status', 'published');
}
Caching:
$meta = Cache::remember("meta_{$model->id}", 60, function () use ($model) {
return $model->meta;
});
Multi-Tenancy:
public function getMetaTable() {
return 'tenant_' . tenant()->id . '_' . parent::getMetaTable();
}
How can I help you explore Laravel packages today?