Skip to content

Commit

Permalink
Merge branch 'refs/heads/master' into refactor-populateRelation
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Jul 4, 2024
2 parents f1ff217 + e9708de commit 6fbbfa0
Show file tree
Hide file tree
Showing 70 changed files with 1,635 additions and 1,567 deletions.
51 changes: 41 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,26 +106,60 @@ final class User extends ActiveRecord

For more information, follow [Create Active Record Model](docs/create-model.md).

## Usage in controler with DI container autowiring
## Usage in controller with DI container autowiring

```php
use App\Entity\User;
use Psr\Http\Message\ResponseInterface;
use Yiisoft\ActiveRecord\ConnectionProvider;
use Yiisoft\Db\Connection\ConnectionInterface;

final class Register
{
public function register(
User $user
ConnectionInterface $db,
): ResponseInterface {
/** Connected AR by di autowired. */
ConnectionProvider::set($db);

$user = new User();
$user->setAttribute('username', 'yiiliveext');
$user->setAttribute('email', '[email protected]');
$user->save();
}
}
```

## Usage in controler with Active Record factory
## Usage with middleware

Add the middleware to the action, for example:

```php
use Yiisoft\ActiveRecord\ConnectionProviderMiddleware;
use Yiisoft\Router\Route;

Route::methods([Method::GET, Method::POST], '/user/register')
->middleware(ConnectionProviderMiddleware::class)
->action([Register::class, 'register'])
->name('user/register');
```

Or, if you use `yiisoft/config` and `yiisoft/middleware-dispatcher` packages, add the middleware to the configuration,
for example in `config/common/params.php` file:

```php
use Yiisoft\ActiveRecord\ConnectionProviderMiddleware;

return [
'middlewares' => [
ConnectionProviderMiddleware::class,
],
];
```

