PHPackages                             cathedral/builder - 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. cathedral/builder

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

cathedral/builder
=================

Database Layer builder library with Basic Web &amp; Console interface

0.32.2(4y ago)5384[1 issues](https://github.com/CathedralCode/Builder/issues)1MITPHP

Since Oct 25Pushed 2y ago2 watchersCompare

[ Source](https://github.com/CathedralCode/Builder)[ Packagist](https://packagist.org/packages/cathedral/builder)[ Docs](https://git.inane.co.za:3000/cathedral/builder)[ RSS](/packages/cathedral-builder/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (3)Versions (18)Used By (1)

Cathedral Builder
=================

[](#cathedral-builder)

Quick Start
-----------

[](#quick-start)

The three steps needed to get up and run assuming you already have laminas running with a database.

### Step 1: Register Static Adapter:

[](#step-1-register-static-adapter)

Laminas let's us register the database connection statically for easy reference.

Edit the `bootstrap` method in `Application\Module.php`:

```
/**
 * Bootstrap
 *
 * If you don't have a bootstrap method this one will do.
 *
 * @param MvcEvent $e
 */
public function onBootstrap(\Laminas\Mvc\MvcEvent $e): void {
    // Add this line to register the static method
    \Laminas\Db\TableGateway\Feature\GlobalAdapterFeature::setStaticAdapter($e->getApplication()->getServiceManager()->get('Laminas\Db\Adapter\Adapter'));
}
```

### Step 2: Register Builder Module:

[](#step-2-register-builder-module)

To register Builder is even easier, it just needs to be added to the module array. This enables ui for console and web.

Edit `config/development.config.php`:

```
    // Additional modules to include when in development mode
    'modules' => [
        'Cathedral\Builder',
    ],
```

That's it!

Open the web interface by using `/builder` as the route.

E.g.: `http://localhost/builder`

Or use it from the command line:

```
# list tables and file status
$ ./vendor/bin/laminas builder:list
# build command
$ ./vendor/bin/laminas builder:build
```

---

CURRENTLY SPLITTING
-------------------

[](#currently-splitting)

Laminas 3 database layer builder with a simple Web &amp; Console UI with many great features.

For a quick list of fixes and changes see [CHANGELOG.md](CHANGELOG.md)

Creates classes based on:

Requirements
------------

[](#requirements)

- PHP &gt;= 8
- Laminas 3 (latest master)

Installing
----------

[](#installing)

I’m sure most of you can do this, but those that need a little help.

### With composer

[](#with-composer)

Command line:

```
composer require --dev cathedral/builder
```

OR edit composer.json manually:

Add builder to composer.json require:

```
    "require-dev": {
        "cathedral/builder": "dev-master"
    }
```

Then update composer:

```
    $ php composer.phar update

```

### Post installation (Optional)

[](#post-installation-optional)

Enabling Builder GUI in your `development.config.php` file:

```
    return [
        'modules' => [
            // ...
            'Cathedral\Builder',
        ],
        // ...
    ];
```

Builder GUI has some options to allow you to quickly customise the basic functionality. After Enabling Builder GUI:

1. copy `./vendor/cathedral/builder/config/cathedral-builder.global.php.dist` to `./config/autoload/cathedral-builder.global.php.php`
2. change settings as desired.
    - **namespace** - Module where files will be created and the namespace of the created files. Default is `Application`.
    - **entity\_singular** - On/Off switch for this feature.
    - **singular\_ignore** - A | (pipe) delimited list of tables to ignore for EntitySingular.

Build Your Data Layer
---------------------

[](#build-your-data-layer)

Builder is only used to generate the classes, after that the classes are only dependent on laminas, so no need to have builder on your production machine as a dependency.

### First things first

[](#first-things-first)

- Make sure any custom module is 100% functional before running builder or it will revert back to Application.
- Using WebUI: check web user has write access to modules `src/{Model,Entity}` folders
- Using Console: check you have write access to `src/{Model,Entity}` folders

### WebUI

[](#webui)

`Open http://yoursite/builder`

If you want builder to save files to disk the directories for Namespace/Entity and Namespace/Model must be writeable by php. And enjoy.

### Console

[](#console)

And just for kicks there is even console support. The console UI uses the same config as the Web UI. In the root of your project run `php index.php` and see the Cathedral options:

Get info with: `php index.php table list`

```
    Listing of tables
    basics
        DataTable     :Ok
        EntityAbstract:Outdated
        Entity        :None

```

Generate with `build (datatable|abstract|entity|ALL)  [--write|-w]`You can redirect to a file ` > path/to/file.php`Or simple use the -w option and builder does it for you.

just use `build ALL ALL -w`and everything's done.

#### Quick console tips

[](#quick-console-tips)

- `builder build -w` # this creates all the files for all the tables
- `builder build ALL logs -w` # build all files for logs table
- `builder build datatable ALL -w` # builds the datatable file for all tables

### Custom Builder

[](#custom-builder)

Use builder in your own way.

#### Single Table

[](#single-table)

Figure out what module will house your db code e.g. DBLayer

create the Entity &amp; Model namespace dirs (module/DBLayer/src/DBLayer/{Entity|Model}

Use BuilderManager:

```
use Cathedral\Builder\BuilderManager;

```

Create a BuilderManager:

```
$buildManager = new BuilderManager('DBLayer', ’mytable');

```

If you don’t leave off the table argument you can use the nextTable method to loop through all the tables. Handy for batch runs. And probably the most common use.

With either a table specified or loaded via nextTable, write the files to disk or display to screen.

```
    //Echo to screen
    echo $buildManager->getDataTableCode();
    echo $buildManager->getEntityAbstractCode();
    echo $buildManager->getEntityCode();

    //Write to file
    $buildManager->writeDataTable();
    $buildManager->writeEntityAbstract();
    $buildManager->writeEntity();
```

That's it for the table :)

#### Loop through Tables

[](#loop-through-tables)

Handy for updating classes to new version etc… And for many tables a lot less painful then 3 lines of code per tables :)

Use BuilderManager:

```
use Cathedral\Builder\BuilderManager;

```

Create a BuilderManager NO table specified:

```
$buildManager = new BuilderManager('DBLayer');

```

Write while loop overwriting current DataTable And EntityAbstract, only create Entity if not found:

```
while ($buildManager->nextTable()) {
    $buildManager->writeDataTable();
    $buildManager->writeEntityAbstract();
    $buildManager->writeEntity();
}

```

That's it for all tables :)

### Restful

[](#restful)

Builder now has some a simple Restful interface to tables.

Supported so far:

- getList (List tables &amp; list rows in table)
- get (individual row from table)

To get a list of tables use:

```
get http://yoursite/builder/rest

```

result:

```
{
    "code": 401,
    "message": "Tabels",
    "data": [
        "cities",
        "countries",
        "currencies",
        "settings",
        "users"
    ]
}

```

To list rows in table showing primary key field and value

```
get http://yoursite/builder/rest/settings

```

result:

```
{
    "code": 0,
    "message": "SettingsTable List",
    "data": [
        {
            "name": "currency"
        },
        {
            "name": "db_version"
        }
    ]
}

```

List a row:

```
get http://yoursite/builder/rest/settings/db_version

```

result:

```
{
    "code": 0,
    "message": "Setting",
    "data": {
        "name": "db_version",
        "value": "1",
        "created": "2014-11-08 05:28:31",
        "modified": null
    }
}

```

Features/Conventions (Assumptions)
----------------------------------

[](#featuresconventions-assumptions)

### EntitySingular

[](#entitysingular)

If a table name is plural, builder will try create the entity as the singular version.

Most **common** plural/singular conventions are supported.

E.g.

```
Table countries
DataTable: CountriesTable
Entity: Country

Table catches
DataTable: CatchesTable
Entity: Catch

Table users
DataTable: UsersTable
Entity: User

```

#### Disable

[](#disable)

But if you want you can also disable it totally.

```
// First we create a NameManger
$nm = new NameManager('Dossier');

// EntitySingular is enabled by default
// To check the status use:
if ($nm->entitySingular()) {
    // If enabled
    // To disable it:
    $nm->entitySingular(false);
} else {
    // If disabled
    // To enable it:
    $nm->entitySingular(true);
}

// Lets keep it enabled
$nm->entitySingular(true);

```

#### Ignore List

[](#ignore-list)

Or add tables to an ignore list to skip a table or two.

```
// But lets tell it that a few tables ending in a plural should be ignored
// To reset the ignore list pass FALSE
$nm->setEntitySingularIgnores(false);

// Now lets add our ignore tables
// adding table1s
$nm->setEntitySingularIgnores('table1s');

// you can add them as an array or | (pipe) delimited string as well
$nm->setEntitySingularIgnores('table1s|table2s');
// OR
$nm->setEntitySingularIgnores(['table1s','table2s']);

```

### Relations

[](#relations)

Builder checks the MySQL info tables to relate tables to one another.

To get related records either use the table name in plural for referenced tables or the singular for a referenced table.

E.g.: Get the User related to a Group

```
...
Table groups which contains users
Method: $group->User()
Entity: User
...

```

E.g.: Get all Groups related to a User

```
...
Method: $user->Groups()
Entities: Group
OR
Method: $user->Groups(['active' => 1])
Entities: Group that also have active set to 1
...

```

### Events

[](#events)

See Laminas Events: [Laminas-db](https://docs.laminas.dev/laminas-db/table-gateway/)

#### TableGateway LifeCycle Events

[](#tablegateway-lifecycle-events)

When the EventFeature is enabled on the TableGateway instance, you may attach to any of the following events, which provide access to the parameters listed.

- **preInitialize** (no parameters)
- **postInitialize** (no parameters)
- **preSelect**, with the following parameters:
    - *select*, with type Laminas\\Db\\Sql\\Select
- **postSelect**, with the following parameters:
    - *statement*, with type Laminas\\Db\\Adapter\\Driver\\StatementInterface
    - *result*, with type Laminas\\Db\\Adapter\\Driver\\ResultInterface
    - *resultSet*, with type Laminas\\Db\\ResultSet\\ResultSetInterface
- **preInsert**, with the following parameters:
    - *insert*, with type Laminas\\Db\\Sql\\Insert
- **postInsert**, with the following parameters:
    - *statement* with type Laminas\\Db\\Adapter\\Driver\\StatementInterface
    - *result* with type Laminas\\Db\\Adapter\\Driver\\ResultInterface
- **preUpdate**, with the following parameters:
    - *update*, with type Laminas\\Db\\Sql\\Update
- **postUpdate**, with the following parameters:
    - *statement*, with type Laminas\\Db\\Adapter\\Driver\\StatementInterface
    - *result*, with type Laminas\\Db\\Adapter\\Driver\\ResultInterface
- **preDelete**, with the following parameters:
    - *delete*, with type Laminas\\Db\\Sql\\Delete
- **postDelete**, with the following parameters:
    - *statement*, with type Laminas\\Db\\Adapter\\Driver\\StatementInterface
    - *result*, with type Laminas\\Db\\Adapter\\Driver\\ResultInterface

Listeners receive a Laminas\\Db\\TableGateway\\Feature\\EventFeature\\TableGatewayEvent instance as an argument. Within the listener, you can retrieve a parameter by name from the event using the following syntax:

#### Examples:

[](#examples)

A Quick Example:

```
// Create Settings & User table objects
$settingaTable = new SettingsTable();
$usersTable = new UsersTable();

// Two simple select events to see it in action
$settingaTable->getEventManager()->attach('postSelect', function(TableGatewayEvent $event) {
    Logger::dump($event->getParam('result')->current(), 'TableGatewayEvent::Setting', false);
});

$usersTable->getEventManager()->attach('postSelect', function(TableGatewayEvent $event) {
    Logger::dump($event->getParam('result')->current(), 'TableGatewayEvent::User', false);
});

// More useful, if a user is added we can run some init setup tasks
$usersTable->getEventManager()->attach('postInsert', function (TableGatewayEvent $event) {
    /** @var ResultInterface $result */
    $result = $event->getParam('result');
    $generatedId = $result->getGeneratedValue();

    // do something with the generated identifier...
});

// More useful, if a setting is updated rebuild cache or ...
$settingaTable->getEventManager()->attach('postUpdate', function (TableGatewayEvent $event) {
    /** @var ResultInterface $result */
    $result = $event->getParam('result');
    $generatedId = $result->getGeneratedValue();

    // do something with the generated identifier...
});

$user = $usersTable->getUser(1);
$pagination = $settingaTable->getSetting('pagination');
$dbVersion = (new Setting())->get('dbVersion');
```

The Generated Files
-------------------

[](#the-generated-files)

### Entity

[](#entity)

This files is created for you to add any custom stuff you may want for that table. On a users table it might be a function that formats the full name to some crazy standard. So this file is **NEVER** replaced by the builder. So use it for what ever you need and rest assured the code will not disappear.

### EntityAbstract

[](#entityabstract)

This is the basic Entity file. If newer version of Builder may replace this with fixes/features/etc Don't edit this file, your changes will be lost!

### DataTable

[](#datatable)

Basically this is a TableGateway, it does the database lifting and returns the Entities. Again, Builder checks the version of this and it will be replaced with newer versions. Don't edit.

Requirements: Runtime
---------------------

[](#requirements-runtime)

### Module &amp; Directories (Only if you want to write to file)

[](#module--directories-only-if-you-want-to-write-to-file)

The namespace passed to a manger needs to be an existing module. It also needs to have the directories Entity and Model in the `src/{ModuleName}/directory`

These 2 dirs need to be writeable by your web server

E.G.

```
$buildManager = new BuilderManager(‘DBLayer');

```

Will try create the files in:

`module/DBLayer/src/DBLayer/Entity`

`module/DBLayer/src/DBLayer/Model`

### Global Adapter

[](#global-adapter)

Builder uses the Global Adapter feature

Simplest way to get set it (I'm my opinion) is to modify the Module.php in the module where the Data object will be created.

`module/DBLayer/Module.php`

```
public function onBootstrap(MvcEvent $e) {
...
  $adapter = $e->getApplication()
    ->getServiceManager()
    ->get('Laminas\Db\Adapter\Adapter');

  \Laminas\Db\TableGateway\Feature\GlobalAdapterFeature::setStaticAdapter($adapter);
...
}

```

A make sure that this Module is before any other in the list the use the DBLayer.

Tips
----

[](#tips)

### Write Permission Error

[](#write-permission-error)

Try shell line bellow (replace DBLayer with your data module)

```
sudo chmod -R a+rwX module/DBLayer/src/{Entity,Model}
```

### Quick console tips

[](#quick-console-tips-1)

- `builder build -w` # this creates all the files for all the tables
- `builder build ALL logs -w` # build all files for logs table
- `builder build datatable ALL -w` # builds the datatable file for all tables

Feedback
--------

[](#feedback)

Hey, got any ideas or suggestions to help improve this generator let me. Email me

###  Health Score

29

—

LowBetter than 59% of packages

Maintenance16

Infrequent updates — may be unmaintained

Popularity17

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 100% 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 ~191 days

Recently: every ~164 days

Total

15

Last Release

1546d ago

PHP version history (5 changes)0.11.0PHP &gt;=5.3.3

0.15.0PHP &gt;=5.4

0.10.1PHP &gt;=5.5

0.22.1.1PHP &gt;=7.1

0.26.0PHP &gt;=7.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1823594?v=4)[Philip Michael Raab](/maintainers/inanepain)[@inanepain](https://github.com/inanepain)

---

Top Contributors

[![inanepain](https://avatars.githubusercontent.com/u/1823594?v=4)](https://github.com/inanepain "inanepain (363 commits)")

---

Tags

laminaslaminas-clilaminas-code-generatorlaminas-dblaminas-mvcphpphp-libraryphp8laminasdbinanecathedral

### Embed Badge

![Health badge](/badges/cathedral-builder/health.svg)

```
[![Health](https://phpackages.com/badges/cathedral-builder/health.svg)](https://phpackages.com/packages/cathedral-builder)
```

###  Alternatives

[robmorgan/phinx

Phinx makes it ridiculously easy to manage the database migrations for your PHP app.

4.5k46.2M405](/packages/robmorgan-phinx)[laminas/laminas-db

Database abstraction layer, SQL abstraction, result set abstraction, and RowDataGateway and TableDataGateway implementations

13922.5M206](/packages/laminas-laminas-db)[samsonasik/error-hero-module

A Hero for your Laminas and Mezzio application to trap php errors &amp; exceptions

5233.4k1](/packages/samsonasik-error-hero-module)[php-db/phpdb

Database abstraction layer, SQL abstraction, result set abstraction, and RowDataGateway and TableDataGateway implementations

1815.0k6](/packages/php-db-phpdb)[masom/lhm

Large Hadron Migrator for phinx

309.3k](/packages/masom-lhm)

PHPackages © 2026

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