1. Go to this page and download the library: Download crucialdigital/metamorph library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
namespace App\Models;
use CrucialDigital\Metamorph\Models\BaseModel;
class Post extends BaseModel
{
/**
* Fields used for full-text search via the `term` query parameter.
* These are matched with a LIKE query.
*/
public static function searchField(): array
{
return ['title', 'content'];
}
/**
* The model attribute used as the human-readable label
* when this model is referenced by another entity (resource / selectresource).
*/
public static function label(): string
{
return 'title';
}
// Optional overrides ↓
/**
* The attribute returned as the `value` in resource dropdowns.
* Defaults to 'id' if not overridden.
*/
public static function labelValue(): string
{
return 'id';
}
/**
* Extra dot-notation fields to
namespace App\Repositories;
use App\Models\Post;
use CrucialDigital\Metamorph\DataRepositoryBuilder;
use MongoDB\Laravel\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
class PostRepository extends DataRepositoryBuilder
{
/**
* Return the base query builder for the Post entity.
* Metamorph will apply all filters, search, pagination, and ordering on top of this.
*/
public function builder(): Builder
{
// Example: always scope to the authenticated user's school
return Post::where('ecole_id', Auth::user()->ecole_id);
}
}
// config/metamorph.php
return [
// Global API route prefix → api/metamorph/...
'route_prefix' => 'metamorph',
// Directory where .json data models are stored
'data_model_base_dir' => database_path('models'),
// Eloquent model registry: entity key => FQCN
'models' => [
'post' => \App\Models\Post::class,
'user' => \App\Models\User::class,
],
// Repository registry: entity key => FQCN (optional per entity)
'repositories' => [
'post' => \App\Repositories\PostRepository::class,
],
// Entities available as resource dropdowns in data model inputs
'resources' => [
['label' => 'Users', 'entity' => 'user'],
['label' => 'Categories', 'entity' => 'category'],
],
// Global middleware applied to all Metamorph routes
'middlewares' => ['auth:sanctum'],
// Per-model middleware (see Advanced section)
'model_middlewares' => [],
// Laravel Gate policies to enforce per model (see Advanced section)
'policies' => [],
// Upload path prefix inside Laravel Storage
'upload_path' => env('APP_NAME', 'metamorph'),
// Redis cache groups per entity (see Advanced section)
'caches' => [],
];
// app/Policies/PostPolicy.php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
public function viewAny(User $user): bool
{
return true; // Everyone authenticated can list postsu
}
public function view(User $user, Post $post): bool
{
return true;
}
public function create(User $user): bool
{
return $user->hasRole('editor');
}
public function update(User $user, Post $post): bool
{
return $user->id === $post->author_id || $user->hasRole('admin');
}
public function delete(User $user, Post $post): bool
{
return $user->id === $post->author_id || $user->hasRole('admin');
}
public function forceDelete(User $user, Post $post): bool
{
return $user->hasRole('admin');
}
public function restore(User $user, Post $post): bool
{
return $user->hasRole('admin');
}
}
// app/Providers/AuthServiceProvider.php
use App\Models\Post;
use App\Policies\PostPolicy;
protected $policies = [
Post::class => PostPolicy::class,
];
// config/metamorph.php
'cache' => [
'enabled' => true,
'ttl' => 3600, // Global TTL (1 hour)
// Multi-tenant configuration
// 'auto' checks header first, then user attribute, then 'global'
'tenant_mode' => 'auto',
'tenant_header' => 'X-Tenant-Id',
'tenant_field' => 'ecole_id',
// Enable caching specifically for the following entities
'entities' => [
'post' => true, // Enabled with global TTL
'category' => 7200, // Enabled with specific TTL (2 hours)
'user' => false, // Explicitly disabled
],
],