Zend Framework 3 詰まったときメモ

スポンサーリンク

Zend Framework3で詰まった時のメモをここに残します。

随時更新していきます。

目次

  • jQuery等(.jsファイル(.cssファイル))をlayout.phtmlファイルに記述したのに動かない!
  • サイトのタブにロゴを表示するには?
  • layoutファイルに変数を入れたい
  • routingで設定した変数の値を取得するには?
  • sqlでバリデートなどをするとき(quote)
  • zendのパッケージインストール(composer require)が失敗する。
  • html文をZend-Formを使って入力したら、html部分が除かれた状態になる
  • urlに複数の変数を入れると、挙動がおかしくなる。
  • lastInsertIdがほしい!

 

jQueryやbootstrapをlayout.phtmlファイルに記述したのに動かない!

解決策:  Zend特有の書き方で記述する

説明:

layout.phtmlファイルに単に

<script src="/js/jquery.min.js"></script>

と記述すると、各アクションに対応するファイル内でjqueryが動きません。
layout.phtmlで宣言したjavascriptを、コンテンツ内で使用することを伝えるために
layout.phtmlで以下のように記述します。

<head>
<!-- 略 -->
        <?= $this->headLink()
            ->prependStylesheet($this->basePath('css/style.css'))
            ->prependStylesheet($this->basePath('css/bootstrap.min.css'))
        ?>
        <!-- Scripts -->
        <?= $this->headScript()
            ->prependFile($this->basePath('js/bootstrap.min.js'))
            ->prependFile($this->basePath('js/jquery-3.4.1.min.js'))
        ?>  
    </head>

 

サイトのタブにロゴを表示するには?

解決策: layout.phtmlファイルに記述

説明:

ブラウザの

この上部のタブについているロゴをつけたい時は、
layout.phtmlファイルに以下のように記述します。

        <?= $this->headLink(['rel' => 'shortcut icon', 'type' => 'image/vnd.microsoft.icon', 'href' => $this->basePath() . '/img/favicon.ico'])?>

 

layoutファイルに変数を入れたい

解決策: Controller内で、別の関数で設定する

layoutに変数を入れ、action返り値にその変数の値を格納しても、反映されません。
それ専用の関数を呼び出す必要があります。
といっても簡単です。

public function indexAction(){  
    $this->layout()->setVariable('label', "これがデータ");
    return new ViewModel([]);
}

layout.phtmlでは、

<?php $this->label;?>

で表示できます。もちろん配列も同様にすることができます。

 

routingで設定した変数の値を取得するには?

解決策: $this->params()->fromRoute(‘id’, -1)

routingで、
‘route’ => ‘/index/:action[/:id]’,
みたいに設定した場合の、「:id」ってどうやったら参照できる?
という話です。

解決策の通りです。キャストすることをお勧めします。

//-1は初期値、もし存在しなかったら-1を返すということ
$this->params()->fromRoute('id', -1)

 

sqlで、バリデートなどをするとき(quote)

解決策: https://docs.zendframework.com/zend-db/adapter/

ユーザーの入力によってsqlを作成するとき、
sqlインジェクションなどに注意する必要があります。
その対策の一つに、用意されている関数達によるquote処理があります。
詳しくは下記サイト中盤を読んでください。

Adapters - zend-db - Zend Framework Docs
Database abstraction layer, SQL abstraction, result set abstraction, and RowDataGateway and TableDataGateway implementations

ここではその一例を示します。
SQL abstractionを使用している場合は、別途$adapterを保存しておくか、
magic property accessによって$platformを作成できます。
(要するに静的にアクセスできるということだと思います。たぶん)

//$adapterは、dbの接続情報を入れてある$adapterです
$platform = $adapter->getPlatform();

//or magic property access version
$platform = $adapter->platform();
$quoted = $platform->quoteValue('quoteしたい値');

//これで,$quotedの値は、sqlで重要な意味を持つ文字列が別文字に変換された値となっている

 

