Pages

2013年10月8日火曜日

ZendFramework2 レイアウトを利用しない場合

Layout を利用したくない場合は下記のような感じでやるようです。

<?php
// TestController.php
public function listAction()
{
    $viewModel = new ViewModel();
    $viewModel->setTerminal(true);
    $viewModel->data = 'test value';
    return $viewModel;
}
?>
<?php
// list.phtml
<?php echo $data; ?>

$this->layout()->clearOptions();
$this->layout()->clearVariables();
$this->layout()->clearChildren();
$this->layout()->>setTerminal(true);

とかも試してみましたがダメでした。

2013年9月27日金曜日

ZendFramework2 Layoutファイルにコントローラーから値をアサインする時

layout じゃなくて中身(コンテンツ?)のテンプレートファイル(.phtml)だと、アクションの最後で

return new ViewModel(array(
    'form'      => $form,
    'param1' => $param1,
));

でOKなんですが、これ layout の.phtmlファイルでもアサインされてると思ってたらされてないようです。。

という事でコントローラーからアサインする時には 中身 と レイアウト で別にアサインする必要があるようです。

具体的な方法はこんな感じです。

$this->layout()->param1 = $param1;
$this->layout()->param2 = $param2;

$this->layout()->setVariable('param1', $param1);
$this->layout()->setVariable('param2', $param2);

$this->layout()->setVariables(array(
    'param1' => $param1,
    'param2' => $param2,
));

※アクション内に記述する内容です。

2013年9月26日木曜日

ZendFramework2 toRouteの使い方

/mod/con/act というURLにリダイレクトしたいと思った時の toRoute の1つ目のパラメータ $route の指定方法がちょっと不明だったので、メモ。

最初こんな風に書いてみた。。

return $this->redirect()->toRoute('/mod/con/act');
return $this->redirect()->toRoute('mod/con/act');

ん~ どちらもダメ。。

正解は

return $this->redirect()->toRoute('mod\con', array('action'=>'act'));

'mod\con' これは module.config.php で下記のように定義している。

'mod\con' => array(
    'type'    => 'segment',
    'options' => array(
        'route'    => '/mod/con[/:action]',
        'constraints' => array(
            'action' => '[a-zA-Z][a-zA-Z0-9]*',
        ),
        'defaults' => array(
            'controller' => 'Mod\Controller\Con',
        ),
    ),
),

ZendFramework2 DateTimeSelectを使ってみた3

ん~ なんか色々ハマったけど、何とか動くものができた。

まず標準の DateTimeSelect のままではエラーが出るので、 オリジナルのDateTimeSelectを追加。
と言ってもDateTimeSelectを継承して

  • getHoursOptions
  • getMinutesOptions
  • getSecondsOptions
をオーバーライドしたものです。

\module\Application\config\module.config.php

に

\module\Application\config\module.config.php

'view_helpers' => array(
    'invokables' => array(
        'formDateTimeSelect2' => 'Application\View\Helper\FormDateTimeSelect2',
    ),
),
を追加する。 次に Application\View\Helper\FormDateTimeSelect2.php を追加する。 中身はこんな感じ。

\module\Application\src\Application\View\Helper\FormDateTimeSelect2.php

namespace Application\View\Helper;

use DateTime;
use IntlDateFormatter;
use Zend\Form\View\Helper\FormDateTimeSelect;

class FormDateTimeSelect2 extends FormDateTimeSelect
{
    protected function getHoursOptions($pattern)
    {
        $keyFormatter   = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'HH');
        $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern);
        $date           = new DateTime('1970-01-01 00:00:00');

        $result = array();
        for ($hour = 1; $hour <= 24; $hour++) {
            $key   = $keyFormatter->format($date->getTimestamp());
            $value = $valueFormatter->format($date->getTimestamp());
            $result[$key] = $value;

            $date->modify('+1 hour');
        }
        return $result;
    }
    protected function getMinutesOptions($pattern)
    {
        $keyFormatter   = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'mm');
        $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern);
        $date           = new DateTime('1970-01-01 00:00:00');

        $result = array();
        for ($min = 1; $min <= 60; $min++) {
            $key   = $keyFormatter->format($date->getTimestamp());
            $value = $valueFormatter->format($date->getTimestamp());
            $result[$key] = $value;

            $date->modify('+1 minute');
        }

        return $result;
    }
    protected function getSecondsOptions($pattern)
    {
        $keyFormatter   = new IntlDateFormatter($this->getLocale(), null, null, null, null, 'ss');
        $valueFormatter = new IntlDateFormatter($this->getLocale(), null, null, null, null, $pattern);
        $date           = new DateTime('1970-01-01 00:00:00');

        $result = array();
        for ($sec = 1; $sec <= 60; $sec++) {
            $key   = $keyFormatter->format($date->getTimestamp());
            $value = $valueFormatter->format($date->getTimestamp());
            $result[$key] = $value;

            $date->modify('+1 second');
        }

        return $result;
    }
}
phtmlファイルでは下記のように記述

