Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
6711c05
Fixes PradoUnit::processException to show the first Db Error Message.
belisoful Apr 23, 2026
ee64c31
Oracle Fix
belisoful Apr 23, 2026
c34ddef
PradoUnit correction and PDO Driver Names.
belisoful Apr 23, 2026
6a96679
Github CI php matrix removes firebird and sqlsrv as default on.
belisoful Apr 23, 2026
8acd66e
using Firebird Casting for column names.
belisoful Apr 23, 2026
d753b9c
fixed the string search for specifics
belisoful Apr 23, 2026
37b76cb
Encoding Firebird Transaction rules.
belisoful Apr 23, 2026
487eb3d
Centralized PDO Database Capabilities.
belisoful Apr 24, 2026
a853756
Adds Data.Common interfaces.
belisoful Apr 30, 2026
4731203
Made the conditions of serial transactions more accurate.
belisoful Apr 30, 2026
1940b30
Updated TDbDriverCapabilities.
belisoful Apr 30, 2026
ad5e94e
removed serial transactions, replaced by TDbTransaction::beginTransac…
belisoful May 1, 2026
813ba19
Updated DbSpecific integration tests.
belisoful May 1, 2026
2866591
Updated unit tests for firebird, ibm, oracle, and sqlite.
belisoful May 2, 2026
127c312
sqlite updated integration tests
belisoful May 2, 2026
b06476f
updated oracle and sqlite code.
belisoful May 2, 2026
b3d2567
Oracle unit test update
belisoful May 2, 2026
f4c6884
Oracle DB Fixes
belisoful May 3, 2026
3e51de6
Better PHP class doc blocks for Data.Common.*
belisoful May 4, 2026
b3d43b8
TDbCommand refactoring, corrects TOracleDbCommand
belisoful May 4, 2026
c373d49
TDbConnection::_getZappableSleepProps update
belisoful May 4, 2026
9afe564
sqlite fix
belisoful May 4, 2026
b85652f
removed unnecessary method
belisoful May 4, 2026
f436006
TSqlCriteria docblock space reversion
belisoful May 4, 2026
527d1ae
removed getDbMetaData from TDbTransacion, it was a prototype
belisoful May 4, 2026
ce176df
integrates fxActiveRecordCreateScaffoldInput into TDbDriverCapabiliti…
belisoful May 4, 2026
b8219af
fxActiveRecordCreateScaffoldInput changed to returning a class, not a…
belisoful May 4, 2026
67ce6f1
Adding missing Exception messages.
belisoful May 4, 2026
180b241
TDbCommand and TDbConnection adding at-since to _getZappableSleepProps.
belisoful May 4, 2026
cd75be9
TDbDataReader using accessors for properties.
belisoful May 4, 2026
fc580ef
fxActiveRecordCreateScaffoldInput => fxActiveRecordScaffoldInputClass
belisoful May 4, 2026
f746218
removes protected resolveCharsetForDriver
belisoful May 4, 2026
63f8b1e
TDbCommandBuilder::requireActiveTransaction moved to assertActiveTran…
belisoful May 4, 2026
a4a5544
Fix for Windows retaining sqlite test files
belisoful May 5, 2026
91155fb
Mssql is converted to the more appropriate SqlSrv; matching the MS ‘S…
belisoful May 5, 2026
ab8f671
Update TTableGateway::getTableExists uses proper Exception.
belisoful May 5, 2026
4e8eee6
correcting yml for sqlsrv
belisoful May 5, 2026
99fdabd
Fixing Windows pgsql user password due to Windows default config bein…
belisoful May 5, 2026
0c518d1
removed original TSqliteCommandBuilder that was used for comparison d…
belisoful May 5, 2026
280bff9
TDbTransaction reorganization
belisoful May 5, 2026
6d58cf3
standardized the php class doc blocks.
belisoful May 5, 2026
240ebbe
more standardization of php class doc blocks.
belisoful May 5, 2026
99ee5f0
Doc Block update
belisoful May 5, 2026
7b941ef
Adds TDbDriver::EXTENSION_MYSQLI and EXTENSION_MSSQL for driver speci…
belisoful May 6, 2026
acd65bf
Using the Interfaces rather than the TDb classes for abstraction thro…
belisoful May 6, 2026
ba72cea
Restrictions on dsn charsets (sqlsrv)
belisoful May 6, 2026
fcfcdba
upgrade Data classes __sleep to _getZappableSleepProps
belisoful May 6, 2026
87ca0d8
Differentiating IDataColumn from IDbColumn for PDO.
belisoful May 8, 2026
b804f2a
TDataCharset is IANA compliant
belisoful May 8, 2026
eb357c7
Standardized the two ‘fx’ global events for custom Data classes
belisoful May 8, 2026
d74da37
Doc Block Tweaks
belisoful May 11, 2026
320b96a
PradoUnit::setUpConnection doc block, documenting EXACTLY what it doe…
belisoful May 11, 2026
156209f
Mysql Refactor for deprecation of column display width
belisoful May 11, 2026
fd9bd6b
Better Upsert - changes conflict data to update existing data or cust…
belisoful May 11, 2026
298b472
updates “initdb_mysql.sql” to account for deprecating display width.
belisoful May 11, 2026
a2542fe
Full Mysql Data Unit tests
belisoful May 11, 2026
8e3cf3f
Sqlite ActiveRecord, Common, and TableGateway unit tests
belisoful May 11, 2026
344425d
Sqlite SqlMap unit tests
belisoful May 11, 2026
9e9c462
Pgsql ActiveRecord, Common, and TableGateway unit tests
belisoful May 11, 2026
8e67e66
Pgsql SqlMap unit tests
belisoful May 11, 2026
d777ac7
SqlMap/common and BaseCase update - ActiveRecordSqlMapTestCase update
belisoful May 11, 2026
5ce1c01
Firebird ActiveRecord, Common, and TableGateway unit tests
belisoful May 11, 2026
a854c8e
Firebird SqlMap unit tests
belisoful May 11, 2026
2f9436a
SqlMap sqlite ActiveRecord.xml update to limit 1
belisoful May 11, 2026
74607d8
Oracle ActiveRecord, Common, and TableGateway unit tests.
belisoful May 11, 2026
9309af6
Oracle SqlMap unit tests
belisoful May 11, 2026
4f95e00
SqlMap mssql ActiveRecord
belisoful May 11, 2026
a2f5cf3
SqlMap Pgql inheritance test
belisoful May 11, 2026
51d5d3c
Ibm DB2 ActiveRecord, Common, and TableGateway unit tests
belisoful May 11, 2026
ac324a2
IBM DB2 SqlMap unit tests
belisoful May 11, 2026
4218fb7
MS SqlSrv ActiveRecord, Common, and TableGateway unit tests
belisoful May 11, 2026
e2e533d
Ms SqlSrv SqlMap unit tests
belisoful May 11, 2026
e97d701
Updated ParameterMap and Statement test to skip in unavailable.
belisoful May 11, 2026
4038d74
removed old SqlMap mssql directory
belisoful May 11, 2026
72785cb
filling in sqlite TableGateway getTableExists gap
belisoful May 11, 2026
7320929
ActiveRecord SqlMap sqlite bug fix.
belisoful May 12, 2026
eac479e
Adds TActiveRecord CONFLICT_COLUMNS and UPSERT_UPDATE_DATA for upsert.
belisoful May 12, 2026
8c426c7
TDbCommandBuilder::buildMergeStatement named columns take precedence …
belisoful May 12, 2026
497cec1
Firebird and pgsql test fixes
belisoful May 12, 2026
a11c861
TActiveRecordGateway::getCommand replaces connection when stale
belisoful May 12, 2026
c61358a
TActiveRecord::setColumnValue is column caseinsensitive .
belisoful May 12, 2026
cca95c1
BaseActiveRecord and Oracle Update
belisoful May 12, 2026
24df3e9
Firebird fix for Skipped tests
belisoful May 13, 2026
99ecad2
IBM DB2 and MS SqlSrv test corrections
belisoful May 13, 2026
d76304e
oracle database.sql fix
belisoful May 13, 2026
7002656
Fixing skipped TableGateway unit tests with comment as to why and todo.
belisoful May 13, 2026
8bb29aa
Firebird Rollback bug fix in TDbTransaction
belisoful May 13, 2026
00eee5b
IbmScriptRunner and Firebird ScriptRunner and their respective bug fixes
belisoful May 13, 2026
1c6b091
SqlMap corrections for databases with UPPER_CASE table names.
belisoful May 14, 2026
0a45e1c
TDbTransaction - completeTransaction catches closed pdo; firebird rol…
belisoful May 14, 2026
6ced791
TDbTransaction::rollback tweak for firebird
belisoful May 14, 2026
fb599d4
TDbCommand::getColumnTypeFromValue catch dead connections TDbCommand …
belisoful May 14, 2026
793579f
TMappedStatement::fillResultObjectProperty getResultMapGroupKey getPo…
belisoful May 14, 2026
68de216
IBM DB2 fix and sqlmap update; oracle sqlmap update; firebird databas…
belisoful May 14, 2026
77a2a42
TDbConnection::open - Mysql attributes “downgraded”? for compatibility
belisoful May 15, 2026
598476f
php-cs-fixer update
belisoful May 15, 2026
c643149
Merge branch 'pradosoft:master' into db-modern-exec
belisoful May 18, 2026
05c56d5
PradoUnit fixes and unit tests
belisoful May 19, 2026
8d8d86b
phpunit.xml update for each DbSpecific
belisoful May 19, 2026
d1ffc9d
Adds Mysql, pgsql, and sqlite integration jobs to yml - separate from…
belisoful May 22, 2026
7deb631
Adds DB initialization before local tests
belisoful May 22, 2026
ac82a40
TDbConnection - Socket support for Mysql and Pgsql
belisoful May 22, 2026
d968c8a
TMappedStatement - Supports Closures
belisoful May 22, 2026
2320cee
TPgsqlMetaData and TSqliteMetaData tweaks for columns
belisoful May 22, 2026
7ef1fe5
Updated Data class unit tests
belisoful May 22, 2026
d762359
Unit tetsts for Data - not DbSpecific
belisoful May 22, 2026
bc5ad66
mysql, sqlite, and pgsql infrastructure update - sqlmap xml and db.sql
belisoful May 22, 2026
a120214
Active Record and DataGateway unit test update
belisoful May 22, 2026
11195e4
Sqlite Unit Tests
belisoful May 22, 2026
0bf0c90
Pgsql Unit Test update
belisoful May 22, 2026
aac9ef8
Mysql Unit Test update
belisoful May 22, 2026
2528909
TDbConnection php-cs-fixer correction.
belisoful May 23, 2026
faff7ea
Firebird unit test update
belisoful May 23, 2026
645607e
Ibm DB2 unit test update
belisoful May 23, 2026
e551a96
Oracle unit test update
belisoful May 23, 2026
73896f6
MS SqlServer unit test update
belisoful May 23, 2026
e0525a0
Moved a Pgsql unit test
belisoful May 23, 2026
90da3b3
MySQL - fixed the clashing class names in mysql
belisoful May 23, 2026
9e9c672
SqlMap fix for unit test common.php and mssql and firebird
belisoful May 23, 2026
858f4d7
TDbTransaction - removed extras for simplified IDbTransaction contract
belisoful May 23, 2026
c20f5ad
Merge branch 'master' into db-modern-exec
belisoful May 23, 2026
86f0f47
TDbDriverCapabilities::normalizeDriver to normalize mysqli to mysql, …
belisoful May 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
134 changes: 126 additions & 8 deletions .github/workflows/prado.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
with:
php-version: ${{ matrix.php-versions }}
extensions: ctype, dom, intl, json, mbstring, memcached, pdo_mysql, pdo_pgsql, pdo_sqlite, openssl, pcre, spl, zlib
extensions: ctype, dom, intl, json, mbstring, memcached, pdo_mysql, pdo_pgsql, pdo_sqlite, openssl, pcre, spl, zlib, :pdo_firebird, :pdo_sqlsrv
tools: php-cs-fixer, phpstan, cs2pr

