前書き
これはZendFramework3を5%理解した人が、
全く触ったことがない人にZendFramework3を3%くらい理解させる目的で書いた記事です。
バージョン
Zend Framework 3.1.3
プロジェクト作成&起動
プロジェクト作成
$ cd C:\xampp\htdocs\zendRensyu (お好きなところにプロジェクトフォルダを作って移動する。)
$ composer create-project zendframework/skeleton-application .
「Do you want a minimal install (no optional packages)? Y/n」と、聞かれるのでnを押す。
後は不要そうなら拒否しておく。よくわからないなら許可すればおk
起動
$ cd C:\xampp\htdocs\zendRensyu
$ php -S 0.0.0.0:80 -t public
http://localhostにアクセスするとWelcomeページが出る。
http://localhost/application/indexでも同じ。
apacheのhtdocsフォルダの配下にプロジェクトフォルダを作成した場合は
http://localhost/(プロジェクト名)/publicでアクセスできる。
Controller
ルーティング設定
編集するファイル
(プロジェクトフォルダ)\module\Application\config\module.config.php
下記の設定は
http://(ドメイン名)/(コンテキストパス)/hogeと、
HogeControllerを紐づけている。
return [
'router' => [
'routes' => [
・・・,
'hoge' => [
'type' => Segment::class,
'options' => [
'route' => '/hoge[/:action]',
'defaults' => [
'controller' => Controller\HogeController::class,
'action' => 'index',
],
],
],
],
],
'controllers' => [
'factories' => [
Controller\IndexController::class => InvokableFactory::class,
Controller\HogeController::class => InvokableFactory::class, // ← 付け足す。
],
],
・・・
基本
(プロジェクトフォルダ)\module\Application\src\Controller\HogeController.php
<?php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class HogeController extends AbstractActionController
{
public function indexAction()
{
$vm = new ViewModel();
return $vm;
}
}
(プロジェクトフォルダ)\module\Application\view\application\hoge\index.phtml
<div>
Hogehoge
</div>
HogeController#indexActionにリクエストが来た際に、自動的にhoge\index.phtmlを元にhtmlが生成されレスポンスされる。
HogeController#hogeActionならhoge\hoge.phtmlが紐づけられる。
レンダリングに使うviewを明示的に指定する
(プロジェクトフォルダ)\module\Application\view\application\moga\moga.phtmlを指定する場合
public function indexAction()
{
$vm = new ViewModel();
$vm->setTemplate('application\moga\moga');
return $vm;
}
Get送信からパラメータを受け取る
public function indexAction()
{
// パラメータを連想配列で受け取る
$params = $this->getRequest()->getQuery();
return new ViewModel();
}
Post送信からパラメータを受け取る
public function indexAction()
{
// パラメータを連想配列で受け取る
$params = $this->getRequest()->getPost();
return new ViewModel();
}
Viewに値を渡す
Controller
class HogeController extends AbstractActionController
{
public function indexAction()
{
// 方法1
$vm = new ViewModel(['param1' => 'ほげほげ']);
// 方法2
$vm->setVariable('param2', 'ふがふが');
// 方法3
$vm->setVariables([
'param3' => 'ぴよぴよ',
'param4' => 'もがもが'
]);
// もちろんオブジェクトも渡せる
$vm->setVariable('param5', new Nagonago('なごなご'));
return $vm;
}
}
class Nagonago {
public $nago = null;
function __construct($nago) { $this->nago = $nago; }
}
View
<div>
Hogehoge<br>
<hr>
<?= $this->param1; ?><br>
<?= $this->param2; ?><br>
<?= $this->param3; ?><br>
<?= $this->param4; ?><br>
<?= $this->param5->nago; ?><br>
</div>
レスポンスでJSONを返す
(プロジェクトフォルダ)\module\Application\config\module.config.php
return [
・・・,
'view_manager' => [
・・・,
// ↓ 追加
'strategies' => [
'ViewJsonStrategy',
],
],
];
Controller
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\View\Model\JsonModel;
class HogeController extends AbstractActionController
{
public function indexAction()
{
return new JsonModel([
'name' => 'mogamoga',
'age' => 24,
'messages' => [
'hello',
'good, morning'
],
'data' => [
'key1' => 'value1',
'key2' => 'value2'
]
]);
}
}
フォワード
基本
class HogeController extends AbstractActionController
{
public function indexAction()
{
// FugaControllerのindexActionにフォワードさせる。
return $this->forward()->dispatch(FugaController::class, ['action' => 'index']);
}
}
パラメータを渡す
投げる側
class HogeController extends AbstractActionController
{
public function indexAction()
{
return $this->forward()->dispatch(
FugaController::class,
[
'action' => 'index',
'human' => [
'name' => 'mogamoga',
'age' => 24
]
]
);
}
}
受け取る側
class FugaController extends AbstractActionController
{
// こうやって受け取る
$human = $this->params('human');
return new ViewModel();
}
リダイレクト
基本
class HogeController extends AbstractActionController
{
public function indexAction()
{
// toRouteメソッドの第一引数には、
// (プロジェクトフォルダ)\module\Application\config\module.config.phpの
// 'routes'の値に設定している連想配列のキーを指定する。
return $this->redirect()->toRoute('fuga', ['action' => 'index']);
}
}
パラメータを渡す
投げる側
class HogeController extends AbstractActionController
{
public function indexAction()
{
// Get送信扱いでリダイレクトさせる。Post送信扱いする方法は知らない。
return $this->redirect()->toRoute(
'fuga',
['action' => 'index'],
[
'query' => [
'name' => 'mogamoga',
'age' => 24
]
]
);
}
}
受け取る側
class FugaController extends AbstractActionController
{
public function indexAction()
{
// パラメータを連想配列で受け取る
$params = $this->getRequest()->getQuery();
return new ViewModel();
}
}
外部にリダイレクトさせる
class HogeController extends AbstractActionController
{
public function indexAction()
{
return $this->redirect()->toUrl('https://qiita.com/');
}
}
View
(プロジェクトフォルダ)\module\Application\src\Controller\HogeController.php
class HogeController extends AbstractActionController
{
public function indexAction()
{
return new ViewModel([
'hoge' => 'ほげほげ',
'fuga' => '<script>alert("Hello, ZF3!")</script>',
'flag' => 1,
'mogas' => [
'このフレームワークの',
'勉強しているの',
'2020年時点で',
'俺だけ説'
]
]);
}
}
(プロジェクトフォルダ)\module\Application\view\application\hoge\index.phtml
<div>
<h3>変数の表示</h3>
<?= $this->hoge; ?>
<br><hr>
<h3>URL</h3>
<!--
urlメソッドの第一引数には、
(プロジェクトフォルダ)\module\Application\config\module.config.phpの
'routes'の値に設定している連想配列のキーを指定する。
-->
<?= $this->url('hoge', ['action' => 'hello']) ?>
<br><hr>
<h3>特殊文字のエスケープ</h3>
<?= $this->escapeHtml($this->fuga); ?>
<br><hr>
<h3>if文</h3>
<?php if ($this->flag === 0): ?>
なごなご
<?php elseif ($this->flag === 1): ?>
ぴよぴよ
<?php else: ?>
もがもが
<?php endif; ?>
<br><hr>
<h3>for文</h3>
<?php foreach ($this->mogas as $moga): ?>
<?= $moga ?><br>
<?php endforeach; ?>
DBアクセス
前書き
ぶっちゃけ、分からん。
いろいろ方法があったり、設定が面倒だったり、おまじないが多かったりして
頭わるわるな自分には分からない。
とりあえず以下のサイトが参考になると思います。
Zend Framework3のチュートリアル日本語化メモ-4
Zend Framework3の始め方4
zendFramework3でdbアダプタをグローバルで持ちたい
ZF2を使っていろいろなSELECT文を生成する
Adapters - zend-db - Zend Framework Docs
SQL Abstraction - zend-db - Zend Framework Docs
オレオレDBアクセスラッパークラス
多分これが一番楽だと思います。
以下をコピペして利用してください。
<?php
namespace Application\Common;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
use Zend\Db\ResultSet\ResultSet;
class DBManager
{
private $adapter = null;
private $connection = null;
private $sql = null;
function __construct() {
// 自分の環境にあわせて変えてください
$config = [
'driver' => 'mysqli',
'host' => 'localhost',
'username' => '(ユーザー名)',
'password' => '(パスワード)',
'database' => '(データベース名)',
'charset' => 'utf8',
];
$this->adapter = new Adapter($config);
$this->connection = $this->adapter->getDriver()->getConnection();
$this->sql = new Sql($this->adapter);
}
public function beginTransaction()
{
$this->connection->beginTransaction();
}
public function commit()
{
$this->connection->commit();
}
public function rollback()
{
$this->connection->rollback();
}
public function query(
$sql,
$parametersOrQueryMode = Adapter::QUERY_MODE_EXECUTE
) {
$result = $this->adapter->query($sql, $parametersOrQueryMode);
return ($result instanceof ResultSet) ? $result->toArray() : $result;
}
public function select(callable $selectFunction)
{
$select = $this->sql->select();
$selectFunction($select);
$resultsItr = $this->sql->prepareStatementForSqlObject($select)->execute();
$results = [];
foreach ($resultsItr as $result) $results[] = $result;
return $results;
}
public function insert(callable $insertFunction)
{
$insert = $this->sql->insert();
$insertFunction($insert);
$this->sql->prepareStatementForSqlObject($insert)->execute();
}
public function update(callable $updateFunction)
{
$update = $this->sql->update();
$updateFunction($update);
$this->sql->prepareStatementForSqlObject($update)->execute();
}
public function delete(callable $deleteFunction)
{
$delete = $this->sql->delete();
$deleteFunction($delete);
$this->sql->prepareStatementForSqlObject($delete)->execute();
}
}
トランザクション
以降もそうですが、コントローラ層で使用方法を説明しているのに特に意味はないです。
実際にはデータアクセス層にでも書いて利用してください。
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Application\Common\DBManager;
class IndexController extends AbstractActionController
{
public function indexAction()
{
$db = new DBManager();
// トランザクション開始
$db->beginTransaction();
// 略(いろんな処理とかSQLとか)
// コミット
$db->commit();
// ロールバック
//$db->rollback();
return new ViewModel();
}
}
生SQL
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Application\Common\DBManager;
class IndexController extends AbstractActionController
{
public function indexAction()
{
$db = new DBManager();
$db->beginTransaction();
// delete
$db->query("delete from characters where name = ?", ['ひで']);
// insert
$db->query('insert into characters(name, kana) values (?, ?)', ['野獣先輩', 'やじゅやじゅビースト']);
$db->query('insert into characters(name, kana) values (?, ?)', ['MUR', 'みうら']);
// update
$db->query('update characters set kana = ? where name = ?', ['やじゅうせんぱい', '野獣先輩']);
// select
$characters = $db->query('select * from characters');
// もちろん第二引数があってもいいですよ
//characters = $db->query('select name, kana from characters where kana like ?', ['%や%']);
echo '<pre>';
echo var_dump($characters);
echo '</pre>';
$db->commit();
return new ViewModel();
}
}
クエリビルダー
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Application\Common\DBManager;
class IndexController extends AbstractActionController
{
public function indexAction()
{
$db = new DBManager();
$db->beginTransaction();
// delete
$db->delete(function($delete) {
$delete->from('characters')
->where
->like('kana', '%や%');
});
// insert
$db->insert(function($insert) {
$insert->into('characters')
->columns(['name', 'kana'])
->values(['KMR', 'きむら']);
});
// 一回のinsertで複数行の挿入は無理っぽい
// 参考:https://stackoverflow.com/questions/816910/how-do-i-add-more-than-one-row-with-zend-db
$db->insert(function($insert) {
$insert->into('characters')
->columns(['name', 'kana'])
->values(['TON', 'まずうち']);
});
// update
$db->update(function($update) {
$update->table('characters')
->set(['kana' => 'とおの'])
->where
->equalTo('name', 'TON');
});
// select
$characters = $db->select(function($select) {
$select->from('characters')
->where
->in('name', ['MUR', 'KMR', 'TON']);
});
echo '<pre>';
echo var_dump($characters);
echo '</pre>';
$db->commit();
return new ViewModel();
}
}
チラ裏
情報少なすぎて泣ける。