Skip to content

Commit

Permalink
Merge pull request #8 from flightphp/join-fix
Browse files Browse the repository at this point in the history
Fixed relation protected keyword issue, setDatabaseConnection, pulling back SQL, Multiple Join issue
  • Loading branch information
n0nag0n authored Mar 12, 2024
2 parents e6df151 + ea0d8d4 commit 4ef962a
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 12 deletions.
47 changes: 45 additions & 2 deletions src/ActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ abstract class ActiveRecord extends Base implements JsonSerializable
*/
protected array $sqlExpressions = [];

/**
* @var string SQL that is built to be used by execute()
*/
protected string $built_sql = '';

/**
* Captures all the joins that are made
*
* @var Expressions|null
*/
protected ?Expressions $join = null;

/**
* Database connection
*
Expand Down Expand Up @@ -361,6 +373,20 @@ public function getDatabaseConnection()
return $this->databaseConnection;
}

/**
* set the database connection.
* @param DatabaseInterface|mysqli|PDO $databaseConnection
* @return void
*/
public function setDatabaseConnection($databaseConnection): void
{
if (($databaseConnection instanceof DatabaseInterface) === true) {
$this->databaseConnection = $databaseConnection;
} else {
$this->transformAndPersistConnection($databaseConnection);
}
}

/**
* function to find one record and assign in to current object.
* @param int|string $id If call this function using this param, will find record by using this id. If not set, just find the first record in database.
Expand Down Expand Up @@ -474,7 +500,7 @@ public function save(): ActiveRecord
}
}

return $record;
return $record;
}

/**
Expand Down Expand Up @@ -535,6 +561,12 @@ public function query(string $sql, array $param = [], ActiveRecord $obj = null,
*/
protected function &getRelation(string $name)
{

// can't set the name of a relation to a protected keyword
if (in_array($name, ['select', 'from', 'join', 'where', 'group', 'having', 'order', 'limit', 'offset'], true) === true) {
throw new Exception($name . ' is a protected keyword and cannot be used as a relation name');
}

$relation = $this->relations[$name];
if (is_array($relation) === true) {
// ActiveRecordData::BELONGS_TO etc
Expand Down Expand Up @@ -604,7 +636,18 @@ protected function buildSql(array $sql_statements = []): string
}
//this code to debug info.
//echo 'SQL: ', implode(' ', $sql_statements), "\n", "PARAMS: ", implode(', ', $this->params), "\n";
return implode(' ', $sql_statements);
$this->built_sql = implode(' ', $sql_statements);
return $this->built_sql;
}

/**
* Gets the built SQL after buildSql has been called
*
* @return string
*/
public function getBuiltSql(): string
{
return $this->built_sql;
}
/**
* make wrap when build the SQL expressions of WHERE.
Expand Down
61 changes: 51 additions & 10 deletions tests/ActiveRecordPdoIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace flight\tests;

use flight\ActiveRecord;
use flight\database\pdo\PdoAdapter;
use flight\tests\classes\Contact;
use flight\tests\classes\User;
use PDO;
Expand Down Expand Up @@ -491,22 +492,62 @@ public function testIsHydratedGoodFindAll()
$this->assertTrue($users[0]->isHydrated());
}

public function testRelationsCascadingSave()
public function testRelationsCascadingSave()
{
$user = new User(new PDO('sqlite:test.db'));
$user->name = 'demo';
$user->password = md5('demo');
$user->insert();

$user->name = 'bobby';
$user->contact->user_id = $user->id;
$user->contact->email = '[email protected]';
$user->contact->address = 'test address';
$user->save();
$user->name = 'bobby';
$user->contact->user_id = $user->id;
$user->contact->email = '[email protected]';
$user->contact->address = 'test address';
$user->save();

$this->assertEquals($user->id, $user->contact->user_id);
$this->assertFalse($user->contact->isDirty());
$this->assertGreaterThan(0, $user->contact->id);
$this->assertFalse($user->isDirty());
}

public function testSetDatabaseConnection()
{
$user = new User();
$user->setDatabaseConnection(new PDO('sqlite:test.db'));
$user->name = 'bob';
$user->password = 'pass';
$user->save();

$this->assertGreaterThan(0, $user->id);
}

public function testSetDatabaseConnectionWithAdapter()
{
$user = new User();
$user->setDatabaseConnection(new PdoAdapter(new PDO('sqlite:test.db')));
$user->name = 'bob';
$user->password = 'pass';
$user->save();

$this->assertGreaterThan(0, $user->id);
}

public function testRelationWithProtectedKeyword()
{
$user = new User(new PDO('sqlite:test.db'));
$user->name = 'demo';
$user->password = md5('demo');
$user->insert();

$contact = new class (new PDO('sqlite:test.db')) extends ActiveRecord {
protected array $relations = [
'group' => [self::HAS_ONE, User::class, 'user_id']
];
};

$this->assertEquals($user->id, $user->contact->user_id);
$this->assertFalse($user->contact->isDirty());
$this->assertGreaterThan(0, $user->contact->id);
$this->assertFalse($user->isDirty());
$this->expectException(\Exception::class);
$this->expectExceptionMessage('group is a protected keyword and cannot be used as a relation name');
$contact->group->id;
}
}
23 changes: 23 additions & 0 deletions tests/ActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,27 @@ public function testCopyFrom()
$this->assertEquals('John', $record->name);
$this->assertEquals(['name' => 'John'], $record->getData());
}

public function testIsset()
{
$record = new class (null, 'test_table') extends ActiveRecord {
};
$record->name = 'John';
$this->assertTrue(isset($record->name));
$this->assertFalse(isset($record->email));
}

public function testMultipleJoins()
{
$record = new class (null, 'test_table') extends ActiveRecord {
public function query(string $sql, array $param = [], ?ActiveRecord $obj = null, bool $single = false)
{
return $this;
}
};
$record->join('table1', 'table1.some_id = test_table.id');
$record->join('table2', 'table2.some_id = table1.id');
$result = $record->find()->getBuiltSql();
$this->assertEquals('SELECT test_table.* FROM test_table LEFT JOIN table1 ON table1.some_id = test_table.id LEFT JOIN table2 ON table2.some_id = table1.id LIMIT 1 ', $result);
}
}

0 comments on commit 4ef962a

Please sign in to comment.