- name: Validate composer.json and composer.lock
Expand Down Expand Up @@ -306,10 +306,130 @@ jobs:
& "$env:PGBIN\pg_ctl.exe" start -D $env:PGDATA -w
& "$env:PGBIN\createdb.exe" -h 127.0.0.1 -U postgres prado_unitest
& "$env:PGBIN\psql.exe" -h 127.0.0.1 -U postgres prado_unitest -f .\tests\initdb_pgsql.sql
# Windows PostgreSQL uses scram-sha-256 (no trust); set the password so
# setupPgsqlConnection('prado_unitest', 'prado_unitest') can authenticate.
& "$env:PGBIN\psql.exe" -h 127.0.0.1 -U postgres -c "ALTER ROLE prado_unitest WITH PASSWORD 'prado_unitest';"

- name: Run Unit Tests
run: composer unittest

db-mysql:
name: Prado Data (MySQL)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP with MySQL extensions
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: ctype, dom, intl, json, mbstring, pdo_mysql, openssl, pcre, spl, zlib

- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader

- name: Setup MySQL schema
run: |
sudo systemctl start mysql.service
mysql -uroot -proot < ./tests/initdb_mysql.sql

- name: Run MySQL tests
run: php vendor/bin/phpunit --testsuite db-mysql

db-pgsql:
name: Prado Data (PostgreSQL)
runs-on: ubuntu-latest
services:
postgres:
image: postgres
env:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP with PostgreSQL extensions
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: ctype, dom, intl, json, mbstring, pdo_pgsql, openssl, pcre, spl, zlib

- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader

- name: Setup PostgreSQL schema
run: |
createdb -h 127.0.0.1 -U postgres prado_unitest
psql -h 127.0.0.1 -U postgres -a -w prado_unitest -f ./tests/initdb_pgsql.sql
env:
PGPASSWORD: postgres

- name: Run PostgreSQL tests
run: php vendor/bin/phpunit --testsuite db-pgsql

db-sqlite:
name: Prado Data (SQLite)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP with SQLite extensions
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: ctype, dom, intl, json, mbstring, pdo_sqlite, openssl, pcre, spl, zlib

- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader

- name: Run SQLite tests
run: php vendor/bin/phpunit --testsuite db-sqlite

db-sqlsrv:
name: Prado Data (Microsoft SQL Server)
runs-on: ubuntu-latest
Expand Down Expand Up @@ -361,10 +481,10 @@ jobs:
run: >-
/opt/mssql-tools18/bin/sqlcmd -C
-U sa -P Prado_Unitest1
-i ./tests/initdb_mssql.sql
-i ./tests/initdb_sqlsrv.sql

- name: Run SQL Server tests
run: php vendor/bin/phpunit tests/unit/Data/DbSpecific/Mssql/
run: php vendor/bin/phpunit --testsuite db-sqlsrv

db-firebird:
name: Prado Data (Firebird)
Expand Down Expand Up @@ -425,7 +545,7 @@ jobs:
"

