【Laminas】リポジトリクラスのリファクタリングとfindPostメソッドを実装する!

Uncategorized

どーも!marusukeです!

前回の記事の続きで(【Laminas】リポジトリクラスのfindAllPostsメソッドを実装する!)、LaminasDbSqlRepositoryクラスのリファクタリングとfindPostメソッドの実装をしていきます!

LaminasDbSqlRepositoryクラスのリファクタリングをする!

今の時点で、LaminasDbSqlRepositoryのリファクタリングをします。(コードの変更量が少ないうちに。)

リファクタリングとは、簡単に説明すると、今あるコードをエンジニアが読みやすく書き換えるということです。(処理内容は変わりません。)

今回のリファクタリングは、クラスの依存性が高い部分(直接インスタンス化させている部分)をコンストラクタのプロパティに変更し、クラスの依存性を低くします。

簡単にいうと、インスタンスの引数で、new クラス名()となっている部分です。

クラスの依存性が高い部分は以下の 部分です。

public function findAllPosts()
{
    $sql       = new Sql($this->db);
    $select    = $sql->select('posts');
    $statement = $sql->prepareStatementForSqlObject($select);
    $result    = $statement->execute();

    if (! $result instanceof ResultInterface || ! $result->isQueryResult()) {
        return [];
    }

    $resultSet = new HydratingResultSet(
        new ReflectionHydrator(),
        new Post('', '')
    );
    $resultSet->initialize($result);
    return $resultSet;
}

依存度が高いとは、簡単に説明をすると、未来の仕様変更で上記のReflectionHydrator()Post(”, ”)が別のオブジェクトを使用するとなった時、この部分のコードも書き換える必要があります。(use文もです。)大規模なシステムの場合だと、この変更部分を探すことが大変です。

したがって、Factoryデザインパターンで、インスタンス化はFactoryクラスにお願いして、Factoryクラスから引数でReflectionHydrator()とやPost()をもらう形にします。(Factoryクラスは次の記事で作成します。)

(FactoryデザインパターンはGoFデザインパターンの一つで、簡単に説明すると、クラスをインスタンス化する工場のことです。)

以下が依存性を低くしたLaminasDbSqlRepository.phpです。

// In module/Blog/src/Model/LaminasDbSqlRepository.php:
namespace Blog\Model;

use InvalidArgumentException;
use RuntimeException;
// Replace the import of the Reflection hydrator with this:
use Laminas\Hydrator\HydratorInterface;
use Laminas\Db\Adapter\AdapterInterface;
use Laminas\Db\Adapter\Driver\ResultInterface;
use Laminas\Db\ResultSet\HydratingResultSet;
use Laminas\Db\Sql\Sql;

class LaminasDbSqlRepository implements PostRepositoryInterface
{
    /**
     * @var AdapterInterface
     */
    private $db;

    /**
     * @var HydratorInterface
     */
    private $hydrator;

    /**
     * @var Post
     */
    private $postPrototype;

    public function __construct(
        AdapterInterface $db,
        HydratorInterface $hydrator,
        Post $postPrototype
    ) {
        $this->db            = $db;
        $this->hydrator      = $hydrator;
        $this->postPrototype = $postPrototype;
    }

    /**
     * Return a set of all blog posts that we can iterate over.
     *
     * Each entry should be a Post instance.
     *
     * @return Post[]
     */
    public function findAllPosts()
    {
        $sql       = new Sql($this->db);
        $select    = $sql->select('posts');
        $statement = $sql->prepareStatementForSqlObject($select);
        $result    = $statement->execute();

        if (! $result instanceof ResultInterface || ! $result->isQueryResult()) {
            return [];
        }

        $resultSet = new HydratingResultSet($this->hydrator, $this->postPrototype);
        $resultSet->initialize($result);
        return $resultSet;
    }

    /**
     * Return a single blog post.
     *
     * @param  int $id Identifier of the post to return.
     * @return Post
     */
    public function findPost($id)
    {
    }
}

簡単に説明すると、コンストラクターに型付きプロパティ$hydrator$postPrototypeを追加しました。

次の記事で作成するFactoryクラスで、インスタンスを作成し、$hydrator$postPrototypeに代入します。

$postPrototypeは、Postエンティティの原型という意味です。プロトタイプについて詳しくはこちら

これでリファクタリングは完了しました!

findPostメソッドを実装する!

最後にLaminasDbSqlRepositoryクラスの2つ目のメソッドである、findPostメソッドを完成させましょう!

以下、findPostメソッドの内容です。


public function findPost($id)
{
    $sql       = new Sql($this->db);
    $select    = $sql->select('posts');
    $select->where(['id = ?' => $id]);

    $statement = $sql->prepareStatementForSqlObject($select);
    $result    = $statement->execute();

    if (! $result instanceof ResultInterface || ! $result->isQueryResult()) {
        throw new RuntimeException(sprintf(
            'Failed retrieving blog post with identifier "%s"; unknown database error.',
            $id
        ));
    }

    $resultSet = new HydratingResultSet($this->hydrator, $this->postPrototype);
    $resultSet->initialize($result);
    $post = $resultSet->current();

    if (! $post) {
        throw new InvalidArgumentException(sprintf(
            'Blog post with identifier "%s" not found.',
            $id
        ));
    }

    return $post;
}

1つ目のメソッドである、findAllPostsメソッドとの差は、 の部分です。

ほぼfindAllPostsメソッドの内容を同じです。

findAllPostsメソッドと異なる部分のみ上から簡単に説明しますと、

findPostメソッドの引数として、$idを取得します。

$select->where([‘id = ?’ => $id]);で引数で取得したidを元にwhere句に代入し、その後executeしデータベースから該当するデータを取得します。

$post = $resultSet->current();のcurrent()は、取得した行データのみを取り出すメソッドです。

if (! $post) {…}は、$postに取得した行データが入っているか確認します。なければエラーを返します。

$post;は、取り出した行データを返します。

これで、findPostメソッドの実装が完了しました!お疲れ様でした!

次は、LaminasDbSqlRepositoryFactoryクラスを作成します!

コメント

タイトルとURLをコピーしました