Skip to content

Releases: webrium/foxdb

FoxDB 4.0.2

11 Jun 19:25
fd96998

Choose a tag to compare

What's Changed

  • V4/core foundation by @benkhalife in #46
  • fix(ci): resolve PHP 8.1 and PostgreSQL compatibility issues by @benkhalife in #48
  • fix(pgsql): embed RawExpression in UPDATE without placeholder by @benkhalife in #50
  • model json encodemodel returns and ide loses type after where first by @benkhalife in #52
  • Fix/where column name collision by @benkhalife in #55

Full Changelog: 3.1.2...4.0.2

FoxDB 4.0.1

11 Jun 16:31
eea0932

Choose a tag to compare

🦊 FoxDB v4 — A Full Database Toolkit

FoxDB started as a lightweight query builder. Version 4 is something bigger: a complete database toolkit for PHP 8.1+ with an ORM, schema management, migrations, and a richer query pipeline — all with zero external dependencies.


✨ What's New

Eloquent-style ORM

Define your database tables as PHP classes. FoxDB handles the rest — mass assignment protection, automatic timestamps, dirty tracking (only changed columns are written on save), and full JSON serialization with hidden fields and casts applied automatically.

Attribute Casting

Declare $casts on your model and FoxDB converts raw database values to the correct PHP type on every read. Integers come back as int, JSON columns as array, booleans as bool, and datetime columns as DateTime objects — no manual conversion needed.

Relations

Define relationships between models with hasOne, hasMany, belongsTo, belongsToMany, and hasManyThrough. Lazy loading works out of the box, and eager loading (with()) lets you eliminate N+1 queries with a single method call. Relations are included automatically when you call toArray().

Soft Deletes

Add use HasSoftDeletes to a model and delete operations set a deleted_at timestamp instead of removing the row. Soft-deleted rows are excluded from all queries by default, and can be restored at any time. withTrashed() and onlyTrashed() give you full control when you need it.

Local Scopes

Encapsulate reusable query conditions as methods on your model. A method named scopeActive becomes User::active() — fully chainable with other builder methods and other scopes.

Schema Builder

Create and modify tables using a fluent Blueprint API. Columns, indexes, foreign keys, unique constraints — all written in PHP, all generating the correct DDL for your driver.

Migrations

Version your schema changes with up() and down() methods. Run pending migrations, roll back the last batch, reset everything, or refresh the entire database in one call.

Collection

Query results are wrapped in a rich Collection class with map, filter, sort, chunk, pluck, groupBy, and aggregate methods. The collection is immutable — every transformation returns a new instance. It implements JsonSerializable, so json_encode($collection) just works.

Multi-driver Support

MySQL, PostgreSQL, and SQLite all work correctly with per-driver SQL generation. Identifier quoting, upsert syntax, boolean defaults, datetime types, and UPDATE semantics are all handled correctly for each database.

Query Log & Hooks

Log every query that runs, measure execution time, detect slow queries above a threshold, and attach beforeQuery / afterQuery callbacks for monitoring or external logging.

PHPUnit Test Suite

A new test suite with unit tests for SQL generation and model logic, and integration tests that run against all three supported drivers. CI runs the full suite on PHP 8.1, 8.2, and 8.3 across MySQL 8.0/8.4, PostgreSQL 15/16, and SQLite on every pull request.

IDE Autocompletion

Full @method PHPDoc annotations on the base Model class. Every query method — where, orderBy, limit, paginate, and all the rest — appears in your IDE's autocomplete when you call User:: or Post::.


🐛 Bug Fixes

  • Model::__callStatic() crashed when a Builder method returned a model instance. The return type was declared as Builder, but terminal Builder methods like first(), find(), and value() can return model instances, scalars, or null. PHP 8's strict return type enforcement caused a TypeError at runtime.

  • isset($model->relation) always returned false after eager loading. __isset() only checked $attributes, so loaded relations were invisible to isset() checks. It now checks both $attributes and $relations.

  • HasSoftDeletes not detected when inherited from a parent model. ReflectionClass::getTraits() only returns traits declared directly on a class. A subclass inheriting HasSoftDeletes from a parent was not recognized, so the WHERE deleted_at IS NULL scope was silently skipped. Fixed by walking the full class hierarchy.

  • PostgresGrammar::compileUpdate() caused a binding count mismatch for increment() and decrement(). The method always emitted col = ? for every column, even for RawExpression values that should be embedded directly. PostgreSQL received a ? placeholder with no bound value and rejected the query.

  • Connection::handleException() declared ): false as a standalone return type, which is only valid from PHP 8.2. Caused a fatal error on PHP 8.1 before any tests could run.

  • Integration test schemas used DATETIME and BOOLEAN DEFAULT 1, both invalid in PostgreSQL. PostgreSQL requires TIMESTAMP and TRUE/FALSE respectively. Cross-driver DDL helpers were added to IntegrationTestCase to handle these differences cleanly.


💬 Notes

FoxDB v4 is a major version with a new ORM layer built on top of the query builder. The query builder API from v3 is unchanged — existing code continues to work without modification. The new ORM features are purely additive.

Full Changelog: 3.1.2...4.0.1

FoxDB 4.0.0

11 Jun 13:42
53933f0

Choose a tag to compare

🦊 FoxDB v4 — A Full Database Toolkit

