Search by

al-rahabi / fancy-crud

MohAlRahabi

Opinionated abstract building blocks (controllers, services, repositories, actions, policies, resources) for well-structured Laravel CRUD projects.

Package info

github.com/al-rahabi/fancy-crud

pkg:composer/al-rahabi/fancy-crud

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.1 2026-11-06 20:51 UTC

This package is auto-updated.

Last update: 2026-11-06 20:52:04 UTC


README

Abstract building blocks for well-structured Laravel projects: base controllers, services, repositories, CRUD actions, policies, requests, resources, enums, casts and traits.

Install

composer require al-rahabi/fancy-crud
php artisan vendor:publish --tag=fancy-crud-config

Structure

Namespace Contents
FancyCrud\Actions\Crud AbstractAction, CreateAction, UpdateAction, DestroyAction
FancyCrud\Services BaseService, BaseCrudService
FancyCrud\Repositories BaseRepository
FancyCrud\Contracts Controller, CrudController, BasePolicy, BaseRequest, BaseResource, BaseEnumTrait, BaseNotification
FancyCrud\Casts MediaCast
FancyCrud\Traits Activable, HasSlug, Sortable, ResponseTrait, PaginationMetaTrait
FancyCrud\Middleware AcceptedLanguagesMiddleware

BaseNotification needs laravel-notification-channels/fcm.

Testing

composer install && composer test

Testing your CRUD endpoints (Pest)

The package ships a declarative test generator, FancyCrud\Testing\CrudTestBuilder (helper: crudTest()), that expands into the standard suite for a CrudController.

  1. Use InteractsWithCrud on the base test case your CRUD files run on, call $this->setUpCrud() at the end of setUp(), and implement crudUser(?array $permissions) (null = may do everything, array = exactly those permissions, e.g. ['index posts']). Token-based apps override crudHeaders(), crudUnauthedHeaders(), crudRestrictedHeaders(); apps needing an environment (tenant, transaction) override crudSeed().
  2. Bind the directory in tests/Pest.php: pest()->extend(CrudTestCase::class)->in('Feature/Crud');
  3. One file per controller:
crudTest('posts')
    ->model(Post::class)
    ->all()                                  // or ->only(['index','store',...]) / ->except([...])
    ->createPayload(['title' => 'Hello'])
    ->invalidPayload(['title' => ''])
    ->jsonStructure(['id', 'title'])
    ->assertCreated(['title' => 'Hello'])
    ->importRows([['Title'], ['First'], ['Second']])   // for the import verb (CSV upload)
    ->run();

Verbs: index store show update patch destroy export template import, plus always 401 (unauthenticated) and 403 (no permission; ->restrictedPermission(null) to skip). Defaults: base URL /api (->baseUrl()), records from Model::factory() (or ->record(fn)). See tests/ for a complete working example (fixture controller, policy, Excel sheet).