Laravel Ownable

v2.0

Automated Ownership Management

A powerful Laravel package to handle ownership relationships between Eloquent models with zero configuration on models, automatic API responses, and dynamic registration.

Key Features

Everything you need to manage ownership relationships in your Laravel application

Hands-off Integration

No traits or interfaces required. Works with any Eloquent model out of the box.

Automatic API Attachment

Automatically inject ownership information into your JSON responses via middleware

Ownership History

Keep track of ownership changes over time with historical records

Dynamic Registration

Register ownable models through config or dedicated API endpoints at runtime

Blade Directive

Simple @owns directive for quick ownership checks in your Blade views

Built-in API

Ready-to-use endpoints for managing ownership and registrations

Requirements

Make sure your environment meets these requirements

PHP Version

PHP ^8.3 or higher

Laravel Version

Laravel ^12.0

Installation

Get started with Laravel Ownable in just a few steps

Step 1

Install via Composer

Add the package to your Laravel project using Composer:

composer require sowailem/ownable
Step 2

Run Migration

Execute the migration to create the database tables:

php artisan migrate

Usage Guide

Learn how to manage ownership without modifying your models

1. Basic Operations

The Owner facade is your primary tool for managing ownership relationships. No traits or interfaces required on your models!

Giving Ownership

Assign ownership of any model to another. This automatically handles marking previous ownerships for that entity as inactive.

use Sowailem\Ownable\Facades\Owner;

// A User owning a Post
Owner::give($user, $post);

// A Team owning a Project
Owner::give($team, $project);

Checking Ownership

Quickly verify if a specific owner currently owns an entity:

use Sowailem\Ownable\Facades\Owner;

if (Owner::check($user, $post)) {
    // Authorized
}

Transferring Ownership

Transfer ownership from one entity to another:

use Sowailem\Ownable\Facades\Owner;

Owner::transfer($oldOwner, $newOwner, $post);

Retrieving Current Owner

Get the actual model instance of the current owner:

$owner = Owner::currentOwner($post); // Returns User, Team, etc.

2. Automatic API Attachment

This is the most powerful feature of the package. The AttachOwnershipMiddleware is automatically registered globally. It recursively scans your JSON responses and injects ownership data for any model registered as "ownable".

How it works:

  • It looks for Eloquent models in your JsonResponse.
  • It checks if the model class is registered in config/ownable.php or via the dynamic API.
  • If matched, it fetches the current owner and appends it to the JSON object.

Registration:

Add models to your configuration:

'ownable_models' => [
    \App\Models\Post::class,
    \App\Models\Comment::class,
],

JSON Response Example:

Original Response

{
    "id": 1,
    "title": "Hello World"
}

Enhanced Response (Automatic)

{
    "id": 1,
    "title": "Hello World",
    "ownership": {
        "id": 45,
        "owner_id": 1,
        "owner_type": "User",
        "ownable_id": 1,
        "ownable_type": "Post",
        "is_current": true,
        "owner": {
            "id": 1,
            "name": "John Doe"
        }
    }
}

Customization:

Change the injection key in config/ownable.php:

'automatic_attachment' => [
    'enabled' => true,
    'key' => 'meta_ownership',
],

3. Blade Directive

Check ownership directly in your views with the @owns directive:

@owns($user, $post)
    <button>Edit Post</button>
@else
    <span>Read Only</span>
@endowns

API Reference

Complete reference for all available methods and classes

Owner Facade

Static methods available via the Owner facade:

Owner::give($owner, $ownable)

Give ownership of an ownable entity to an owner.

Parameters: $owner - The owner model, $ownable - The ownable entity
Returns: \Sowailem\Ownable\Models\Ownership

Owner::check($owner, $ownable)

Check if an owner owns a specific ownable entity.

Parameters: $owner - The owner model to check, $ownable - The ownable entity
Returns: bool

Owner::transfer($fromOwner, $toOwner, $ownable)

Transfer ownership of an ownable entity from one owner to another.

Parameters: $fromOwner - The current owner, $toOwner - The new owner, $ownable - The ownable entity
Returns: \Sowailem\Ownable\Models\Ownership

Owner::currentOwner($ownable)

Get the current owner of an ownable entity.

Parameters: $ownable - The ownable entity
Returns: \Illuminate\Database\Eloquent\Model|null

REST API Endpoints

The package provides built-in endpoints for managing ownership and registrations. These are prefixed with /api/ownable by default.

POST /api/ownable/ownerships/give

Give ownership of an ownable entity to an owner.

Payload: owner_id, owner_type, ownable_id, ownable_type

POST /api/ownable/ownerships/transfer

Transfer ownership from one owner to another.

Payload: from_owner_id, from_owner_type, to_owner_id, to_owner_type, ownable_id, ownable_type

POST /api/ownable/ownerships/check

Check if an owner owns a specific entity.

Payload: owner_id, owner_type, ownable_id, ownable_type

POST /api/ownable/ownerships/remove

Remove ownership of an entity.

Payload: ownable_id, ownable_type

POST /api/ownable/ownerships/current

Get the current owner of an entity.

Payload: ownable_id, ownable_type

GET /api/ownable/ownerships

List and filter ownership history records.

POST /api/ownable/ownable-models

Register a new model class for automatic ownership attachment dynamically.

Payload: name, model_class, description, is_active

Practical Examples

Real-world scenarios and use cases

Examples & Scenarios

A. Multi-Level Ownership

You might have Users owning Projects, and Projects owning Tasks. This is fully supported out of the box.

// User owns Project
Owner::give($user, $project);

// Project owns Task
Owner::give($project, $task);

// Verify hierarchy
if (Owner::check($project, $task)) {
    // Project is the owner of this task
}

B. Middleware Authorization

Protect your routes easily using the Owner facade in your middleware or controllers.

public function update(Request $request, Post $post)
{
    if (!Owner::check($request->user(), $post)) {
        abort(403, 'You do not own this resource.');
    }

    $post->update($request->all());
}

C. Dynamic Registration

Register new models as ownable via the API without modifying your code. Perfect for CMS or highly dynamic applications.

// Request to register a new model class
POST /api/ownable/ownable-models
{
    "name": "Document",
    "model_class": "App\\Models\\Document",
    "description": "Client documents"
}