FoxDB started as a lightweight query builder. Version 4 is something bigger: a complete database toolkit for PHP 8.1+ with an ORM, schema management, migrations, and a richer query pipeline — all with zero external dependencies.


✨ What's New

Eloquent-style ORM

Define your database tables as PHP classes. FoxDB handles the rest — mass assignment protection, automatic timestamps, dirty tracking (only changed columns are written on save), and full JSON serialization with hidden fields and casts applied automatically.

Attribute Casting

Declare $casts on your model and FoxDB converts raw database values to the correct PHP type on every read. Integers come back as int, JSON columns as array, booleans as bool, and datetime columns as DateTime objects — no manual conversion needed.

Relations

Define relationships between models with hasOne, hasMany, belongsTo, belongsToMany, and hasManyThrough. Lazy loading works out of the box, and eager loading (with()) lets you eliminate N+1 queries with a single method call. Relations are included automatically when you call toArray().

Soft Deletes

Add use HasSoftDeletes to a model and delete operations set a deleted_at timestamp instead of removing the row. Soft-deleted rows are excluded from all queries by default, and can be restored at any time. withTrashed() and onlyTrashed() give you full control when you need it.

Local Scopes

Encapsulate reusable query conditions as methods on your model. A method named scopeActive becomes User::active() — fully chainable with other builder methods and other scopes.

Schema Builder

Create and modify tables using a fluent Blueprint API. Columns, indexes, foreign keys, unique constraints — all written in PHP, all generating the correct DDL for your driver.

Migrations

Version your schema changes with up() and down() methods. Run pending migrations, roll back the last batch, reset everything, or refresh the entire database in one call.

Collection

Query results are wrapped in a rich Collection class with map, filter, sort, chunk, pluck, groupBy, and aggregate methods. The collection is immutable — every transformation returns a new instance. It implements JsonSerializable, so json_encode($collection) just works.

Multi-driver Support

MySQL, PostgreSQL, and SQLite all work correctly with per-driver SQL generation. Identifier quoting, upsert syntax, boolean defaults, datetime types, and UPDATE semantics are all handled correctly for each database.

Query Log & Hooks

Log every query that runs, measure execution time, detect slow queries above a threshold, and attach beforeQuery / afterQuery callbacks for monitoring or external logging.

PHPUnit Test Suite

A new test suite with unit tests for SQL generation and model logic, and integration tests that run against all three supported drivers. CI runs the full suite on PHP 8.1, 8.2, and 8.3 across MySQL 8.0/8.4, PostgreSQL 15/16, and SQLite on every pull request.

IDE Autocompletion

Full @method PHPDoc annotations on the base Model class. Every query method — where, orderBy, limit, paginate, and all the rest — appears in your IDE's autocomplete when you call User:: or Post::.


🐛 Bug Fixes

  • Model::__callStatic() crashed when a Builder method returned a model instance. The return type was declared as Builder, but terminal Builder methods like first(), find(), and value() can return model instances, scalars, or null. PHP 8's strict return type enforcement caused a TypeError at runtime.

  • isset($model->relation) always returned false after eager loading. __isset() only checked $attributes, so loaded relations were invisible to isset() checks. It now checks both $attributes and $relations.

  • HasSoftDeletes not detected when inherited from a parent model. ReflectionClass::getTraits() only returns traits declared directly on a class. A subclass inheriting HasSoftDeletes from a parent was not recognized, so the WHERE deleted_at IS NULL scope was silently skipped. Fixed by walking the full class hierarchy.

  • PostgresGrammar::compileUpdate() caused a binding count mismatch for increment() and decrement(). The method always emitted col = ? for every column, even for RawExpression values that should be embedded directly. PostgreSQL received a ? placeholder with no bound value and rejected the query.

  • Connection::handleException() declared ): false as a standalone return type, which is only valid from PHP 8.2. Caused a fatal error on PHP 8.1 before any tests could run.

  • Integration test schemas used DATETIME and BOOLEAN DEFAULT 1, both invalid in PostgreSQL. PostgreSQL requires TIMESTAMP and TRUE/FALSE respectively. Cross-driver DDL helpers were added to IntegrationTestCase to handle these differences cleanly.


💬 Notes

FoxDB v4 is a major version with a new ORM layer built on top of the query builder. The query builder API from v3 is unchanged — existing code continues to work without modification. The new ORM features are purely additive.

Full Changelog: 3.1.2...4.0.0

FoxDB 3.1.2

22 May 12:39
f9bd343

Choose a tag to compare

What's Changed

  • feat: add static query() method to Model class by @benkhalife in #39

Full Changelog: 3.1.1...3.1.2

3.1.1

12 Sep 12:37
8fdcb18

Choose a tag to compare

fix: Add explicit nullable type for $previous parameter in constructor

Full Changelog: 3.1.0...3.1.1

3.1.0

07 Sep 07:17

Choose a tag to compare

What's Changed

Full Changelog: 3.0.4...3.1.0

3.0.4

23 May 07:52
92cbfd5

Choose a tag to compare

What's Changed

  • 30 bug in date operations by @parsgit in #31

Full Changelog: 3.0.3...3.0.4

3.0.3

07 May 20:05
aab2a94

Choose a tag to compare

Full Changelog: 3.0.2...3.0.3

3.0.2

11 Jan 15:18
4f346ea

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: 3.0.1...3.0.2

FoxDB 3.0.1

02 Sep 08:02

Choose a tag to compare