zendでパッケージインストール(composer require)がうまくいかない

解決策: composer updateをすると治ることがある

べつのパッケージが必要になったとき、composer requireコマンドを実行しますが、
弾に失敗することがあります。依存パッケージのバージョンが古いことが原因となることがあります。

updateしましょう。composer.jsonファイルのある場所で

composer update

 

 

html文をZend-Formを使って入力したら、html部分が除かれた状態になる

解決策: ※ $form->getInputFilter()->getRawValue()する

※htmlをそのまま入力できることが、
※恐ろしいことであることが認識できない方は絶対にしないでください
※現時点で私が見つけた方法です。より安全な方法があるかもしれません。
※自己責任で使用してください。

このサイトで紹介した、ユーザーの入力は以下の順序で行われます。

  1. Formクラスにデータが格納される(ユーザーの入力)
  2. データをInputFilterでバリデートする
  3. バリデートされたデータを保存する

Zend-Formのバリデート機能は結構優秀みたいで、
バリデート時、入力されたデータにhtmlがある場合、それを除いてくれるみたいです。

ものすごくありがたい機能なのですが、ごく一部の状況においてそれが邪魔になることがあります。
その例が、
「利用者がhtmlを入力し、入力されたhtmlをそのまま文として保存、出力したい時」です。
その際は、バリデート前のデータを取得する必要があります。

以下の方法で取得可能です。ここでは、aというnameのtextareaにhtml文が入っている状況を仮定します。

//要するに、InputFilterクラスにある、getRawValue関数を呼び出しています。
$data = $form->getInputFilter()->getRawValue('a');

これにより、$dataにはhtml文が入ったことになります。

 

  • urlに複数の変数を入れると、挙動がおかしくなる。

urlに複数の変数を入れると、挙動がおかしくなる

解決策:先頭に固有の名称を入れて、一意に定まるようにする

urlには変数を入れることができますが、
複数の変数をurlに含ませるとき、以下のような書き方では
どの変数にどの値が入っているのかを特定できず、
動作がおかしくなります。

//悪い例
'options' =>[
	'route' => '/index/:action[/:id][/:page]',
	'constraints' =>[
		'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
		'id' => '[0-9]+',
		'page' => '[0-9]+',
	],
]

この状態で、page=9という意味を込めて

/index/index/9

とアクセス下としても
変数が二つ以上あるために、
routing機能はpage=9という意図を汲み取れません。

そこで、以下のように、どのような値が入るか、一意に定まるような書き方をします。

//悪い例
'options' =>[
	'route' => '/index/:action[id/:id][page/:page]',
	'constraints' =>[
		'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
		'id' => '[0-9]+',
		'page' => '[0-9]+',
	],
]

※おさらいですが
[:page]が変数なのではなく、:pageが変数です。
[page/:page]は、page/が定数で、:pageが変数であり、あってもなくてもよい(=四角括弧の意味)
という意味になります。

こうすると、page=9という意味を込めるには
/index/index/page/9

となり、[id/:id]には当てはまらないが[page/:page]には当てはまるので
一意に定まり、
page=9
と認識してくれます。
id=8,page=9なら

/index/index/id/8/page/9

と打てばよいということになります。

付け加え

この方法を使用すると、view側での
$this->url()
が使用しにくくなります。
その場合は手打ちで対応しましょう。例えば以下のようにします。

  <a href="/index/index/page/<?= $this->page ?>/id/<?= $this->id ?>">

 

lastInsertIdがほしい!

解決策:ResultSetにある、getGeneratedValue()

データベースをしてるとあるあるな
直前にinsertしたデータのidを使って、別のデータを挿入したい!
というやつです。
この方法は、sql abstractionを使用している場合の答えです。

//新規登録
$sql = $this->Sql->insert();
$sql->into('tablename');
$sql->values([
//略
]);
$stmt = $this->Sql->prepareStatementForSqlObject($sql);
$ret = $stmt->execute();
echo $ret->getGeneratedValue();

 

コメント

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