PHPackages                             efabrica/nette-repository - 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. [Database &amp; ORM](/categories/database)
4. /
5. efabrica/nette-repository

ActiveLibrary[Database &amp; ORM](/categories/database)

efabrica/nette-repository
=========================

Repositories for Nette database

0.7.0(5mo ago)348.4k—5.6%8[3 PRs](https://github.com/efabrica-team/nette-database-repository/pulls)MITPHPPHP ^8.3

Since Mar 28Pushed 3mo ago4 watchersCompare

[ Source](https://github.com/efabrica-team/nette-database-repository)[ Packagist](https://packagist.org/packages/efabrica/nette-repository)[ RSS](/packages/efabrica-nette-repository/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (15)Versions (30)Used By (0)

eFabrica Nette Database Repository
==================================

[](#efabrica-nette-database-repository)

This extension enhances the static analysis of your Nette Database by providing typehinted entities (ActiveRows), queries (Selections) and repositories (services).

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

[](#installation)

You can install this extension using [Composer](http://getcomposer.org/), the dependency manager for PHP:

```
composer require efabrica/nette-repository
```

To enable the extension, you need to register it in config:

```
extensions:
    netteRepo: Efabrica\NetteRepository\Bridge\EfabricaNetteRepositoryExtension
```

Finally, you can run the repository code generation command to generate the necessary classes and files:

```
$ php vendor/bin/enc
```

Usage
-----

[](#usage)

### Entity

[](#entity)

The `Entity` class is a subclass of ActiveRow that serves as a superclass for your entities. You can either use our code generation tool to create it automatically or write it manually.

#### Inserting an entity

[](#inserting-an-entity)

```
assert($repository instanceof PersonRepository);
assert($entity instanceof Person);
$entity = $repository->create();
$entity->name = 'John';
$entity->surname = 'Doe';
$entity->age = 42;
$entity->save();
```

Save array:

```
$entity = $repository->insertOne([
    Person::NAME => 'John',
    Person::SURNAME => 'Doe',
    Person::AGE => 42,
]); // always returns entity

// More verbose approach:
$entity = $repository->create();
$entity->fill([
    Person::NAME => 'John',
    Person::SURNAME => 'Doe',
    Person::AGE => 42,
]);
$entity->save();
```

Classic:

```
$person = $repository->insert([
    Person::NAME => 'John',
    Person::SURNAME => 'Doe',
    Person::AGE => 42,
]); // always returns Entity
```

Multi-insert:

```
$persons = [];
foreach (range(30, 40) as $age) {
    $person = $repository->createRow();
    Person::NAME => 'John',
    Person::SURNAME => 'Doe',
    Person::AGE => $age,
    $persons[] = $person;
}
$repository->insertMany($persons); // always returns int
```

#### Updating an entity

[](#updating-an-entity)

```
$entity = $repository->find($id);
$entity->name = 'Jake';
$entity->update(); // or $entity->save();
```

Classic:

```
$repository->update($id, [Person::name => 'Jake']);
```

#### Deleting an entity

[](#deleting-an-entity)

```
$repository->delete($id);
```

Or, if you already have the entity available:

```
$entity = $repository->find($id);
$entity->delete();
```

### Scopes

[](#scopes)

Scope is a class that defines which existing behaviors are disabled for the Repository, Query and Entity.

The active Scope is passed down from Repository to Query and from Query down to Entity.

`->withScope(Scope $scope)` returns a clone of the object with the given scope applied.

`->scopeRaw()` returns a clone of the object with raw scope. Raw scope removes all behaviors.

`->scopeFull()` returns a clone of the object with full scope. Full scope keeps all behaviors. This is the default scope, unless you change the scope in repository's setup() method.

#### Example

[](#example)

```
final class AdminScope implements \Efabrica\NetteRepository\Repository\Scope\Scope
{
    public function apply(RepositoryBehaviors $behaviors, Repository $repository): void
    {
        // Remove these behaviors because they are not needed for the Admin
        $behaviors
            ->remove(SoftDeleteBehavior::class)
            ->remove(PublishBehavior::class);

        // Do not add any new behaviors here, because this scope can be used by different repositories
        // and you might introduce unwanted side effects.

        // However, you can conditionally add behaviors based on the repository type and some parameter
        // For example, if you want to apply a special behavior for admin users in the user repository, you can do this:
        if ($repository instanceof UserRepository && $someContainerParameter) { // Scopes can be services and receive parameters.
            $behaviors->add(AdminBehavior::class); // This is a hypothetical behavior, just for illustration.
        }
    }
}
```

To use the Scope as a **container service**, which may not be necessary in your case, please follow these steps:

```
use Efabrica\NetteRepository\Repository\RepositoryBehaviors;
abstract class RepositoryBase extends \Efabrica\NetteRepository\Repository\Repository
{
    /** @inject */
    public AdminScope $adminScope;

    public function scopeAdmin(): self
    {
        return $this->withScope($this->adminScope);
    }

    // Do this if you want to set the AdminScope as default:
    protected function setup(RepositoryBehaviors $behaviors) : void
    {
        $behaviors->setScope($this->adminScope);
    }
}
```

And **optionally** implement shorthand methods for your queries:

```
use YourBeautifulApplication\Admin\AdminScope;

abstract class QueryBase extends \Efabrica\NetteRepository\Repository\Query
{
    public function scopeAdmin(): self
    {
        // This method returns a copy of the query with your own Admin scope applied
        // The Admin scope removes some behaviors that are not relevant for the Admin
        return $this->withScope($this->repository->adminScope);
        // Alternatively, if the Admin scope does not depend on any parameters, you can create a new instance of it like this:
        return $this->withScope(new AdminScope());
    }
}
```

Usage:

```
// all of these are equivalent:
$repository->findBy(['age > ?' => 18])->scopeAdmin()->fetchAll();
$repository->scopeAdmin()->findBy(['age > ?' => 18])->fetchAll();
$repository->query()->where('age > ?', 18)->scopeAdmin()->fetchAll();
$repository->scopeAdmin()->query()->where('age > ?', 18)->fetchAll();
$repository->query()->scopeAdmin()->where('age > ?', 18)->fetchAll();
```

Code Generator
--------------

[](#code-generator)

Code generation is fully optional, but it is recommended to use it.

> To run the code generation, use this command:
>
> ```
> $ php bin/console efabrica:nette-repo:code-gen
> # OR
> $ php bin/console e:n:c
> # OR
> $ php vendor/bin/enc
> ```

For every table in the database, it will generate these classes in the `/Generated/` namespace: (Example: `person` table)

- `Repository\Generated\Repository\PersonRepositoryBase` - Repository base class, holds typehints for `PersonQuery` and `Person` entity. ( abstract)
- `Repository\Generated\Query\PersonQuery` - Query class, holds typehints for `Person` entity. (abstract)
- `Repository\Generated\Entity\Person` - Entity class, holds types for columns and public constants for column names. (final)

These classes are **always regenerated** when you run the code generator. They should not be modified manually.

For every table in the database, it will also generate these classes **outside** of the `/Generated/` namespace, but only if they don't exist. If they exist, they will not be overwritten:

- `Repository\PersonRepository` - extends `PersonRepositoryBase`. Here you write your custom repository methods. (final)
- `Repository\Query\PersonQuery` - extends `PersonQuery`. Here you write your custom query methods. (final)
- `Repository\Entity\PersonBody` - trait that is inserted into `Person` entity. Here you write your custom entity methods. (trait)

These classes are **not regenerated** when you run the code generator. They are meant to be customized by you. If you want to regenerate them, you have to delete them first.

#### Ignoring tables

[](#ignoring-tables)

It is also possible to ignore some tables. To do that, you can modify the `ignoredTables` parameter in the config file:

```
netteRepo:
    ignoreTables:
        # These are the defaultly ignored tables:
        migrations: true
        migration_log: true
        phoenix_log: true
        phinxlog: true

```

#### Table alias

[](#table-alias)

You can define a custom alias for specific tables using the `tableAlias` parameter in the config file. The defined alias will be used as the entity name when generating the structure:

```
netteRepo:
    tableAlias:
        matches: games

```

#### Custom Inheritance

[](#custom-inheritance)

If you want to set different `extends` or `implements` for a generated class, you can do that by adding an entry into your config file:

```
netteRepo:
    inheritance:
        AuthorRepositoryBase:
            extends: 'App\Repository\PeopleRepositoryBase'
            implements: ['App\Repository\PersonRepositoryInterface']
        AuthorQuery:
            extends: 'App\Repository\PeopleQueryBase'
        Person:
            implements: ['App\Repository\PersonInterface']
```

- Every generated class can be used for this.
- Key is the short class name (without namespace). Generated classes are made such that there are no namespace collisions, so this shouldn't prove a problem.
- `extends` must be string or null/not specified.
- `implements` must be string array or empty array or null/not specified.
- You cannot unimplement an interface.

This config schema is a bit verbose, but very intuitive once you see it and easy to read.

Behaviors and Traits
--------------------

[](#behaviors-and-traits)

#### DateBehavior

[](#datebehavior)

This behavior automatically sets the `created_at` and `updated_at` columns to the current date and time when inserting or updating a row.

#### FilterBehavior

[](#filterbehavior)

This behavior applies a default where() condition to every select query.

#### KeepDefaultBehavior

[](#keepdefaultbehavior)

This behavior ensures that there is always at least one row with a truthy value in the default column. This is useful for flag columns.

#### SoftDeleteBehavior

[](#softdeletebehavior)

This behavior marks a row as deleted by setting the `deleted_at` column to the current date and time instead of removing it from the table.

#### LastManStandingBehavior

[](#lastmanstandingbehavior)

This behavior prevents deleting the last row in the table that matches a given query.

#### TreeTraverseBehavior

[](#treetraversebehavior)

This behavior manages the `lft` and `rgt` columns that represent the hierarchical structure of the table. It updates them automatically when inserting or updating a row.

#### SortingTrait

[](#sortingtrait)

This trait adds methods to the repository for changing the order of rows, such as moveUp(), moveDown(), insertBefore(), and insertAfter().

#### CastBehavior

[](#castbehavior)

This behavior automatically casts values to the specified type when retrieving them from the database.

There are some predefined casts, but you can also define your own.

- `JsonCastBehavior`: casts values from JSON to PHP array and vice versa.
- `CarbonCastBehavior`: casts values from MySQL datetime to CarbonImmutable and vice versa.

#### Events

[](#events)

There are several events that you can listen to in your repository: Insert, Update, Delete, Select, Load

To implement your own event subscriber, create a new class that extends `Efabrica\NetteRepository\Subscriber\EventSubscriber` and register it in the container. It will get automatically detected, since it extends the EventSubscriber.

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance78

Regular maintenance activity

Popularity36

Limited adoption so far

Community20

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 67.7% 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 ~39 days

Recently: every ~9 days

Total

19

Last Release

165d ago

PHP version history (3 changes)0.1.0PHP ^7.4|^8.0

0.4.2PHP ^8.1

0.5.0PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/25289c62a88df1c404543693ba52e44748dbce486bcfab91fc8c5931a6bb38e1?d=identicon)[dev-efabrica](/maintainers/dev-efabrica)

---

Top Contributors

[![riki137](https://avatars.githubusercontent.com/u/1223388?v=4)](https://github.com/riki137 "riki137 (63 commits)")[![tonop01](https://avatars.githubusercontent.com/u/29866948?v=4)](https://github.com/tonop01 "tonop01 (10 commits)")[![calvera](https://avatars.githubusercontent.com/u/432090?v=4)](https://github.com/calvera "calvera (6 commits)")[![mgemmel](https://avatars.githubusercontent.com/u/26734633?v=4)](https://github.com/mgemmel "mgemmel (3 commits)")[![jzernovic](https://avatars.githubusercontent.com/u/7045023?v=4)](https://github.com/jzernovic "jzernovic (3 commits)")[![lulco](https://avatars.githubusercontent.com/u/9377319?v=4)](https://github.com/lulco "lulco (3 commits)")[![MartinPetricko](https://avatars.githubusercontent.com/u/39132866?v=4)](https://github.com/MartinPetricko "MartinPetricko (2 commits)")[![rasstislav](https://avatars.githubusercontent.com/u/9253113?v=4)](https://github.com/rasstislav "rasstislav (1 commits)")[![andrejjursa](https://avatars.githubusercontent.com/u/2331773?v=4)](https://github.com/andrejjursa "andrejjursa (1 commits)")[![riskar](https://avatars.githubusercontent.com/u/8099443?v=4)](https://github.com/riskar "riskar (1 commits)")

---

Tags

phpnettedatabaserepository

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/efabrica-nette-repository/health.svg)

```
[![Health](https://phpackages.com/badges/efabrica-nette-repository/health.svg)](https://phpackages.com/packages/efabrica-nette-repository)
```

###  Alternatives

[ssch/typo3-rector

Instant fixes for your TYPO3 PHP code by using Rector.

2592.8M263](/packages/ssch-typo3-rector)[rector/rector-src

Instant Upgrade and Automated Refactoring of any PHP code

134391.5k12](/packages/rector-rector-src)[modul-is/orm

Lightweight hybrid ORM/Explorer

1118.1k](/packages/modul-is-orm)[larachimp/mango-repo

Simple repository package for Laravel 5.

317.2k](/packages/larachimp-mango-repo)

PHPackages © 2026

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