Download the PHP package luany/database without Composer
On this page you can find all versions of the php package luany/database. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download luany/database
More information about luany/database
Files in luany/database
Package database
Short Description Database layer for the Luany ecosystem — PDO connection, Model base, QueryBuilder, and Migration engine.
License MIT
Homepage https://github.com/luany-ecosystem/luany-database
Informations about the package database
luany/database
PDO connection, fluent Query Builder, Active Record ORM, Relations, Pagination, Soft Deletes, Migration engine, and Seeders for the Luany ecosystem.
Version: v1.1.0 | PHP: >= 8.2 | License: MIT Author: António Ambrósio Ngola | Org: luany-ecosystem
Table of Contents
- Installation
- Connection
- QueryBuilder
- Fluent API
- Aggregates
- Pagination
- Raw Methods
- Model
- Defining a Model
- CRUD
- Relationships
- Eager Loading
- Soft Deletes
- Transactions
- Migrations
- Seeders
- Changelog
1. Installation
2. Connection
Connection is a PDO wrapper. It does not enforce a singleton — that responsibility belongs to the application's DatabaseServiceProvider.
Connection Methods
| Method | Signature | Description |
|---|---|---|
make |
static make(array $config): static |
Create from config array |
fromPdo |
static fromPdo(\PDO $pdo): static |
Wrap an existing PDO |
getPdo |
getPdo(): \PDO |
Get the underlying PDO |
execute |
execute(string $sql, array $bindings = []): \PDOStatement |
Prepare and execute |
lastInsertId |
lastInsertId(): string |
Last inserted row ID |
beginTransaction |
beginTransaction(): bool |
Begin a transaction |
commit |
commit(): bool |
Commit the transaction |
rollBack |
rollBack(): bool |
Roll back the transaction |
transaction |
transaction(callable $callback): mixed |
Execute callback in a transaction |
inTransaction |
inTransaction(): bool |
Whether inside a transaction |
3. QueryBuilder
Fluent query builder with full prepared-statement safety. All user-supplied values are bound — never interpolated.
3.1 Fluent API
SELECT
WHERE Clauses
ORDER BY, LIMIT, OFFSET
INSERT
UPDATE
DELETE
3.2 Aggregates
3.3 Pagination
paginate() executes two queries: one COUNT(*) to get the total, one SELECT with LIMIT/OFFSET for the page data. All WHERE and ORDER BY clauses are respected by both queries.
Edge cases handled:
$page < 1is clamped to1$perPage < 1throws\InvalidArgumentException- Empty result set:
total=0,lastPage=1,from=null,to=null
3.4 Raw Methods
Available for backward-compatibility and complex queries that the fluent API cannot express.
4. Model
Model is an abstract Active Record base class. Extend it to define your application models.
4.1 Defining a Model
Register the connection (done once in your DatabaseServiceProvider):
4.2 CRUD
4.3 Relationships
Define relationship methods on your model. They return Relation descriptor objects — no query is executed when the method is called. The query runs only on property access (lazy) or via with() (eager).
hasOne — one-to-one (FK on related table)
hasMany — one-to-many (FK on related table)
belongsTo — inverse (FK on THIS table)
Key signatures:
All FK/owner-key arguments are optional. Defaults follow the convention {table_singular}_id (e.g. users → user_id). Pass explicit keys for irregular plurals or non-standard schemas.
Relation results are cached after the first access:
Manual relation management:
4.4 Eager Loading
Prevents N+1 queries. Instead of executing one query per model, with() executes one batched WHERE IN query per relation for the entire collection.
with() returns an EagerProxy that delegates to all() and find(). After execution, the eager-load state is consumed and reset — no cross-request leakage.
4.5 Soft Deletes
Add the SoftDeletes trait to a model. Requires a deleted_at DATETIME DEFAULT NULL column.
Migration:
Behaviour:
5. Transactions
6. Migrations
Migrations live in database/migrations/ and are ordered by filename timestamp.
Defining a Migration
MigrationRunner
The _migrations table is created automatically on first use.
7. Seeders
Seeders live in database/seeders/ and populate the database with initial or test data.
Defining a Seeder
DatabaseSeeder — entry point
DatabaseSeeder is the root seeder. It chains other seeders via $this->call():
All classes referenced via call() are loaded automatically before any seeder runs — no manual require needed.
SeederRunner
SeederRunner loads all PHP files in the seeders directory before executing — call() chains always resolve regardless of file order.
Seeder base class
| Method | Description |
|---|---|
run(\PDO $pdo): void |
Abstract — implement your insert logic here |
call(string ...$classes): void |
Chain one or more seeders. All receive the same PDO instance. |
8. Changelog
v1.1.0 — Seeders
New — src/Seeder/Seeder.php
- Abstract base class for all seeders. Defines
run(\PDO $pdo): voidcontract. call(string ...$seederClasses): void— chain seeders from withinDatabaseSeeder. All called seeders receive the same PDO instance.- PDO injected via
setPdo()beforerun()— managed bySeederRunner.
New — src/Seeder/SeederRunner.php
- Discovers and executes seeders from a given directory.
- Loads all PHP files in the seeders directory before running —
call()chains always resolve. - Optional output callback
fn(string $class, string $status): void. - Throws
\RuntimeExceptionif target class not found or does not extendSeeder.
Tests added: SeederRunnerTest (9 tests)
Total: 178 → 187 tests, 284 → 296 assertions — all green.
v0.3.0 — Phase 3: Relations, Eager Loading, Pagination, Soft Deletes
New — src/Relations/
Relation— abstract base withgetResults()andbatchLoad()contractsHasOne— one-to-one relation with true eager batch loading (WHERE IN)HasMany— one-to-many relation with true eager batch loading (WHERE IN + group by FK)BelongsTo— inverse relation with true eager batch loading (WHERE IN + key by owner key)
New — src/Concerns/SoftDeletes.php
- Trait: overrides
newQuery()to addWHERE deleted_at IS NULLscope - Adds
delete()(setsdeleted_at),forceDelete(),restore(),trashed() - Adds static
withTrashed()andonlyTrashed()(both accept ORDER BY)
New — src/EagerProxy.php
- Returned by
Model::with()— delegatesall()andfind()with eager-load injection - No cross-request state leakage (eager-load list consumed and reset after each query)
New — src/PaginationResult.php
- Immutable value object:
data,total,perPage,currentPage,lastPage,from,to - Methods:
hasMore(),hasPrev(),toArray()
Modified — src/QueryBuilder.php
- Added
paginate(int $perPage = 15, int $page = 1): PaginationResult - Two queries per call: COUNT(*) + SELECT with LIMIT/OFFSET
- Page clamped to ≥ 1;
perPage < 1throws\InvalidArgumentException
Modified — src/Model.php
$attributes,$relations,$existschanged fromprivatetoprotected(required bySoftDeletestrait)getAttribute()changed fromprotectedtopublic(required by Relation classes)validateOrderBy()changed fromprivatetoprotected(required bySoftDeletestrait)- Added
public static hydrateFromRow(array $row): static(required by Relation classes) - Added
public static setEagerLoad(array $relations): void(used byEagerProxy) with()now returnsEagerProxyinstead of a plain instance- Relationship methods (
hasOne,hasMany,belongsTo) now return typedRelationdescriptor objects instead of executing queries directly getRelation()now resolvesRelationdescriptors viagetResults()(lazy load with cache)eagerLoadRelation()now delegates toRelation::batchLoad()(true N+1-free eager loading)- Added
fill(array $attributes): void
Tests added: RelationsTest (15), EagerLoadTest (13), PaginateTest (27), SoftDeletesTest (21)
Total: 170 tests, 274 assertions — all green.
v0.2.0 — Phase 1: Fluent QueryBuilder & Transactions
New — QueryBuilder fluent API
table(),select(),where(),orWhere(),whereIn(),whereNull(),whereNotNull()orderBy(),limit(),offset()get(),first(),insert(),update(),delete(),count(),exists()raw()/query()/statement()preserved for backward-compatibility- All queries use prepared statements — no string interpolation of user values
New — Connection transaction methods
beginTransaction(),commit(),rollBack(),inTransaction()transaction(callable)— auto-commit / auto-rollback wrapper
New — Connection::fromPdo() and Connection::make()
- Replaces the legacy
configure()/getInstance()singleton pattern
Modified — Model
find(),all(),create(),save(),delete()refactored to use the fluent QueryBuilder internallyall()ORDER BY clause validated against a strict regex whitelist (SQL injection prevention)- Added
where(),firstWhere(),count()static methods - Added
setConnection()/getConnection()(replaces global singleton)
Tests: 94 tests, 136 assertions.
v0.1.3 and earlier
Initial release. Raw-query-only QueryBuilder. Basic Model with hand-built SQL strings. MigrationRunner, MigrationRepository, Migration base class.