_For more information about how to configure middleware, follow
[Middleware Documentation](https://github.com/yiisoft/docs/blob/master/guide/en/structure/middleware.md)_

Now you can use the Active Record in the action:

```php
use App\Entity\User;
Expand All @@ -134,12 +168,9 @@ use Yiisoft\ActiveRecord\ActiveRecordFactory;

final class Register
{
public function register(
ActiveRecordFactory $arFactory
): ResponseInterface {
/** Connected AR by factory di. */
$user = $arFactory->createAR(User::class);

public function register(): ResponseInterface
{
$user = new User();
$user->setAttribute('username', 'yiiliveext');
$user->setAttribute('email', '[email protected]');
$user->save();
Expand Down
9 changes: 9 additions & 0 deletions composer-require-checker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"symbol-whitelist": [
"Psr\\Http\\Message\\ResponseInterface",
"Psr\\Http\\Message\\ServerRequestInterface",
"Psr\\Http\\Server\\MiddlewareInterface",
"Psr\\Http\\Server\\RequestHandlerInterface",
"Yiisoft\\Factory\\Factory"
]
}
16 changes: 13 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
"php": "^8.1",
"ext-json": "*",
"yiisoft/arrays": "^3.0",
"yiisoft/db": "dev-master",
"yiisoft/factory": "^1.0"
"yiisoft/db": "dev-master"
},
"require-dev": {
"maglnet/composer-require-checker": "^4.2",
Expand All @@ -46,7 +45,18 @@
"yiisoft/cache": "^3.0",
"yiisoft/db-sqlite": "dev-master",
"yiisoft/di": "^1.0",
"yiisoft/json": "^1.0"
"yiisoft/factory": "^1.2",
"yiisoft/json": "^1.0",
"yiisoft/middleware-dispatcher": "^5.2"
},
"suggest": {
"yiisoft/db-sqlite": "For SQLite database support",
"yiisoft/db-mysql": "For MySQL database support",
"yiisoft/db-pgsql": "For PostgreSQL database support",
"yiisoft/db-mssql": "For MSSQL database support",
"yiisoft/db-oracle": "For Oracle database support",
"yiisoft/factory": "For factory support",
"yiisoft/middleware-dispatcher": "For middleware support"
},
"autoload": {
"psr-4": {
Expand Down
4 changes: 4 additions & 0 deletions docs/create-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,7 @@ $user = $userQuery->where(['id' => 1])->onePopulate();
$profile = $user->getProfile();
$orders = $user->getOrders();
```

Also see [Using Dependency Injection With Active Record Model](docs/using-di.md).

Back to [README](../README.md)
96 changes: 96 additions & 0 deletions docs/using-di.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Using Dependency Injection With Active Record

Using [dependency injection](https://github.com/yiisoft/di) in the Active Record model allows to inject dependencies
into the model and use them in the model methods.

To create an Active Record model with dependency injection, you need to use
a [factory](https://github.com/yiisoft/factory) that will create an instance of the model and inject the dependencies
into it.

## Define The Active Record Model

Yii Active Record provides a `FactoryTrait` trait that allows to use the factory with the Active Record class.

```php
use Yiisoft\ActiveRecord\ActiveQueryInterface;
use Yiisoft\ActiveRecord\ActiveRecord;
use Yiisoft\ActiveRecord\Trait\FactoryTrait;

#[\AllowDynamicProperties]
final class User extends ActiveRecord
{
use FactoryTrait;

public function __construct(private MyService $myService)
{
}

public function getTableName(): string
{
return '{{%user}}';
}

public function relationQuery(string $name): ActiveQueryInterface
{
return match ($name) {
'profile' => $this->hasOne(Profile::class, ['id' => 'profile_id']),
'orders' => $this->hasMany(Order::class, ['user_id' => 'id']),
default => parent::relationQuery($name),
};
}

public function getProfile(): Profile|null
{
return $this->relation('profile');
}

/** @return Order[] */
public function getOrders(): array
{
return $this->relation('orders');
}
}
```

When you use dependency injection in the Active Record model, you need to create the Active Record instance using
the factory.

```php
/** @var \Yiisoft\Factory\Factory $factory */
$user = $factory->create(User::class);
```

To create `ActiveQuery` instance you also need to use the factory to create the Active Record model.

```php
$userQuery = new ActiveQuery($factory->create(User::class)->withFactory($factory));
```

## Factory Parameter In The Constructor

Optionally, you can define the factory parameter in the constructor of the Active Record class.

```php
use Yiisoft\ActiveRecord\ActiveQueryInterface;
use Yiisoft\ActiveRecord\ActiveRecord;
use Yiisoft\ActiveRecord\Trait\FactoryTrait;

#[\AllowDynamicProperties]
final class User extends ActiveRecord
{
use FactoryTrait;

public function __construct(Factory $factory, private MyService $myService)
{
$this->factory = $factory;
}
}
```

This will allow to create the `ActiveQuery` instance without calling `ActiveRecord::withFactory()` method.

```php
$userQuery = new ActiveQuery($factory->create(User::class));
```

Back to [Create Active Record Model](docs/create-model.md)
30 changes: 10 additions & 20 deletions src/AbstractActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ abstract class AbstractActiveRecord implements ActiveRecordInterface
/** @psalm-var string[][] */
private array $relationsDependencies = [];

public function __construct(
private ConnectionInterface $db,
private string $tableName = ''
) {
}

/**
* Returns the public and protected property values of an Active Record object.
*
Expand Down Expand Up @@ -90,7 +84,7 @@ public function delete(): int

public function deleteAll(array $condition = [], array $params = []): int
{
$command = $this->db->createCommand();
$command = $this->db()->createCommand();
$command->delete($this->getTableName(), $condition, $params);

return $command->execute();
Expand Down Expand Up @@ -329,7 +323,7 @@ public function insert(array $attributes = null): bool
*/
public function instantiateQuery(string|ActiveRecordInterface|Closure $arClass): ActiveQueryInterface
{
return new ActiveQuery($arClass, $this->db);
return new ActiveQuery($arClass);
}

/**
Expand Down Expand Up @@ -437,7 +431,7 @@ public function link(string $name, ActiveRecordInterface $arClass, array $extraC

$viaClass->insert();
} elseif (is_string($viaTable)) {
$this->db->createCommand()->insert($viaTable, $columns)->execute();
$this->db()->createCommand()->insert($viaTable, $columns)->execute();
}
} else {
$link = $relation->getLink();
Expand Down Expand Up @@ -719,7 +713,7 @@ public function update(array $attributeNames = null): int

public function updateAll(array $attributes, array|string $condition = [], array $params = []): int
{
$command = $this->db->createCommand();
$command = $this->db()->createCommand();

$command->update($this->getTableName(), $attributes, $condition, $params);

Expand Down Expand Up @@ -788,7 +782,7 @@ public function updateAllCounters(array $counters, array|string $condition = '',
$n++;
}

$command = $this->db->createCommand();
$command = $this->db()->createCommand();
$command->update($this->getTableName(), $counters, $condition, $params);

return $command->execute();
Expand Down Expand Up @@ -884,7 +878,7 @@ public function unlink(string $name, ActiveRecordInterface $arClass, bool $delet
$viaClass->updateAll($nulls, $columns);
}
} elseif (is_string($viaTable)) {
$command = $this->db->createCommand();
$command = $this->db()->createCommand();
if ($delete) {
$command->delete($viaTable, $columns)->execute();
} else {
Expand Down Expand Up @@ -997,7 +991,7 @@ public function unlinkAll(string $name, bool $delete = false): void
$viaClass->updateAll($nulls, $condition);
}
} elseif (is_string($viaTable)) {
$command = $this->db->createCommand();
$command = $this->db()->createCommand();
if ($delete) {
$command->delete($viaTable, $condition)->execute();
} else {
Expand Down Expand Up @@ -1250,15 +1244,11 @@ protected function resetDependentRelations(string $attribute): void

public function getTableName(): string
{
if ($this->tableName === '') {
$this->tableName = '{{%' . DbStringHelper::pascalCaseToId(DbStringHelper::baseName(static::class)) . '}}';
}

return $this->tableName;
return '{{%' . DbStringHelper::pascalCaseToId(DbStringHelper::baseName(static::class)) . '}}';
}

protected function db(): ConnectionInterface
public function db(): ConnectionInterface
{
return $this->db;
return ConnectionProvider::get();
}
}
Loading

0 comments on commit 6fbbfa0

Please sign in to comment.