- name: Run Firebird tests
run: php vendor/bin/phpunit tests/unit/Data/DbSpecific/Firebird/
run: php vendor/bin/phpunit --testsuite db-firebird

db-oracle:
name: Prado Data (Oracle)
Expand Down Expand Up @@ -498,14 +618,12 @@ jobs:
bash -c 'source ~/.bash_profile && sqlplus -S prado_unitest/prado_unitest@//localhost/FREEPDB1 @/tmp/initdb_oracle.sql'

- name: Run Oracle tests
run: php vendor/bin/phpunit tests/unit/Data/DbSpecific/Oracle/
run: php vendor/bin/phpunit --testsuite db-oracle
env:
ORACLE_SERVICE_NAME: FREEPDB1

db-ibm:
name: Prado Data (IBM DB2)
# DB2 image takes 2-3 minutes to start; only run on explicit manual dispatch.
# if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
services:
db2:
Expand Down Expand Up @@ -554,7 +672,7 @@ jobs:
su - db2inst1 -c "db2 connect to pradount && db2 -td@ -f /tmp/initdb.sql"

- name: Run IBM DB2 tests
run: php vendor/bin/phpunit tests/unit/Data/DbSpecific/Ibm/
run: php vendor/bin/phpunit --testsuite db-ibm
env:
DB2_USER: db2inst1
DB2_PASSWORD: Prado_Unitest1
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,13 @@
"npm run playwright:install",
"@setup-demos"
],
"dbinit": "php tests/test_tools/initdb.php",
"setup-demos": "bash tests/setup-demos.sh",
"gendoc": "phpdoc --template=./vendor/pradosoft/prado-phpdoc-template",
"fix": "vendor/bin/php-cs-fixer fix",
"stan": "vendor/bin/phpstan analyse --memory-limit=512M",
"unittest": "vendor/bin/phpunit --testsuite unit",
"unittest": "vendor/bin/phpunit --testsuite unit,db-mysql,db-pgsql,db-sqlite",
"dbtest": "vendor/bin/phpunit --testsuite db-mysql,db-pgsql,db-sqlite",
"fulltest": [
"@fix",
"@stan",
Expand Down
16 changes: 10 additions & 6 deletions framework/Caching/TDbCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Prado\Data\TDataSourceConfig;
use Prado\Data\TDbConnection;
use Prado\Data\TDbDriver;
use Prado\Data\TDbDriverCapabilities;
use Prado\Data\TDbPropertiesTrait;
use Prado\Exceptions\TConfigurationException;
use Prado\TPropertyValue;
Expand Down Expand Up @@ -130,8 +131,11 @@ class TDbCache extends TCache implements \Prado\Util\IDbModule
*/
public function init($config)
{
$this->getApplication()->attachEventHandler('OnLoadStateComplete', [$this, 'doInitializeCache']);
$this->getApplication()->attachEventHandler('OnSaveState', [$this, 'doFlushCacheExpired']);
$app = $this->getApplication();
if ($app) {
$app->attachEventHandler('OnLoadStateComplete', [$this, 'doInitializeCache']);
$app->attachEventHandler('OnSaveState', [$this, 'doFlushCacheExpired']);
}
parent::init($config);
}

Expand Down Expand Up @@ -194,7 +198,7 @@ protected function initializeCache($force = false)
if ($this->_autoCreate) {
Prado::trace('Autocreate: ' . $this->_cacheTable, TDbCache::class);

$driver = $db->getDriverName();
$driver = TDbDriverCapabilities::normalizeDriver($db->getDriverName());
if ($driver === TDbDriver::DRIVER_MYSQL) {
$blob = 'LONGBLOB';
} elseif ($driver === TDbDriver::DRIVER_PGSQL) {
Expand Down Expand Up @@ -456,10 +460,10 @@ protected function setValue($key, $value, $expire)
$this->initializeCache();
}
$db = $this->getDbConnection();
$driver = $db->getDriverName();
if (in_array($driver, [TDbDriver::DRIVER_MYSQL, TDbDriver::EXTENSION_MYSQLI, TDbDriver::DRIVER_SQLITE, TDbDriver::DRIVER_IBM, TDbDriver::DRIVER_OCI, TDbDriver::DRIVER_SQLSRV, TDbDriver::EXTENSION_MSSQL, TDbDriver::DRIVER_DBLIB, TDbDriver::DRIVER_PGSQL])) {
$driver = TDbDriverCapabilities::normalizeDriver($db->getDriverName());
if (in_array($driver, [TDbDriver::DRIVER_MYSQL, TDbDriver::DRIVER_SQLITE, TDbDriver::DRIVER_IBM, TDbDriver::DRIVER_OCI, TDbDriver::DRIVER_SQLSRV, TDbDriver::DRIVER_DBLIB, TDbDriver::DRIVER_PGSQL])) {
$expire = ($expire <= 0) ? 0 : time() + $expire;
if (in_array($driver, [TDbDriver::DRIVER_MYSQL, TDbDriver::EXTENSION_MYSQLI, TDbDriver::DRIVER_SQLITE])) {
if (in_array($driver, [TDbDriver::DRIVER_MYSQL, TDbDriver::DRIVER_SQLITE])) {
$sql = "REPLACE INTO {$this->_cacheTable} (itemkey,value,expire) VALUES (:key,:value,$expire)";
} elseif ($driver === TDbDriver::DRIVER_PGSQL) {
$sql = "INSERT INTO {$this->_cacheTable} (itemkey, value, expire) VALUES (:key, :value, :expire) " .
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
namespace Prado\Data\ActiveRecord\Exceptions;

/**
* TActiveRecordConfigurationException class.
* TActiveRecordConfigurationException class
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @since 3.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use Prado\Prado;

/**
* TActiveRecordException class
*
* Base exception class for Active Records.
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
Expand Down
3 changes: 3 additions & 0 deletions framework/Data/ActiveRecord/Exceptions/messages.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ ar_relations_undefined = Unable to determine Active Record relationships be
ar_undefined_relation_prop = Unable to find {1}::${2}['{0}'], Active Record relationship definition for property "{0}" not found in entries of {1}::${2}.
ar_invalid_relationship = Invalid active record relationship.
ar_relations_missing_fk = Unable to find foreign key relationships in table '{0}' that corresponds to table '{1}'.
ar_belongs_to_multiple_result = BelongsTo/HasOne relationship returned more than one result but exactly one was expected.
scaffold_unable_to_find_edit_view = Unable to find scaffold edit view control with ID '{0}'.
scaffold_unable_to_find_list_view = Unable to find scaffold list view control with ID '{0}'.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use Prado\Data\ActiveRecord\Exceptions\TActiveRecordException;

/**
* TActiveRecordBelongsTo class
*
* Implements the foreign key relationship (TActiveRecord::BELONGS_TO) between
* the source objects and the related foreign object. Consider the
* <b>entity</b> relationship between a Team and a Player.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
namespace Prado\Data\ActiveRecord\Relations;

/**
* TActiveRecordHasMany class
*
* Implements TActiveRecord::HAS_MANY relationship between the source object having zero or
* more foreign objects. Consider the <b>entity</b> relationship between a Team and a Player.
* ```php
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Prado\Prado;

/**
* TActiveRecordHasManyAssociation class
*
* Implements the M-N (many to many) relationship via association table.
* Consider the <b>entity</b> relationship between Articles and Categories
* via the association table <tt>Article_Category</tt>.
Expand Down
2 changes: 2 additions & 0 deletions framework/Data/ActiveRecord/Relations/TActiveRecordHasOne.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Prado\Prado;

/**
* TActiveRecordHasOne class
*
* TActiveRecordHasOne models the object relationship that a record (the source object)
* property is an instance of foreign record object having a foreign key
* related to the source object. The HAS_ONE relation is very similar to the
Expand Down
62 changes: 61 additions & 1 deletion framework/Data/ActiveRecord/Relations/TActiveRecordRelation.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,67 @@
use Prado\Prado;

/**
* Base class for active record relationships.
* TActiveRecordRelation class
*
* Abstract base class for all Active Record relationship handlers.
*
* Active Record relationships are declared via the static `$RELATIONS` array on
* each {@see TActiveRecord} subclass. Each entry maps a property name to an
* array whose first element is one of the four relationship constants and whose
* second element is the foreign record class name:
*
* ```php
* public static $RELATIONS = [
* 'profile' => [self::HAS_ONE, 'ProfileRecord'],
* 'orders' => [self::HAS_MANY, 'OrderRecord'],
* 'team' => [self::BELONGS_TO, 'TeamRecord'],
* 'categories' => [self::HAS_MANY_ASSOC, 'CategoryRecord', 'Article_Category'],
* ];
* ```
*
* The four relationship types are:
*
* - **HAS_ONE** ({@see TActiveRecordHasOne}) — the foreign table carries a foreign key
* that points back to this record's primary key. The related property is a single
* object (or `null`).
* - **HAS_MANY** ({@see TActiveRecordHasMany}) — same foreign-key direction as HAS_ONE,
* but the related property is a collection (array) of foreign objects.
* - **BELONGS_TO** ({@see TActiveRecordBelongsTo}) — this record's table carries the
* foreign key that points to the related record's primary key. The related
* property is a single object (or `null`).
* - **HAS_MANY_ASSOC** ({@see TActiveRecordHasManyAssociation}) — a many-to-many
* relationship resolved through an intermediate association table. A third
* element in the `$RELATIONS` entry names the association table.
*
* ## Fetching related objects
*
* Related objects are fetched lazily by chaining a relationship call onto a
* finder method call:
*
* ```php
* // Fetch all teams with their players eagerly loaded.
* $teams = TeamRecord::finder()->withPlayers()->findAll();
*
* // Chain multiple relationships.
* $articles = ArticleRecord::finder()->withCategories()->withAuthor()->findAll();
* ```
*
* The {@see __call()} method intercepts `with<Property>()` calls, delegates the
* underlying finder call to the source record, then calls
* {@see collectForeignObjects()} to populate each result's relationship property.
* Multiple chained `with*()` calls are queued via a static stack so that all
* relationships are applied to the same result set.
*
* ## Implementing a new relationship type
*
* Subclasses must implement:
* - {@see collectForeignObjects()} — given the source results, fetch and assign
* the corresponding foreign objects to each source record's relationship
* property.
* - {@see getRelationForeignKeys()} — return the foreign key mapping (FK field
* names as keys, source property names as values) used by this relationship.
* - {@see updateAssociatedRecords()} — persist any changes to the associated
* foreign objects (e.g. insert/delete rows in an association table).
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @since 3.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Prado\Prado;

/**
* TActiveRecordRelationContext class
*
* TActiveRecordRelationContext holds information regarding record relationships
* such as record relation property name, query criteria and foreign object record
* class names.
Expand Down
Loading