PHPackages                             nexus-smart-solutions/crud-engine - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. nexus-smart-solutions/crud-engine

ActiveLibrary[Admin Panels](/categories/admin)

nexus-smart-solutions/crud-engine
=================================

Generic CRUD services, file lifecycle management, nested relation synchronization, a statistics engine, and Laravel macros — extracted into a reusable, testable, framework-friendly package.

v1.0.1(yesterday)01↑2900%MITPHPPHP ^8.2

Since Jun 18Pushed yesterdayCompare

[ Source](https://github.com/Nexus-smart-solutions/Crud-Engine)[ Packagist](https://packagist.org/packages/nexus-smart-solutions/crud-engine)[ RSS](/packages/nexus-smart-solutions-crud-engine/feed)WikiDiscussions main Synced today

READMEChangelog (2)Dependencies (10)Versions (3)Used By (0)

Nexus CRUD Engine
=================

[](#nexus-crud-engine)

Generic CRUD services, file lifecycle management, nested relation synchronization, a statistics engine, and a handful of Laravel macros — extracted from an internal framework into a standalone, testable, dependency-injected Laravel package.

Supports Laravel 10, 11, and 12, on PHP 8.2+.

Installation
------------

[](#installation)

```
composer require nexus-smart-solutions/crud-engine
```

The service provider and facade are auto-discovered — no manual registration needed.

Publish the config and translation files (optional):

```
php artisan crud-engine:install
```

This is equivalent to running both of:

```
php artisan vendor:publish --tag=crud-engine-config
php artisan vendor:publish --tag=crud-engine-lang
```

Core Concepts
-------------

[](#core-concepts)

The package never assumes anything about your models' structure. Instead, your Eloquent models opt in to behavior by implementing small **capability interfaces**, and every generic service asks a single `CapabilityRegistry` what a model supports — there's no scattered `instanceof` checking anywhere in your application code.

InterfaceEnables`Nexus\CrudEngine\Contracts\Capabilities\FileUpload`Automatic file store/delete/URL-rewrite for declared attributes`Nexus\CrudEngine\Contracts\Capabilities\HasManyRelations`Automatic diff-based sync of declared hasMany relations`Nexus\CrudEngine\Contracts\Capabilities\HasOneRelations`Automatic update-or-create of declared hasOne relations`Nexus\CrudEngine\Contracts\Capabilities\ManyToManyRelations`Automatic `sync()` of declared belongsToMany relations`Nexus\CrudEngine\Contracts\Capabilities\OriginalName`Marker — keep the client's original filename instead of a hashed oneQuick Start
-----------

[](#quick-start)

### 1. Implement capability interfaces on your model

[](#1-implement-capability-interfaces-on-your-model)

```
use Illuminate\Database\Eloquent\Model;
use Nexus\CrudEngine\Contracts\Capabilities\FileUpload;
use Nexus\CrudEngine\Contracts\Capabilities\HasManyRelations;
use Nexus\CrudEngine\Traits\HasFileUrlsTrait;

class Product extends Model implements FileUpload, HasManyRelations
{
    use HasFileUrlsTrait; // rewrites file attributes into full URLs in toArray()

    public function documentFullPathStore(): string
    {
        // Any structure you want — the package never assumes one.
        return 'products/'.$this->getKey();
    }

    public function requestKeysForFile(): array
    {
        return ['cover_image'];
    }

    public function getHasManyRelations(): array
    {
        return ['variants'];
    }

    public function variants()
    {
        return $this->hasMany(ProductVariant::class);
    }
}
```

### 2. Extend the abstract Crud service for your resource

[](#2-extend-the-abstract-crud-service-for-your-resource)

```
use Nexus\CrudEngine\Services\Crud\AbstractStoreService;

class ProductStoreService extends AbstractStoreService
{
    public function model(): string
    {
        return Product::class;
    }

    public function requestFile(): string
    {
        return ProductStoreRequest::class; // any class with a public rules(): array method
    }
}
```

### 3. Use it in a controller

[](#3-use-it-in-a-controller)

```
class ProductController extends Controller
{
    public function store(ProductStoreService $service)
    {
        $result = $service->store();

        return response()->success($result->data, $result->messages, $result->code);
    }
}
```

That's it — validation (only declared fields are persisted), file storage, and relation syncing for `variants` all happen automatically, in that order, with the file write deferred until after the database transaction commits.

Updating and Deleting
---------------------

[](#updating-and-deleting)

```
use Nexus\CrudEngine\Services\Crud\AbstractUpdateService;
use Illuminate\Database\Eloquent\Model;

class ProductUpdateService extends AbstractUpdateService
{
    public function __construct(private Product $product, /* ...parent deps via DI... */) { /* ... */ }

    public function model(): string { return Product::class; }
    public function requestFile(): string { return ProductUpdateRequest::class; }
    public function resolveModel(): Model { return $this->product; }
}
```

```
use Nexus\CrudEngine\Services\Crud\AbstractBulkDeleteService;

class ProductBulkDeleteService extends AbstractBulkDeleteService
{
    public function model(): string
    {
        return Product::class;
    }
}
```

`AbstractBulkDeleteService` reads `ids` from the current request by default (override `resolveIds()` to change that), and safely handles a scalar `ids` value instead of throwing.

Statistics
----------

[](#statistics)

```
use Nexus\CrudEngine\Services\Statistics\AbstractStatisticsService;

class ProductStatisticsService extends AbstractStatisticsService
{
    public function getModelClass(): string { return Product::class; }
    public function getDateColumn(): string { return 'created_at'; }
}

// In a controller:
$service->getStatistics('2026-01-01', '2026-01-31', 'days');
// => ['2026-01-01' => 3, '2026-01-02' => 0, ..., '2026-01-31' => 1]
```

Results are cached (`crud-engine.statistics.cache_ttl`, default 300 seconds). The query engine defaults to pure Eloquent (portable across MySQL/Postgres/SQLite); set `crud-engine.statistics.query_strategy` to `spatie` if you've separately installed `spatie/laravel-query-builder` and want its filtering conventions instead.

Macros
------

[](#macros)

Available globally once the package is installed, no setup required:

```
// Migrations
Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->status();       // tinyInteger('status')->default(1)
    $table->standardTime(); // created_at, updated_at, soft deletes
});

// Queries
Product::query()->customOrdering('name', 'asc'); // or relation: 'category.name'
Product::query()->datesFiltering();              // reads period_type/from_date/to_date from the request

// Carbon
Carbon::parseOrNow($maybeInvalidDate); // never throws

// Str
Str::snakeToTitle('product_name'); // "Product Name"
Str::humanText('product---name!!'); // "Product Name"

// Responses
return response()->success($data, ['crud-engine::responses.success.created']);
return response()->error('Something specific went wrong.');
```

Events
------

[](#events)

Subscribe to any of these instead of, or in addition to, the package's default logging listener:

- `RecordCreated`, `RecordUpdated`, `RecordDeleted`, `RecordDeletionFailed`
- `FileStored`, `FileDeleted`
- `RelationSynced`

```
Event::listen(RecordCreated::class, function (RecordCreated $event) {
    Cache::forget("product:{$event->model->getKey()}");
});
```

Disable the package's own logging listener with `crud-engine.log_operations = false` if you only want your own listeners.

Overriding Defaults
-------------------

[](#overriding-defaults)

Every behavior described above is bound against an interface and can be swapped from your own `AppServiceProvider`:

```
$this->app->bind(
    \Nexus\CrudEngine\Contracts\Files\FilePathResolverInterface::class,
    \App\Services\TenantAwarePathResolver::class,
);

$this->app->bind(
    \Nexus\CrudEngine\Contracts\Responses\ResponseFormatterInterface::class,
    \App\Services\JsonApiResponseFormatter::class,
);
```

Configuration
-------------

[](#configuration)

After publishing, see `config/crud-engine.php` for: `strict_validation`, `strict_capabilities`, `files.disk`, `relations.max_recursion_depth`, `statistics.query_strategy`, `statistics.cache_ttl`, `response_formatter`, and `log_operations`.

Testing
-------

[](#testing)

```
composer install
vendor/bin/phpunit
```

The test suite uses Orchestra Testbench against an in-memory SQLite database. It includes dedicated regression tests for every bug fixed during the refactor (see CHANGELOG.md) — most notably the HasOne/HasMany recursion mix-up, the validation mass-assignment gap, the orphaned-file bug, and the original-filename path-traversal fix.

License
-------

[](#license)

@NexusSmartSolution. [![Up Scale Logo](https://private-user-images.githubusercontent.com/244020528/609817716-de1182f5-4a62-47ab-868d-82ec3f58663f.jpg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODE4MzY3ODcsIm5iZiI6MTc4MTgzNjQ4NywicGF0aCI6Ii8yNDQwMjA1MjgvNjA5ODE3NzE2LWRlMTE4MmY1LTRhNjItNDdhYi04NjhkLTgyZWMzZjU4NjYzZi5qcGc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwNjE5JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDYxOVQwMjM0NDdaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0yNjQ2ZTg2YmY3MzIwYjc5MDQzM2NiMjAyNmJkNjFmNzUzZTViMWQ1NzgzMmFjNjA4NzNiYTBiMmE5OTk0MzlmJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZyZXNwb25zZS1jb250ZW50LXR5cGU9aW1hZ2UlMkZqcGVnIn0.52EV41e32Xd9DmOFN1l3cj0Ensj4V77MRhquIoMI7Bo)](https://private-user-images.githubusercontent.com/244020528/609817716-de1182f5-4a62-47ab-868d-82ec3f58663f.jpg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODE4MzY3ODcsIm5iZiI6MTc4MTgzNjQ4NywicGF0aCI6Ii8yNDQwMjA1MjgvNjA5ODE3NzE2LWRlMTE4MmY1LTRhNjItNDdhYi04NjhkLTgyZWMzZjU4NjYzZi5qcGc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjYwNjE5JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI2MDYxOVQwMjM0NDdaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0yNjQ2ZTg2YmY3MzIwYjc5MDQzM2NiMjAyNmJkNjFmNzUzZTViMWQ1NzgzMmFjNjA4NzNiYTBiMmE5OTk0MzlmJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZyZXNwb25zZS1jb250ZW50LXR5cGU9aW1hZ2UlMkZqcGVnIn0.52EV41e32Xd9DmOFN1l3cj0Ensj4V77MRhquIoMI7Bo)

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 60% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

1d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/91374170?v=4)[usman ahmed fathy](/maintainers/USmanFathy)[@USmanFathy](https://github.com/USmanFathy)

---

Top Contributors

[![USmanFathy](https://avatars.githubusercontent.com/u/91374170?v=4)](https://github.com/USmanFathy "USmanFathy (3 commits)")[![Nexus-smart-solutions](https://avatars.githubusercontent.com/u/244020528?v=4)](https://github.com/Nexus-smart-solutions "Nexus-smart-solutions (2 commits)")

---

Tags

laravelcrudrepositoryrelationsstatisticsfile-upload

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/nexus-smart-solutions-crud-engine/health.svg)

```
[![Health](https://phpackages.com/badges/nexus-smart-solutions-crud-engine/health.svg)](https://phpackages.com/packages/nexus-smart-solutions-crud-engine)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k51.0M7.5k](/packages/larastan-larastan)[laravel/ai

The official AI SDK for Laravel.

9782.1M157](/packages/laravel-ai)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45344.0k1](/packages/pressbooks-pressbooks)[api-platform/laravel

API Platform support for Laravel

59156.3k11](/packages/api-platform-laravel)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
