CakePHP2 で Component と Helper の連携

何がやりたいのかっていうと、Paginator みたいなのを自作したいです。

Component が呼ばれたら Helper も自動で呼ぶ

Paginator は Controller 内で public $components = array('Paginator'); で呼び出すと、Helper も自動で使えるようになるので同じように Helper が呼び出されるようにします。

<?php
class SampleComponent extends Component {

    public $settings = array();

    public function __construct(ComponentCollection $collection, $settings = array()) {
        $settings = array_merge($this->settings, (array)$settings);

        // Controller をこの Component 内で使えるようにする
        $this->Controller = $collection->getController();

        // SampleHelper を ctp 内で利用できるようにする
        if (!in_array('Sample', $this->Controller->helpers) &&
            !array_key_exists('Sample', $this->Controller->helpers)
        ) {
            $this->Controller->helpers[] = 'Sample';
        }

        parent::__construct($collection, $settings);
    }

Paginator では、pagenate() 内で $this->Controller->helpers[] = 'Pagenate'; をしていますが、今回は関数を実行していなくても Helper を使いたかったので、コンストラクタで同様の処理をしました。

Helper で Component の設定を使えるようにする

Pagenator では外から設定を行うことができます。

<?php
$this->Paginator->settings = array(
        'paramType' => 'querystring',
        'limit' => 20,
        'order' => 'Info.created desc');

同じように設定できて、かつ、この設定を Helper 内で使えるようにします。

<?php
    public function beforeRender(Controller $controller){
        // 設定が利用できるように request に設定する
        if (!isset($this->Controller->request['__sample_setting'])) {
            $this->Controller->request['__sample_setting'] = array();
        }
        $this->Controller->request['__sample_setting'] = array_merge(
            (array)$this->Controller->request['__sample_setting'],
            $this->settings
        );
    }

いい方法が見つからなくて、Controller の request に設定しちゃってます。もっと腑に落ちるやり方がありそうなんですがどうなんでしょうかね。

Component 内のメソッドで設定をいじってもいいように beforeRender でやってます。

これで、Helper 内で $this->request->params['__sample_setting'] でアクセスできるようになります。

まとめ

  • Component の呼び出しで Helper を使えるようにする
  • Component と Helper で設定の共有

を実装してみた話でした。

Bake が何かわかってないレベルの僕が作ったやつなので、モアベターがあれば教えてほしいです。