Skip to content

Commit

Permalink
Merge branch 'refs/heads/master' into refactor-populateRelation-test
Browse files Browse the repository at this point in the history
# Conflicts:
#	tests/Driver/Pgsql/ActiveRecordTest.php
  • Loading branch information
Tigrov committed Jul 5, 2024
2 parents 28f13f6 + c8d7a5e commit 886156c
Show file tree
Hide file tree
Showing 74 changed files with 1,896 additions and 1,608 deletions.
1 change: 0 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.scrutinizer.yml export-ignore
/phpunit.xml.dist export-ignore
/docs export-ignore

Expand Down
73 changes: 38 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,17 @@ Example:
composer require yiisoft/db-sqlite
```

## Config container interface class
## Configure container with database connection

web.php:
Add the following code to the configuration files, for example:

`config/common/di/db.php`:

```php
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Sqlite\Connection;
use Yiisoft\Db\Sqlite\Driver;

/**
* config ConnectionInterface::class
*/
return [
ConnectionInterface::class => [
'class' => Connection::class,
Expand All @@ -71,7 +70,7 @@ return [
];
```

params.php
`config/common/params.php`:

```php
return [
Expand All @@ -81,6 +80,24 @@ return [
]
```

For more information about how to configure the connection, follow [Yii Database](https://github.com/yiisoft/db/blob/master/docs/guide/en/README.md).

`config/common/bootstrap.php`:

```php
use Psr\Container\ContainerInterface;
use Yiisoft\ActiveRecord\ConnectionProvider;
use Yiisoft\Db\Connection\ConnectionInterface;

return [
static function (ContainerInterface $container): void {
ConnectionProvider::set($container->get(ConnectionInterface::class));
}
];
```

See other ways to [define the DB connection](docs/define-connection.md) for Active Record.

## Defined your active record class

```php
Expand All @@ -106,45 +123,31 @@ 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

Now you can use the Active Record:

```php
use App\Entity\User;
use Psr\Http\Message\ResponseInterface;

final class Register
{
public function register(
User $user
): ResponseInterface {
/** Connected AR by di autowired. */
$user->setAttribute('username', 'yiiliveext');
$user->setAttribute('email', '[email protected]');
$user->save();
}
}
$user = new User();
$user->setAttribute('username', 'yiiliveext');
$user->setAttribute('email', '[email protected]');
$user->save();
```

## Usage in controler with Active Record factory
Usage with `ActiveQuery`:

```php
use App\Entity\User;
use Psr\Http\Message\ResponseInterface;
use Yiisoft\ActiveRecord\ActiveRecordFactory;
use Yiisoft\ActiveRecord\ActiveQuery;

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

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

$user = $userQuery->where(['id' => 1])->onePopulate();

$username = $user->getAttribute('username');
$email = $user->getAttribute('email');
```

## Documentation
Expand Down
10 changes: 10 additions & 0 deletions composer-require-checker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"symbol-whitelist": [
"Psr\\Http\\Message\\ResponseInterface",
"Psr\\Http\\Message\\ServerRequestInterface",
"Psr\\Http\\Server\\MiddlewareInterface",
"Psr\\Http\\Server\\RequestHandlerInterface",
"Yiisoft\\Arrays\\ArrayableTrait",
"Yiisoft\\Factory\\Factory"
]
}
19 changes: 15 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@
"require": {
"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 @@ -43,10 +41,23 @@
"spatie/phpunit-watcher": "^1.23",
"vimeo/psalm": "^5.20",
"yiisoft/aliases": "^2.0",
"yiisoft/arrays": "^3.1",
"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/arrays": "For \\Yiisoft\\Arrays\\ArrayableInterface support",
"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)
97 changes: 97 additions & 0 deletions docs/define-connection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Define the DB connection for Active Record

To use the Active Record, you need to define the DB connection in one of the following ways:

## Using the bootstrap configuration

Add the following code to the configuration file, for example in `config/common/bootstrap.php`:

```php
use Psr\Container\ContainerInterface;
use Yiisoft\ActiveRecord\ConnectionProvider;
use Yiisoft\Db\Connection\ConnectionInterface;

return [
static function (ContainerInterface $container): void {
ConnectionProvider::set($container->get(ConnectionInterface::class));
}
];
```

## Using 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, using with `yiisoft/middleware-dispatcher` packages, add the middleware to the configuration file,
for example in `config/common/params.php`:

```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)_

## Using DI container autowiring

You can set the DB connection for Active Record using the DI container autowiring.

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

final class Register
{
public function register(
ConnectionInterface $db,
): ResponseInterface {
ConnectionProvider::set($db);

// ...
}
}
```

## Using dependency injection

Another way to define the DB connection for Active Record is to use dependency injection.

```php
use Yiisoft\Db\Connection\ConnectionInterface;

class User extends ActiveRecord
{
public function __construct(private readonly ConnectionInterface $db)
{
}

public function db(): ConnectionInterface
{
return $this->db;
}
}
```

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

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)
Loading

0 comments on commit 886156c

Please sign in to comment.