formDateTimeSelect2($form->get('date_from'), IntlDateFormatter::SHORT, IntlDateFormatter::LONG, 'ja'); ?>
これで動くはずです。

余談ですが、サンプルのAlbumモジュールのように実装してもvalidatorのところが上手く動作しません。
\Zend\Form\Element\DateTimeSelect.php::getInputSpecification
を見ると解るんですが、下記のようにフィルターでコールバックを追加してStringに変換しなければなりません。
そして、ValidatorでDateでチェックするようです。


protected function getValidator()
{
    if (null === $this->validator) {
        $this->validator = new DateValidator(array('format' => 'Y-m-d H:i:s'));
    }

    return $this->validator;
}

public function getInputSpecification()
{
    return array(
        'name' => $this->getName(),
        'required' => false,
        'filters' => array(
            array(
                'name'    => 'Callback',
                'options' => array(
                    'callback' => function($date) {
                        // Convert the date to a specific format
                        if (is_array($date)) {
                            if (!isset($date['second'])) {
                                $date['second'] = '00';
                            }
                            $date = sprintf('%s-%s-%s %s:%s:%s',
                                $date['year'], $date['month'], $date['day'],
                                $date['hour'], $date['minute'], $date['second']
                            );
                        }

                        return $date;
                    }
                )
            )
        ),
        'validators' => array(
            $this->getValidator(),
        )
    );
}
これをデフォルトとしてFormオブジェクト作成時にセットしたいんですが、ちょっとやり方が解りませんでした。。

そこで、アクション内で

\module\Album\src\Album\Controller\IndexController.php

if ($request->isPost()) {
    $album= new Album();
    $form->setInputFilter($album->getInputFilter($form->getInputFilter()));
    $form->setData($request->getPost());
...

\module\Album\src\Album\Model\Album.php

public function getInputFilter(InputFilterInterface $defaultInputFilter = NULL)
{
    if (!$this->inputFilter) {
        if (is_null($defaultInputFilter)) {
            $inputFilter = new InputFilter();
        } else {
            $inputFilter = $defaultInputFilter;
        }
    }
    $factory     = new InputFactory();
という感じにしました。

ZendFramework2 DateTimeSelectを使ってみた2

DateTimeSelect が使えない問題が解決しました。

問題はレンダリング時にありました。

ファイルは
\Zend\Form\View\Helper\FormDateTimeSelect.php

こいつの最後の方にある
  • getHoursOptions
  • getMinutesOptions
  • getSecondsOptions
これです。

$date           = new DateTime('1970-01-01 00:00:00');
↓
$key   = $keyFormatter->format($date);

途中略してますが、こんな感じで IntlDateFormatter::format のパラメータに DateTime オブジェクトを指定しているんです。

この format メソッドに DateTime オブジェクトを指定できるのは
の変更履歴を見ると解るんですが、5.3.4から対応している。

そして、利用しているサーバーの intl のバージョンを確認。

# yum list install php-intl

すると結果は

php-intl.x86_64  5.3.3-23.el6_4  @updates

ってな感じで5.3.3でした。。
なので、エラーが出て時、分、秒が出てない状況だっというわけです。。

RHEL7 では5.4か5.5が標準パッケージで入りそうなので、それを利用できれば解決しそうですが、実際に利用されるまでにはあと1年以上はかかる気がするので、 intl 5.3.3 で動く方法を探すしかないですね。。

Followers