denosyscore / database
Database ORM, query builder, migrations, and seeding
Requires
- php: ^8.2
- ext-pdo: *
- denosyscore/container: ^0.2
- denosyscore/contracts: ^0.2
- denosyscore/support: ^0.1
Requires (Dev)
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^10.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v0.4.1
- v0.4.0
- v0.3.0
- v0.2.3
- v0.2.2
- v0.2.1
- v0.2.0
- v0.1.0
- dev-codex/sqlite-column-primary-key
- dev-codex/schema-index-metadata
- dev-codex/model-pagination
- dev-codex/release-workflow-permission
- dev-codex/migration-pretend-read-only
- dev-codex/repository-pagination-metadata
- dev-codex/pdo-option-keys
- dev-codex/sqlite-column-discovery
- dev-codex/sqlite-foreign-keys
- dev-codex/database-exception
- dev-codex/collection-dependency
- dev-codex/sqlite-migration-timestamp
- dev-codex/model-query-types
- dev-codex/metadata-collection-integration
- dev-codex/model-metadata-types
This package is auto-updated.
Last update: 2026-11-03 19:40:40 UTC
README
Database ORM, query builder, migrations, and seeding
Status
Initial extraction snapshot from denosyscore monorepo as of 2026-02-14.
Installation
composer require denosyscore/database
This installs denosyscore/support, which provides the
Denosys\Support\Collection returned by hydrated model queries and used by
eager-loaded relations. Database consumers do not need to define that class.
Included Modules
- src/Database/*
Model query pagination
ModelBuilder::paginate(int $page = 1, int $perPage = 15) returns a
Denosys\Database\Pagination\LengthAwarePaginator containing a hydrated
Denosys\Support\Collection in items. Its metadata includes total,
perPage, currentPage, lastPage, from, to, previousPage, and
nextPage. Relations forward paginate() to their model query, retaining
relation constraints. Apply a stable orderBy() before paginating when order
matters.
Pagination uses cloned count and page queries, leaving the caller's builder
unchanged. Out-of-range pages clamp to the last page. An empty result reports
page 1 of 1, from and to as 0, and an empty collection. Page and page size
must be positive; request-level upper bounds remain the caller's policy.
PDO connection options
Pass driver options under options in the connection configuration. Numeric
PDO attribute identifiers are preserved, so caller options override matching
defaults. For MySQL, the configured charset/collation init command and ssl
settings take precedence over conflicting entries in options.
On SQLite, SchemaBuilder::getColumns() and hasColumn() report existing
columns through the same public API used for other supported drivers.
SchemaBuilder::getIndexes($table) returns indexes in name order for MySQL,
SQLite, and PostgreSQL. Each entry has name, columns (in key order),
unique, and primary fields. Expression index positions have a null
column name. A missing table returns an empty list. Inspect existing indexes
before replacing one, and check for duplicate values before adding a unique
constraint.
SQLite table creation emits declared foreign keys, including configured
ON DELETE and ON UPDATE actions. Existing SQLite tables do not acquire
new constraints automatically; rebuild those tables in an explicit migration.
Migration execution timestamps are stored in UTC using a bound value so the migration repository works with SQLite, MySQL, and PostgreSQL.
Connection setup failures and unsupported drivers raise
Denosys\Database\Exceptions\DatabaseException. When a PDO connection fails,
the original PDOException is available from getPrevious().
Model attribute metadata
Model subclasses declare $fillable and $hidden as lists of attribute names,
not maps. The lists control mass assignment and serialization respectively.
final class User extends \Denosys\Database\Model { /** @var list<string> */ protected array $fillable = ['name', 'email']; /** @var list<string> */ protected array $hidden = ['password']; }
Migration preview
Migrator::pretend()->run() lists pending migrations without creating the
migration repository, applying schema changes, or recording history. The
MigrationResult contains planned migration names, and getPretendLog()
contains descriptive Would up entries; it does not contain compiled SQL.
Pretend mode also keeps rollback, reset, and fresh operations read-only. Turn
pretend mode off before the real operation.
Repository pagination
Repository::paginate() reports empty results as page 1 of 1, with from
and to both 0. Its existing response array shape is unchanged.
Development
composer validate --strict find src -type f -name '*.php' -print0 | xargs -0 -n1 php -l composer test composer analyse
CI Workflows
- CI: Composer validation, model metadata static analysis, PHP syntax lint, and database regression tests on supported PHP versions for push and pull requests.
- Release: GitHub release publication on semantic version tags.
- Dependabot: weekly Composer dependency update checks.
Releases
After CI passes on main, create an annotated semantic version tag from that
reviewed commit and push the tag. The Release workflow publishes a GitHub
Release. Confirm the matching version is available in the Composer package
index before updating dependent package constraints.