Laravel開発におけるRepositoryに関しての話

今回は、私流のアーキテクチャの Repository層の話です。

Repositoryとは何ぞい?何て言われると、私は実際のブツとプログラムの間という事です… ま、実際には保存箱という入れ物そのものを指しますが、プログラムなので、ラップしていると思えばOKです。

んで?と思われるかもしれませんが、重要なポイントです。

入れ物変わっても、アクセス方法が変わらないというのは良いことです!

例えば、全データをfindAllで取れるなら、DBでもファイルでも取れるわけですね。

今回はそんなリポジトリ層(私は層と呼びます)の話です。

図で書くと…こんな感じ

○下線は実際のファイルと思ってください。yamlとcsvです。

その上の○が、今回のリポジトリです!

さて、ポイントは、それぞれのリポジトリにControllerがくっついています。そのControllerが今回のリポジトリクラスというわけです。

ん?二通並んでいますが?と思われますが、左で切り換えています。

つまりは、このシステムではファイルをYAML/CSVを切り換えて、同じように使うことが可能と言うわけです

はいはいぃ〜ポイントは、左のロリポップです。○の提供側と、)の受け側 で構成されています。プログラミング言語的に言うとインタフェイスです。

ここで日本語的に言うと、InformationYAMLRepositoryは、ファイルfiles/top/information.ymlを管理しており、RepositoryAccessibleインタフェイスを実装しています。

提供側の名前は… RepositoryAccessibleですねw
インタフェイスなので提供側と受け手側は同じですねw

実際に出来ていますが、試験を作ります


class InformationRepositoryTest extends TestCase
{
    public function test_findAll(){
        $repository = new InformationYAMLRepository_mock();
        $results = $repository->findAll();
        $this->assertEquals('Hello World',$results[0]->title);
        $this->assertEquals('hello/',$results[0]->url);

        $this->assertEquals('Say Hello World',$results[1]->title);
        $this->assertEquals('say/',$results[1]->url);

        $this->assertEquals('laravelにてファイルからhtmlを作成する話',$results[2]->title);
        $this->assertEquals('read/',$results[2]->url);
    }

}
class InformationYAMLRepository_mock extends InformationYAMLFileRepository{
    public function findAll() : array{
        $data = array();

        $information = new InformationYAMLObject();
        $information->title = 'Hello World';
        $information->url = 'hello/';
        $data[] = $information;

        $information = new InformationYAMLObject();
        $information->title = 'Say Hello World';
        $information->url = 'say/';
        $data[] = $information;

        $information = new InformationYAMLObject();
        $information->title = 'laravelにてファイルからhtmlを作成する話';
        $information->url = 'read/';
        $data[] = $information;
        return $data;
    }
}

はい、全データ取得のfindAllで内容作成して試験します….

実装!

YAMLのファイルとかCSVってのはよく使うので、抽象化しておきます

abstract class AbstractYAMLFileRepository implements RepositoryAccessible
{
    private $file;
    public function __construct($file_path)
    {
        $file = storage_path($file_path);
        $this->file = $file;
    }


    /**
     * @param $file
     * @return array
     */
    public function readYAML($file){
        return YAMLReader::read($file);
    }
    /**
     * ファイルのすべての情報を取得します
     * @return array Informationの配列
     */
    public function findAll(): array
    {
        //
        $yaml = $this->readYAML($this->file);
        $results = array();
        foreach ($yaml as $line) {
            $results[] = $this->read_line($line);
        }
        return $results;
    }

    /**
     * @param array $line
     * @return YAMLObject
     */
    abstract public function read_line(array $line) ;
}

YAMLReader::read($file);は、ただ単にファイルをデータ配列単位に分けます。

    abstract public function read_line(array $line) ;

ここは実際のデータ内容をオブジェクト型に変換しています

class InformationYAMLFileRepository extends AbstractYAMLFileRepository
{
    public function __construct($file_path = 'files/top/information.yml')
    {
        parent::__construct($file_path);
    }

    /**
     * 行データをタイトルエンティティに変換します
     * @param array $line YAML行データ
     * @return InformationYAMLObject タイトルエンティティ
     */
    public function read_line(array $line) {
        $information = new InformationYAMLObject();
        $information->title = $line['title'];
        $information->url = $line['url'];
        $information->create = $line['create'];
        $information->latest = $line['latest'];
        $information->blog = $line['blog'];
        return $information;
    }
}

こんな感じで作ります!

今回はインタフェイスの中でファイル内容をすべて抽出するfindAllだけでした。