PHP code example of amondar-libs / repository-pattern

1. Go to this page and download the library: Download amondar-libs/repository-pattern 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/ */

    

amondar-libs / repository-pattern example snippets


use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Concerns\HasUuids;

class User extends Model
{
    use HasUuids;

    // fillable or guarded...

    protected function casts(): array
    {
        return [
            'password'  => 'hashed',
            'is_active' => 'boolean',
            'is_admin'  => 'boolean',
        ];
    }
}

use Spatie\LaravelData\Data;

class UserData extends Data
{
    public function __construct(
        public string $name,
        public string $email,
        public ?string $password,
        public bool $is_active,
        public bool $is_admin,
    ) {}
}

use Amondar\RepositoryPattern\Attributes\UseModel;
use Amondar\RepositoryPattern\Repository;

/**
 * @extends Repository<User, UserData>
 */
#[UseModel(User::class)]
readonly class UserRepository extends Repository {}

$repo = new UserRepository();

// Create (array input)
$model = $repo->create([
    'name'      => 'Jane',
    'email'     => '[email protected]',
    'password'  => 'secret',
    'is_active' => true,
    'is_admin'  => false,
]);

// Update (spatie Data input)
$model = $repo->update($model, UserData::from([
    'name'      => 'Jane Roe',
    'email'     => '[email protected]',
    'password'  => null, // your model/service can decide how to treat nulls
    'is_active' => false,
    'is_admin'  => true,
]));

// Query builder passthrough
$activeAdmins = $repo->where('is_active', true)
                    ->where('is_admin', true)
                    ->orderBy('name')
                    ->get();

$repo = new UserRepository();

// Will NOT fire creating/created/updating/updated/etc. model events
$user = $repo->quietly->create([
    'name'      => 'Silent User',
    'email'     => '[email protected]',
    'password'  => '123456',
    'is_active' => true,
    'is_admin'  => false,
]);

$repo = new UserRepository();

// Wrap a single method call inside DB::transaction(...)
$user = $repo->transaction->create([
    'name'      => 'Tx User',
    'email'     => '[email protected]',
    'password'  => '123456',
    'is_active' => true,
    'is_admin'  => false,
]);

$repo = new UserRepository();

$user = $repo->transaction->quietly->create([
    'name'      => 'Stealth Tx User',
    'email'     => '[email protected]',
    'password'  => '123456',
    'is_active' => true,
    'is_admin'  => false,
]);

$repo = new UserRepository();

$user = $repo->transaction->forUpdate(1, function(User $user, UserRepository $repository){
    // do Some logic under SELECT FOR UPDATE lock.
});

Schema::create('some_versioned', function (Blueprint $table) {
    $table->...->primary();
    //...
    // Add custom field to test with attribute.
    $table->versionable('version_field');
    //or
    $table->versionable('version_field')->index()->nullable()->...;
    //...
});

use Illuminate\Database\Eloquent\Model;
use Amondar\RepositoryPattern\Concerns\HasOptimisticLock;
use Amondar\RepositoryPattern\Attributes\VersionField;
use Amondar\RepositoryPattern\Contracts\Lockable;

#[VersionField('version')]
class Post extends Model implements Lockable
{
    use HasOptimisticLock;

    protected $fillable = ['title', 'body'];
}

use Amondar\RepositoryPattern\Exceptions\OptimisticLockException;

$post = Post::create(['title' => 'Hello', 'body' => '...']); // version = 1

$a = $post->fresh();
$b = $post->fresh();

$a->title = 'A';
$a->save(); // version becomes 2

$b->title = 'B';

try {
    $b->save(); // throws OptimisticLockException (stale version: 1 vs current: 2)
} catch (OptimisticLockException $e) {
    // handle or retry logic
}

// Bypass the optimistic lock when you are sure it is safe
$b->title = 'B';
$b->saveUnlocked();            // 1) bypass via helper
Post::unlocked(fn() => $b->save()); // 2) or run within an unlocked callback

use Amondar\RepositoryPattern\Attributes\UseModel;
use Amondar\RepositoryPattern\Repository;

/**
 * @extends Repository<Post>
 */
#[UseModel(Post::class)]
readonly class PostRepository extends Repository {}

$repo = new PostRepository();

$model = $repo->create(['title' => 'Hello', 'body' => '...']); // version = 1
$stale = $model->fresh();

$model = $repo->update($model, ['title' => 'A']); // version = 2

// Throws OptimisticLockException because $stale has version = 1
$repo->update($stale, ['title' => 'B']);

// Bypass optimistic locking via the higher-order proxy
$repo->unlocked->update($stale, ['title' => 'B']); // succeeds without changing version semantics

use Amondar\RepositoryPattern\Concerns\HasCreateCommand;use Amondar\RepositoryPattern\Concerns\HasUpdateCommand;use Amondar\RepositoryPattern\Service;

/**
 * @extends Service<User, UserData, UserRepository>
 */
readonly class UserService extends Service
{
    /**
     * @use HasCreateCommand<User, UserData, UserRepository>
     * @use HasUpdateCommand<User, UserData, UserRepository>
     */
    use HasCreateCommand, HasUpdateCommand;

    public function __construct(private UserRepository $users) {}

    // Define an abstract repository for target methods (create/update).
    protected function repository(): UserRepository
    {
        return $this->users;
    }

    // Override hooks if needed
}

$service = app(UserService::class);

// Run a service method in a DB transaction
$user = $service->transaction->create(UserData::from([
    'name'      => 'Jane',
    'email'     => '[email protected]',
    'password'  => 'secret',
    'is_active' => true,
    'is_admin'  => false,
]));