1. Go to this page and download the library: Download moffhub/maker-checker 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/ */
moffhub / maker-checker example snippets
use Illuminate\Database\Eloquent\Model;
use Moffhub\MakerChecker\Traits\RequiresApproval;
class Post extends Model
{
use RequiresApproval;
// Optionally specify which actions eate' => ['editor' => 1],
'delete' => ['admin' => 2],
];
}
$post = new Post(['title' => 'My Post', 'user_id' => auth()->id()]);
$saved = $post->save();
if (!$saved && Post::wasIntercepted()) {
$request = Post::getInterceptedRequest();
return response()->json([
'message' => 'Your request has been submitted for approval.',
'request_id' => $request->id,
'request_code' => $request->code,
], 202); // HTTP 202 Accepted
}
// To bypass approval (for admin operations, seeders, etc.):
$post = Post::createWithoutApproval(['title' => 'Direct Create']);
// Or use the callback method:
Post::withoutApprovalDo(function () {
Post::create(['title' => 'Also bypassed']);
});
use Moffhub\MakerChecker\Facades\MakerChecker;
// Create a request (auto-injects auth user as maker)
$request = MakerChecker::create(Post::class, ['title' => 'My Post']);
// With custom description
$request = MakerChecker::create(Post::class, ['title' => 'My Post'], 'Create a new blog post');
// Update a model
$request = MakerChecker::update($post, ['title' => 'Updated Title']);
// Delete a model
$request = MakerChecker::delete($post);
// Execute a custom action
$request = MakerChecker::execute(TransferFunds::class, ['amount' => 5000]);
// Approve (uses authenticated user)
MakerChecker::approve($request);
MakerChecker::approve($request, null, 'admin'); // With role
MakerChecker::approve($request, null, 'admin', 'LGTM'); // With role and remarks
// Or with explicit user
MakerChecker::approve($request, $approver, 'admin');
// Reject
MakerChecker::reject($request);
MakerChecker::reject($request, null, 'Missing information');
// Cancel (only maker can cancel)
MakerChecker::cancel($request);
$request->approve(); // Uses auth user
$request->approve(null, 'admin'); // With role
$request->approve($user, 'admin', 'Approved'); // Explicit user
$request->reject(null, 'Not approved');
$request->cancel();
use Moffhub\MakerChecker\Facades\MakerChecker;
$request = MakerChecker::request()
->toCreate(Post::class, ['title' => 'My Post'])
->madeBy(auth()->user())
->description('Create a new blog post')
->withApprovals(['editor' => 1, 'admin' => 1])
->beforeApproval(fn($r) => Log::info('Approving...'))
->afterApproval(fn($r) => Notification::send(...))
->save();
use Moffhub\MakerChecker\Contracts\MakerCheckerUserContract;
class User extends Authenticatable implements MakerCheckerUserContract
{
public function hasMakerCheckerPermission(string $permission): bool
{
return $this->hasPermission($permission); // Your permission logic
}
public function getMakerCheckerTeamId(): ?int
{
return $this->team_id; // For multi-tenancy, or null
}
public function getMakerCheckerRole(): ?string
{
return $this->role; // e.g., 'admin', 'manager'
}
public function getMakerCheckerEmail(): ?string
{
return $this->email;
}
}
use Moffhub\MakerChecker\Facades\MakerChecker;
use App\Models\Post;
// Create request for a new Post
$request = MakerChecker::request()
->toCreate(Post::class, [
'title' => 'My New Post',
'content' => 'Post content here...',
'user_id' => auth()->id(),
])
->madeBy(auth()->user())
->description('Create a new blog post')
->save();
use Moffhub\MakerChecker\Facades\MakerChecker;
// Simple - uses authenticated user automatically
MakerChecker::approve($request);
MakerChecker::reject($request, null, 'Missing dmin', 'Looks good!');
// Or call directly on the request model
$request->approve();
$request->approve(null, 'admin');
$request->reject(null, 'Not approved');
$request->cancel(); // Only maker can cancel
use Moffhub\MakerChecker\Contracts\ExecutableRequest;
use Moffhub\MakerChecker\Models\MakerCheckerRequest;
class TransferFunds extends ExecutableRequest
{
public function execute(MakerCheckerRequest $request): void
{
$payload = $request->payload;
// Perform the transfer
BankService::transfer(
from: $payload['from_account'],
to: $payload['to_account'],
amount: $payload['amount']
);
}
public function uniqueBy(): array
{
return ['from_account', 'to_account', 'amount'];
}
public function beforeApproval(MakerCheckerRequest $request): void
{
// Validate accounts still exist
}
public function afterApproval(MakerCheckerRequest $request): void
{
// Send notification
}
public function onFailure(MakerCheckerRequest $request): void
{
// Handle failure
}
}
$request->getApprovalCount(); // Total approvals received
$request->getPendingRoles(); // ['admin' => 1, ...] remaining
$request->hasMetApprovalThreshold(); // true/false
// Require approval from a specific user by email
MakerChecker::request()
->toCreate(Contract::class, $data)
->requiringUsersToApprove(['[email protected]'])
->madeBy(auth()->user())
->save();
// Require approval from multiple specific users
MakerChecker::request()
->toCreate(Contract::class, $data)
->requiringUsersToApprove(['[email protected]', '[email protected]'])
->madeBy(auth()->user())
->save();
// Require approval from user by ID
MakerChecker::request()
->toCreate(Contract::class, $data)
->requiringUsersToApprove([(string) $cfoUser->id])
->madeBy(auth()->user())
->save();
// Requires 1 admin approval AND approval from the CFO
MakerChecker::request()
->toCreate(Contract::class, $data)
->withRoleAndUserApprovals(
roles: ['admin' => 1],
users: ['[email protected]']
)
->madeBy(auth()->user())
->save();
// This will throw an exception if the user doesn't exist
MakerChecker::request()
->toCreate(Contract::class, $data)
->requiringUsersToApprove(['[email protected]'])
->madeBy(auth()->user())
->save();
// Throws: RequestCouldNotBeInitiated
// Disable validation if needed (not recommended)
MakerChecker::request()
->toCreate(Contract::class, $data)
->requiringUsersToApprove(['[email protected]'], validateExistence: false)
->madeBy(auth()->user())
->save();
$request = MakerChecker::request()
->toCreate(Contract::class, $data)
->requiringUsersToApprove(['[email protected]'])
->madeBy(auth()->user())
->save();
// Only the CFO can approve - other users will get an error
MakerChecker::approve($request, $cfoUser, 'user'); // Works
MakerChecker::approve($request, $otherUser); // Throws exception
use Moffhub\MakerChecker\Contracts\MakerCheckerConfigurable;
use Moffhub\MakerChecker\Enums\RequestType;
class Post extends Model implements MakerCheckerConfigurable
{
public static function makerCheckerApprovals(): array
{
return [
'create' => ['editor' => 1],
'update' => ['editor' => 1],
'delete' => ['admin' => 1, 'editor' => 1],
];
}
public static function makerCheckerUniqueFields(): array
{
return [
'create' => ['title', 'slug'],
];
}
public static function
$transaction = Transaction::find(1);
// Check if there are pending approvals
$transaction->hasPendingApproval(); // Any action
$transaction->hasPendingApproval(RequestType::DELETE); // Specific action
// Get pending approval requests
$pending = $transaction->getPendingApprovals();
$pendingDeletes = $transaction->getPendingApprovals(RequestType::DELETE);
// Set a specific user as the maker
Transaction::setApprovalMaker($adminUser);
// Operations will use $adminUser as the maker
Transaction::create([...]);
// Reset to use auth()->user() again
Transaction::setApprovalMaker(null);
use Moffhub\MakerChecker\Models\MakerCheckerRequest;
// Get requests visible to current user
$requests = MakerCheckerRequest::visibleTo(auth()->user())->get();
// Users with 'view_any_permission' see all requests
// Others see only their own or their team's requests
// Default behavior: finds users where role = 'admin'
// When request
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Moffhub\MakerChecker\Contracts\ApproverResolver;
use Moffhub\MakerChecker\Models\MakerCheckerRequest;
class CustomApproverResolver implements ApproverResolver
{
public function getApproversForRole(MakerCheckerRequest $request, string $role): Collection
{
// Custom logic: Spatie permissions, team filtering, etc.
return User::role($role)
->where('team_id', $request->team_id)
->where('id', '!=', $request->maker_id)
->get();
}
public function getAllApprovers(MakerCheckerRequest $request): Collection
{
// Get all users who can approve any role or are specifically =', $request->maker_id)
->get();
}
public function getApproverByIdentifier(string $identifier): ?Model
{
return User::where('email', $identifier)
->orWhere('id', $identifier)
->first();
}
public function userExists(string $identifier): bool
{
return $this->getApproverByIdentifier($identifier) !== null;
}
public function validateUsersExist(array $userIdentifiers): array
{
return array_filter($userIdentifiers, fn($id) => !$this->userExists($id));
}
}
// Register in AppServiceProvider
$this->app->bind(ApproverResolver::class, CustomApproverResolver::class);
'notifications' => [
'sequential' => true,
],
// After partial approval, notify next approvers
MakerChecker::approve($request, $user, 'editor');
if ($request->isPartiallyApproved()) {
MakerChecker::notifyNextApprovers($request);
}
use Illuminate\Notifications\Notification;
use Moffhub\MakerChecker\Models\MakerCheckerRequest;
class CustomPendingNotification extends Notification
{
public function __construct(
public MakerCheckerRequest $request,
public ?string $role = null
) {}
public function via($notifiable): array
{
return ['mail', 'database', 'slack']; // Add any channels
}
public function toMail($notifiable): MailMessage
{
return (new MailMessage)
->subject('Custom: Approval Needed')
->line("Please review: {$this->request->description}")
->action('Review', url("/approvals/{$this->request->code}"));
}
// Add toSlack(), toArray(), etc. as needed
}
// Notify all approvers about a pending request
MakerChecker::notifyApprovers($request);
// Notify with sequential mode (only first role)
MakerChecker::notifyApprovers($request, sequential: true);
// Notify next approvers after partial approval
MakerChecker::notifyNextApprovers($request);
// Access the notification service directly
$service = MakerChecker::notifications();
$service->notifyPendingApproval($request);
$service->notifyRequestApproved($request);
$service->notifyRequestRejected($request);
class User extends Authenticatable implements MakerCheckerUserContract
{
public function getMakerCheckerTeamId(): ?int
{
return $this->team_id;
}
// ... other contract methods
}