Laravel Meta

repository·2.0·Indexed 19 days ago

https://github.com/kodeine/laravel-meta

A package for Laravel 8.x or higher that provides a fluent way to manage extra metadata for Eloquent models using a separate meta table. It allows developers to treat meta attributes as regular model properties via the Metable trait, supporting default values, type casting for arrays, objects, and models, and a comprehensive set of meta-specific lifecycle events.

Tokens
3.6K
Snippets
15
Records
18
Agent score
15%

What's inside laravel-meta

  1. Use Meta-aware lifecycle events for database consistency

    2.0

    Laravel Meta provides additional events that fire only after all associated meta data has been successfully saved to the database. These events do not require the HasMetaEvents trait and follow standard Laravel event patterns (receiving one parameter: the model instance).

    These are useful when you need to perform actions (like dispatching a queue job) that depend on the meta data being present in the database. Standard Laravel events like created or updated might fire before the meta data is actually persisted.

    Event Names

    • createdWithMetas
    • updatedWithMetas
    • savedWithMetas
  2. Enable and use Meta Events in Eloquent Models

    2.0

    Laravel Meta dispatches several events that allow you to hook into the lifecycle of meta data. To enable these events, you must include the HasMetaEvents trait in your Eloquent model alongside the Metable trait.

    Available Events

    • metaCreating
    • metaCreated
    • metaSaving
    • metaSaved
    • metaUpdating
    • metaUpdated
    • metaDeleting
    • metaDeleted

    Listener Parameters

    Listeners for these events receive two parameters:

    1. An instance of the model.
    2. The name of the meta that the event occurred for.

    Aborting Operations

    If you return false; within a listener for any event ending in ing (e.g., metaCreating, metaSaving), the operation will be aborted.

    use Kodeine\Metable\Metable;
    use Kodeine\Metable\HasMetaEvents;
    use Illuminate\Database\Eloquent\Model;
    
    class User extends Model
    {
        use Metable, HasMetaEvents;
    }
  3. Configure Meta Table Migrations

    2.0

    Each model requires its own meta table. By default, the table name is the pluralized form of the model name followed by _meta (e.g., posts_meta for a Post model). The foreign key should be the model name plus _id (e.g., post_id).

    If you wish to use a custom table name or foreign key, define them in your model:

    protected $metaTable = 'custom_meta_table';
    protected $metaKeyName = 'custom_foreign_key';

    Example Migration for a Post model:

    Schema::create('posts_meta', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->bigInteger('post_id')->unsigned();
        $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
        $table->string('type')->default('null');
        $table->string('key')->index();
        $table->text('value')->nullable();
        $table->timestamps();
    });
    public function up()
    {
        Schema::create('posts_meta', function (Blueprint $table) {
            $table->bigIncrements('id');
    
            $table->bigInteger('post_id')->unsigned();
            $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
    
            $table->string('type')->default('null');
    
            $table->string('key')->index();
            $table->text('value')->nullable();
    
            $table->timestamps();
        });
    }
  4. Set up the Metable trait in Eloquent Models

    2.0

    To enable meta functionality, add the Metable trait to your model. The trait automatically determines the meta table name based on the model's pluralized name.

    use Kodeine\\Metable\u005cMetable;
    
    class Post extends Eloquent
    {
        use Metable;
    }

    If you need to specify a custom table name, use the $metaTable property:

    use Kodeine\Metable\Metable;
    
    class Post extends Eloquent
    {
        use Metable;
        protected $metaTable = 'posts_meta'; // optional
    }
  5. Listen for Meta Events

    2.0

    There are three ways to listen for meta events in your application:

    1. Defining the $dispatchesEvents property

    You can map specific meta events to custom event classes directly on the model.

    2. Using Closures in the booted method

    You can use static magic methods like static::metaCreated(...) within the model's booted method to define logic via closures. Note that closures receive both the model and the meta name.

    3. Using Observers

    You can create a dedicated Observer class. The method names in the observer should match the meta event names (e.g., metaCreated). Observers receive the model and the meta name as parameters.

    // 1. Using $dispatchesEvents
    class User extends Model
    {
        use Metable, HasMetaEvents;
    
        protected $dispatchesEvents = [
            'metaSaved' => UserMetaSaved::class,
        ];
    }
    
    // 2. Using Closures
    class User extends Model
    {
        use Metable, HasMetaEvents;
    
        protected static function booted()
        {
            static::metaCreated(function ($user, $meta) {
                // logic here
            });
        }
    }
    
    // 3. Using Observers
    class UserObserver
    {
        public function metaCreated(User $user, $meta)
        {
            // logic here
        }
    }
  6. Upgrade to Laravel Meta v2

    2.0

    To upgrade from a master version to ^2.0, update your composer.json and run composer update.

    Breaking Changes in v2:

    • Laravel 7 or lower is no longer supported.
    • __get, __set, and __isset methods are removed. If you use them in your model, remove the as operator (e.g., change __get as __metaGet to __get).
    • Legacy getters (e.g., getSomething()) can no longer be accessed via property magic (e.g., $model->something). You must call the method directly: $model->getSomething().
    • setAttribute now overrides the parent method.
    • getMetaDefaultValue was renamed to getDefaultMetaValue.
    • The second parameter of getMeta is now the default value returned when a meta is null.
    • whereMeta was replaced by the scopeWhereMeta scope.
    • getModelKey was removed.
  7. Manage MetaData value types and casting

    2.0

    The MetaData model automatically handles type casting for various PHP data types when setting or retrieving values. When you set a value via the value attribute, the model detects the type and stores it accordingly. Supported types include:

    • array: Stored as a JSON-encoded string.
    • object: Stored as a JSON-encoded string.
    • datetime: Stored as a formatted string and cast back to a DateTime instance upon retrieval.
    • model: Stores the class name and the model's primary key (e.g., ClassName#ID). Upon retrieval, it resolves the specific Eloquent model instance.
    • boolean, integer, double, float, string, NULL: Standard scalar types.

    If a type is not recognized in the internal dataTypes list, it defaults to string.

  8. Configure default meta values

    2.0

    You can define default values for meta attributes using the $defaultMetaValues array.

    Behavior:

    1. If a meta attribute does not exist in the database, the default value is returned instead of null.
    2. If you attempt to set a meta attribute to its defined default value, the corresponding row in the meta table will be removed (causing the default value to be returned via rule 1).

    Note: Use lowercase keys.

    public $defaultMetaValues = [
        'is_user_home_sick' => false,
    ];
  9. Disable fluent meta access

    2.0

    If you want to prevent the package from intercepting property access (e.g., to use standard Laravel behavior for attributes that happen to share names with metas), add the $disableFluentMeta property to your model.

    class Post extends Eloquent
    {
        protected $disableFluentMeta = true;
    }

    When disabled, $post->content, unset($post->content), and isset($post->content) will behave as standard Eloquent attributes and will not interact with the meta table. To access meta data when this is enabled, you must use getAttributeRaw and setAttributeRaw.

  10. Unset meta data from a model

    2.0

    To remove meta entries, you can use fluent unset, the unsetMeta method, or pass multiple keys to unsetMeta.

    Fluent unset:

    unset($post->content);
    $post->save();

    Using unsetMeta:

    $post->unsetMeta('content');
    $post->save();

    Multiple metas:

    // Using delimiters
    $post->unsetMeta('content,views');
    $post->unsetMeta('content|views');
    
    // Using multiple arguments
    $post->unsetMeta('content', 'views');
    
    // Using an array
    $post->unsetMeta(['content', 'views']);
    $post->save();
    $post->unsetMeta(['content', 'views']);
    $post->save();