諸事情で Zend Framework を理解する 2022 - ④登録機能の作成
こんにちは!
スマレジの テックファーム(SES 部門)のWebエンジニア やまて(@r_yamate) と申します。
はじめに
前回の記事(③一覧画面の作成)で、Webサービスのトップページとなる一覧画面を作成しました。
本連載の目次
本連載では以下の順序で進めています。
今回は、商品データを Products テーブルに登録する、登録機能を作成します。
目次
Zend Framework公式ドキュメントのチュートリアルを参考に作成しました。(ところどころアレンジしています)
- https://docs.zendframework.com/tutorials/getting-started/database-and-models/
- https://docs.zendframework.com/tutorials/getting-started/forms-and-actions/
本記事完了時点のソースコード
本記事完了時点のソースコードをGitHub上に公開しています。
以下は変更差分です。
商品管理ページの構成
ページ | 説明 |
---|---|
商品一覧 | 商品の一覧を表示。商品の新規登録や編集、削除のためのリンクボタン表示。 |
商品登録⭐️ | 新規商品を登録するためのフォーム。 |
商品編集 | 商品を編集するためのフォーム。 |
商品削除 | 商品を削除することを確認し、削除するページ。 |
1. パッケージ zend-form のインストール
1-1. パッケージ zend-form のインストール
フォーム画面を簡単に作成するためのパッケージ zend-form をインストールします。
docker-compose exec app composer require zendframework/zend-form
コマンド実行結果
# r_yamate @ mbp in ~/Documents/code/zend-framework-crud-sample on git:feature-create-add o [22:58:16] $ docker-compose exec app composer require zendframework/zend-form Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/ Info from https://repo.packagist.org: #StandWithUkraine Using version ^2.14 for zendframework/zend-form ./composer.json has been updated Loading composer repositories with package information Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/ Info from https://repo.packagist.org: #StandWithUkraine Updating dependencies (including require-dev) Package operations: 4 installs, 0 updates, 0 removals - Installing zendframework/zend-hydrator (3.0.2): Downloading (100%) Please select which config file you wish to inject 'Zend\Hydrator' into: [0] Do not inject [1] config/modules.config.php [2] config/development.config.php.dist Make your selection (default is 1):1 Remember this option for other packages of the same type? (Y/n)Y Installing Zend\Hydrator from package zendframework/zend-hydrator - Installing zendframework/zend-filter (2.9.2): Downloading (100%) Installing Zend\Filter from package zendframework/zend-filter - Installing zendframework/zend-inputfilter (2.10.1): Downloading (100%) Installing Zend\InputFilter from package zendframework/zend-inputfilter - Installing zendframework/zend-form (2.14.3): Downloading (100%) Installing Zend\Form from package zendframework/zend-form zendframework/zend-hydrator suggests installing zendframework/zend-serializer (^2.9, to use the SerializableStrategy) zendframework/zend-filter suggests installing psr/http-factory-implementation (psr/http-factory-implementation, for creating file upload instances when consuming PSR-7 in file upload filters) zendframework/zend-filter suggests installing zendframework/zend-crypt (Zend\Crypt component, for encryption filters) zendframework/zend-filter suggests installing zendframework/zend-i18n (Zend\I18n component for filters depending on i18n functionality) zendframework/zend-inputfilter suggests installing psr/http-message-implementation (PSR-7 is required if you wish to validate PSR-7 UploadedFileInterface payloads) zendframework/zend-form suggests installing zendframework/zend-captcha (^2.7.1, required for using CAPTCHA form elements) zendframework/zend-form suggests installing zendframework/zend-code (^2.6 || ^3.0, required to use zend-form annotations support) zendframework/zend-form suggests installing zendframework/zend-i18n (^2.6, required when using zend-form view helpers) zendframework/zend-form suggests installing zendframework/zendservice-recaptcha (in order to use the ReCaptcha form element) Package container-interop/container-interop is abandoned, you should avoid using it. Use psr/container instead. Package zendframework/zend-component-installer is abandoned, you should avoid using it. Use laminas/laminas-component-installer instead. Package zendframework/zend-config is abandoned, you should avoid using it. Use laminas/laminas-config instead. Package zendframework/zend-db is abandoned, you should avoid using it. Use laminas/laminas-db instead. Package zendframework/zend-escaper is abandoned, you should avoid using it. Use laminas/laminas-escaper instead. Package zendframework/zend-eventmanager is abandoned, you should avoid using it. Use laminas/laminas-eventmanager instead. Package zendframework/zend-http is abandoned, you should avoid using it. Use laminas/laminas-http instead. Package zendframework/zend-json is abandoned, you should avoid using it. Use laminas/laminas-json instead. Package zendframework/zend-loader is abandoned, you should avoid using it. Use laminas/laminas-loader instead. Package zendframework/zend-modulemanager is abandoned, you should avoid using it. Use laminas/laminas-modulemanager instead. Package zendframework/zend-mvc is abandoned, you should avoid using it. Use laminas/laminas-mvc instead. Package zendframework/zend-router is abandoned, you should avoid using it. Use laminas/laminas-router instead. Package zendframework/zend-servicemanager is abandoned, you should avoid using it. Use laminas/laminas-servicemanager instead. Package zendframework/zend-stdlib is abandoned, you should avoid using it. Use laminas/laminas-stdlib instead. Package zendframework/zend-uri is abandoned, you should avoid using it. Use laminas/laminas-uri instead. Package zendframework/zend-validator is abandoned, you should avoid using it. Use laminas/laminas-validator instead. Package zendframework/zend-view is abandoned, you should avoid using it. Use laminas/laminas-view instead. Package zfcampus/zf-development-mode is abandoned, you should avoid using it. Use laminas/laminas-development-mode instead. Package zendframework/zend-hydrator is abandoned, you should avoid using it. Use laminas/laminas-hydrator instead. Package zendframework/zend-filter is abandoned, you should avoid using it. Use laminas/laminas-filter instead. Package zendframework/zend-inputfilter is abandoned, you should avoid using it. Use laminas/laminas-inputfilter instead. Package zendframework/zend-form is abandoned, you should avoid using it. Use laminas/laminas-form instead. Writing lock file Generating autoload files
途中、
Please select which config file you wish to inject 'Zend\Hydrator' into: (どの設定ファイルに 'Zend\Hydrator' を注入したいかを選択してください。)
という質問をされて、 [1] config/modules.config.php
を選択すると、'Zend\Hydrator' 使用についての設定を追記してくれます。
Remember this option for other packages of the same type? (Y/n) (このオプションを他の同じタイプのパッケージにも適用しますか? (Y/n))
とも聞かれるので、Y
にします。
1-2. アプリケーションへの zend-form 追加
アプリケーションにパッケージを追加するために設定します。(上の質問で [1] config/modules.config.php
選択していたら確認のみです)
確認 or 編集:config/modules.config.php
<?php // 略 return [ + 'Zend\Form', + 'Zend\InputFilter', + 'Zend\Filter', + 'Zend\Hydrator', 'Zend\Db', 'Zend\Router', 'Zend\Validator', 'Application', 'Product', ];
関連するパッケージ('Zend\InputFilter'
, 'Zend\Filter',
'Zend\Hydrator'
)も併せて追加されています。
2. パッケージ zend-i18n のインストール
zend-i18n は翻訳関連のパッケージです。
https://github.com/zendframework/zend-i18n
2-1. パッケージ zend-i18n のインストール
zend-i18n がないと、 zend-form 使用時にエラーが出るため、インストールします。
エラー内容の参考
An error occurred An error occurred during execution; please try again later. Additional information: Error File: /var/www/zf-sample/vendor/zendframework/zend-form/src/View/Helper/AbstractHelper.php:21 Message: Class 'Zend\I18n\View\Helper\AbstractTranslatorHelper' not found Stack trace: #0 /var/www/zf-sample/vendor/composer/ClassLoader.php(444): include() #1 /var/www/zf-sample/vendor/composer/ClassLoader.php(322): Composer\Autoload\includeFile('/var/www/zf-sam...') #2 [internal function]: Composer\Autoload\ClassLoader->loadClass('Zend\\Form\\View\\...') #3 /var/www/zf-sample/vendor/zendframework/zend-form/src/View/Helper/Form.php(19): spl_autoload_call('Zend\\Form\\View\\...') #4 /var/www/zf-sample/vendor/composer/ClassLoader.php(444): include('/var/www/zf-sam...') #5 /var/www/zf-sample/vendor/composer/ClassLoader.php(322): Composer\Autoload\includeFile('/var/www/zf-sam...') #6 [internal function]: Composer\Autoload\ClassLoader->loadClass('Zend\\Form\\View\\...') #7 /var/www/zf-sample/vendor/zendframework/zend-servicemanager/src/Factory/InvokableFactory.php(30): spl_autoload_call('Zend\\Form\\View\\...') #8 /var/www/zf-sample/vendor/zendframework/zend-servicemanager/src/ServiceManager.php(764): Zend\ServiceManager\Factory\InvokableFactory->__invoke(Object(Zend\ServiceManager\ServiceManager), 'Zend\\Form\\View\\...', NULL) #9 /var/www/zf-sample/vendor/zendframework/zend-servicemanager/src/ServiceManager.php(200): Zend\ServiceManager\ServiceManager->doCreate('Zend\\Form\\View\\...') #10 /var/www/zf-sample/vendor/zendframework/zend-servicemanager/src/AbstractPluginManager.php(152): Zend\ServiceManager\ServiceManager->get('Zend\\Form\\View\\...') #11 /var/www/zf-sample/vendor/zendframework/zend-view/src/Renderer/PhpRenderer.php(376): Zend\ServiceManager\AbstractPluginManager->get('form', NULL) #12 /var/www/zf-sample/vendor/zendframework/zend-view/src/Renderer/PhpRenderer.php(394): Zend\View\Renderer\PhpRenderer->plugin('form') #13 /var/www/zf-sample/module/Product/view/product/product/add.phtml(23): Zend\View\Renderer\PhpRenderer->__call('form', Array) #14 /var/www/zf-sample/vendor/zendframework/zend-view/src/Renderer/PhpRenderer.php(506): include('/var/www/zf-sam...') #15 /var/www/zf-sample/vendor/zendframework/zend-view/src/View.php(207): Zend\View\Renderer\PhpRenderer->render(NULL) #16 /var/www/zf-sample/vendor/zendframework/zend-view/src/View.php(236): Zend\View\View->render(Object(Zend\View\Model\ViewModel)) #17 /var/www/zf-sample/vendor/zendframework/zend-view/src/View.php(200): Zend\View\View->renderChildren(Object(Zend\View\Model\ViewModel)) #18 /var/www/zf-sample/vendor/zendframework/zend-mvc/src/View/Http/DefaultRenderingStrategy.php(105): Zend\View\View->render(Object(Zend\View\Model\ViewModel)) #19 /var/www/zf-sample/vendor/zendframework/zend-eventmanager/src/EventManager.php(322): Zend\Mvc\View\Http\DefaultRenderingStrategy->render(Object(Zend\Mvc\MvcEvent)) #20 /var/www/zf-sample/vendor/zendframework/zend-eventmanager/src/EventManager.php(171): Zend\EventManager\EventManager->triggerListeners(Object(Zend\Mvc\MvcEvent)) #21 /var/www/zf-sample/vendor/zendframework/zend-mvc/src/Application.php(367): Zend\EventManager\EventManager->triggerEvent(Object(Zend\Mvc\MvcEvent)) #22 /var/www/zf-sample/vendor/zendframework/zend-mvc/src/Application.php(348): Zend\Mvc\Application->completeRequest(Object(Zend\Mvc\MvcEvent)) #23 /var/www/zf-sample/public/index.php(40): Zend\Mvc\Application->run() #24 {main} © 2005 - 2022 by Zend Technologies Ltd. All rights reserved.
パッケージ zend-i18n をインストールします。
docker-compose exec app composer require zendframework/zend-i18n
コマンド実行結果
# r_yamate @ mbp in ~/Documents/code/zend-framework-crud-sample on git:feature-create-add x [23:39:58] $ docker-compose exec app composer require zendframework/zend-i18n Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/ Info from https://repo.packagist.org: #StandWithUkraine Using version ^2.10 for zendframework/zend-i18n ./composer.json has been updated Loading composer repositories with package information Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/ Info from https://repo.packagist.org: #StandWithUkraine Updating dependencies (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing zendframework/zend-i18n (2.10.1): Downloading (100%) Please select which config file you wish to inject 'Zend\I18n' into: [0] Do not inject [1] config/modules.config.php [2] config/development.config.php.dist Make your selection (default is 1):1 Remember this option for other packages of the same type? (Y/n)Y Installing Zend\I18n from package zendframework/zend-i18n zendframework/zend-i18n suggests installing zendframework/zend-cache (Zend\Cache component) zendframework/zend-i18n suggests installing zendframework/zend-i18n-resources (Translation resources) Package container-interop/container-interop is abandoned, you should avoid using it. Use psr/container instead. Package zendframework/zend-component-installer is abandoned, you should avoid using it. Use laminas/laminas-component-installer instead. Package zendframework/zend-config is abandoned, you should avoid using it. Use laminas/laminas-config instead. Package zendframework/zend-db is abandoned, you should avoid using it. Use laminas/laminas-db instead. Package zendframework/zend-escaper is abandoned, you should avoid using it. Use laminas/laminas-escaper instead. Package zendframework/zend-eventmanager is abandoned, you should avoid using it. Use laminas/laminas-eventmanager instead. Package zendframework/zend-filter is abandoned, you should avoid using it. Use laminas/laminas-filter instead. Package zendframework/zend-form is abandoned, you should avoid using it. Use laminas/laminas-form instead. Package zendframework/zend-http is abandoned, you should avoid using it. Use laminas/laminas-http instead. Package zendframework/zend-hydrator is abandoned, you should avoid using it. Use laminas/laminas-hydrator instead. Package zendframework/zend-inputfilter is abandoned, you should avoid using it. Use laminas/laminas-inputfilter instead. Package zendframework/zend-json is abandoned, you should avoid using it. Use laminas/laminas-json instead. Package zendframework/zend-loader is abandoned, you should avoid using it. Use laminas/laminas-loader instead. Package zendframework/zend-modulemanager is abandoned, you should avoid using it. Use laminas/laminas-modulemanager instead. Package zendframework/zend-mvc is abandoned, you should avoid using it. Use laminas/laminas-mvc instead. Package zendframework/zend-router is abandoned, you should avoid using it. Use laminas/laminas-router instead. Package zendframework/zend-servicemanager is abandoned, you should avoid using it. Use laminas/laminas-servicemanager instead. Package zendframework/zend-stdlib is abandoned, you should avoid using it. Use laminas/laminas-stdlib instead. Package zendframework/zend-uri is abandoned, you should avoid using it. Use laminas/laminas-uri instead. Package zendframework/zend-validator is abandoned, you should avoid using it. Use laminas/laminas-validator instead. Package zendframework/zend-view is abandoned, you should avoid using it. Use laminas/laminas-view instead. Package zfcampus/zf-development-mode is abandoned, you should avoid using it. Use laminas/laminas-development-mode instead. Package zendframework/zend-i18n is abandoned, you should avoid using it. Use laminas/laminas-i18n instead. Writing lock file Generating autoload files
同じく途中、
Please select which config file you wish to inject 'Zend\Hydrator' into: (どの設定ファイルに 'Zend\Hydrator' を注入したいかを選択してください。)
という質問をされて、 [1] config/modules.config.php
を選択すると、'Zend\Hydrator' 使用についての設定を追記してくれます。
Remember this option for other packages of the same type? (Y/n) (このオプションを他の同じタイプのパッケージにも適用しますか? (Y/n))
とも聞かれるので、Y
にします。
2-2. アプリケーションへの zend-i18n 追加
アプリケーションにパッケージを追加するために設定します。(上の質問で [1] config/modules.config.php
選択していたら確認のみです)
確認 or 編集:config/modules.config.php
<?php // 略 return [ + 'Zend\I18n', 'Zend\Form', 'Zend\InputFilter', 'Zend\Filter', 'Zend\Hydrator', 'Zend\Db', 'Zend\Router', 'Zend\Validator', 'Application', 'Product', ];
3. 登録機能の作成
3-1. パッケージ zend-form を利用して、フォーム機能の追加
作成・編集:module/Product/src/Form/ProductForm.php
<?php namespace Product\Form; use Zend\Form\Form; /** * 商品フォームクラス。 * 商品の新規作成・編集に使用する。 */ class ProductForm extends Form { /** * コンストラクタ。 * * 親のコンストラクタを呼び出す際にフォームの名前を設定する。コンストラクタに指定された名前は無視する。 * フォーム要素を設定する。各項目について、表示されるラベルを含むさまざまな属性やオプションを設定する。 * - name 属性は テーブルのフィールド名に合わせている。 * * @param mixed $name 指定されているが、使用されない。 */ public function __construct($name = null) { parent::__construct('product'); $this->add([ 'name' => 'id', 'type' => 'hidden', ]); $this->add([ 'name' => 'item_name', 'type' => 'text', 'options' => [ 'label' => '商品名', ], ]); $this->add([ 'name' => 'price', 'type' => 'text', 'options' => [ 'label' => '商品単価', ], ]); $this->add([ 'name' => 'submit', 'type' => 'submit', 'attributes' => [ 'value' => 'Go', 'id' => 'submitbutton', ], ]); } }
3-2. パッケージ zend-inputfilter でバリデーションの追加
編集:module/Product/src/Model/Product.php
<?php namespace Product\Model; use DomainException; use Zend\Filter\StringTrim; use Zend\Filter\StripTags; use Zend\Filter\ToInt; use Zend\InputFilter\InputFilter; use Zend\InputFilter\InputFilterAwareInterface; use Zend\InputFilter\InputFilterInterface; use Zend\Validator\StringLength; use Zend\Validator\Between; /** * 商品モデルクラス。 * zend-db の TableGateway クラスで動作させるために、 exchangeArray() メソッドを実装する。 */ class Product implements InputFilterAwareInterface { /** @var null|int $id */ public ?int $id; /** @var null|string $itemName */ public ?string $itemName; /** @var null|int $price */ public ?int $price; /** @var null|string $image */ public ?string $image; /** @var $inputFilter */ private $inputFilter; /** * 指定した配列からデータをエンティティのプロパティにコピーする。 * (zend-db の TableGateway クラスで動作させるため) * * @param array $data * @return void */ public function exchangeArray(array $data) { $this->id = isset($data['id']) ? $data['id'] : null; $this->itemName = isset($data['item_name']) ? $data['item_name'] : null; $this->price = isset($data['price']) ? $data['price'] : null; $this->image = isset($data['image']) ? $data['image'] : null; } /** * InputFilterAwareInterfaceでは、setInputFilter()とgetInputFilter()という2つのメソッドが定義されており、 * getInputFilter()のみを実装すればよいので、setInputFilter()からは例外を投げる。 * * @param \Zend\InputFilter\InputFilterInterface $inputFilter * @return void * @throws DomainException */ public function setInputFilter(InputFilterInterface $inputFilter) { throw new DomainException(sprintf( '%s does not allow injection of an alternate input filter', __CLASS__ )); } /** * InputFilter のインスタンスを作成。フィルタリングやバリデーションを行うプロパティごとに設定。 * * @return InputFilterInterface $inputFilter */ public function getInputFilter() { if ($this->inputFilter) { return $this->inputFilter; } $inputFilter = new InputFilter(); $inputFilter->add([ 'name' => 'id', 'required' => true, // 必須項目として設定 'filters' => [ ['name' => ToInt::class], // int フィルタを追加し、整数値のみを使用 ], ]); $inputFilter->add([ 'name' => 'item_name', 'required' => true, // 必須項目として設定 // StripTagsとStringTrimという2つのフィルタを追加して、不要なHTMLや不要な空白を削除。 'filters' => [ ['name' => StripTags::class], ['name' => StringTrim::class], ], // データベースに格納できる文字数以上の文字をユーザーが入力しないように StringLength バリデーターを追加。 'validators' => [ [ 'name' => StringLength::class, 'options' => [ 'encoding' => 'UTF-8', 'min' => 1, 'max' => 85, ], ], ], ]); $inputFilter->add([ 'name' => 'price', 'required' => true, // 必須項目として設定 'filters' => [ // int フィルタを追加し、整数値のみを使用 ['name' => ToInt::class], // StripTagsとStringTrimという2つのフィルタを追加して、不要なHTMLや不要な空白を削除。 ['name' => StripTags::class], ['name' => StringTrim::class], ], 'validators' => [ [ // 指定した値が他の2つの値の間にあるかどうか 'name' => Between::class, 'options' => [ 'min' => 1, 'max' => 100000000, // 8桁までOK ], ], ], ]); $this->inputFilter = $inputFilter; return $this->inputFilter; } }
編集:module/Product/src/Controller/ProductController.php
<?php namespace Product\Controller; use Product\Form\ProductForm; use Product\Model\Product; use Product\Model\ProductTable; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; /** * 商品コントローラークラス。 */ class ProductController extends AbstractActionController { /** @var \Product\Model\ProductTable $table */ private ProductTable $table; /** * コンストラクタ。 * ProductController は ProductTable に依存する。 * * @param \Product\Model\ProductTable $table productsテーブル */ public function __construct(ProductTable $table) { $this->table = $table; } /** * 商品一覧を表示する。 * 商品一覧を表示するために、モデルから商品を取得し、ビューに渡す。 * * @return Zend\View\Model\ViewModel 商品一覧 */ public function indexAction() { // ビューに変数を設定するために、 ViewModel のインスタンスを返す。 return new ViewModel([ // コンストラクタの最初のパラメータは、表現したいデータを含む配列。自動的にビュースクリプトに渡される。 'products' => $this->table->fetchAll(), ]); } /** * 商品を新規登録する。 * フォームからデータを取得し、新しい商品の行を保存し、商品一覧にリダイレクトする。 * * @return Response|array */ public function addAction() { // ProductFormインスタンスを作成し、送信ボタンのラベルを "新規登録" に設定する。 $form = new ProductForm(); $form->get('submit')->setValue('新規登録'); $request = $this->getRequest(); // POSTでない場合、フォームデータは送信されていないのでフォームを表示する(zend-mvcでは、ビューモデルの代わりにデータの配列を返せる)。 if (!$request->isPost()) { return ['form' => $form]; } // フォームの投稿があるため、Productインスタンスを作成し、入力フィルタをフォームに渡し、リクエストインスタンスからフォームに送信されたデータを渡す。 $product = new Product(); $form->setInputFilter($product->getInputFilter()); $form->setData($request->getPost()); // バリデーション失敗の場合、フォームを再表示する(バリデーション失敗の内容を、ビューレイヤーに伝える)。 if (!$form->isValid()) { return ['form' => $form]; } // フォームからデータを取得し、新しい商品の行を保存し、Redirectコントローラプラグインを使って商品一覧にリダイレクトする。 $product->exchangeArray($form->getData()); $this->table->createProduct($product); return $this->redirect()->toRoute('product'); } }
3-3. 新しい商品データのテーブルへの登録(モデルの処理)
編集:module/Product/src/Model/ProductTable.php
<?php namespace Product\Model; use Zend\Db\TableGateway\TableGatewayInterface; /** * 商品のデータベース・テーブルに対する操作を実行するクラス。 */ class ProductTable { /** @var \Zend\Db\TableGateway\TableGatewayInterface $tableGateway */ private TableGatewayInterface $tableGateway; /** * コンストラクタ。 * 渡された TableGateway インスタンスを $tableGateway に設定する。 * TableGateway インスタンスを使用して、データベースのテーブルから行を検索、挿入、更新、削除する。 * (これにより、テスト時にモックインスタンスを含む別の実装を簡単に提供することができる) * * @param \Zend\Db\TableGateway\TableGatewayInterface $tableGateway */ public function __construct(TableGatewayInterface $tableGateway) { $this->tableGateway = $tableGateway; } /** * データベースからすべての商品のカラムをResultSetとして取得する。 * * @return Zend\Db\ResultSet\ResultSet データベースから取得したすべての商品のカラム */ public function fetchAll() { return $this->tableGateway->select(); } // 以下のメソッド追記 /** * データベースに新しい行を作成する。 * * @param Product $product 新しく作成する商品のカラム * @return void */ public function createProduct(Product $product) { $data = [ 'item_name' => $product->itemName, 'price' => $product->price, 'image' => $product->image, ]; $this->tableGateway->insert($data); } }
チュートリアルのメソッドの分け方は、「取得する」メソッド、「登録と更新する」メソッド、「削除する」メソッドでしたが、シンプルにするため登録と更新を切り分け、使いまわしが効くようにアレンジしています。次回で更新と削除を追加して、下記のメソッドをCRUD 処理においては用意します。
- 「取得する」メソッド
- 「登録する」メソッド
- 「更新する」メソッド
- 「削除する」メソッド
3-4. 新規登録用のフォーム画面(ビュースクリプト)の作成
作成・編集:module/Product/view/product/product/index.phtml
<?php // ページのタイトルと、ブラウザのタイトルバーに表示される headTitle() ビューヘルパーを使用して // <head> セクションのタイトルを設定する。 $title = '商品一覧'; $this->headTitle($title); ?> <h1><?= $this->escapeHtml($title) ?></h1> <!-- 新しい商品を追加するためのリンクを作成する。 --> <p> <!-- url() ビューヘルパーは zend-mvc と zend-view によって提供され、必要なリンクを作成するために使用される。 url() の最初のパラメータは URL の作成に使用するルート名で、 2番目のパラメータはルートのプレースホルダに代入する変数の配列。 この場合、2つのプレースホルダ変数: action と id を受け入れるように設定されたアルバムルートを使用する。 --> <a href="<?= $this->url('product', ['action' => 'add']) ?>">新規登録</a> </p> <table class="table"> <tr> <th>ID</th> <th>商品名</th> <th>商品単価</th> </tr> <!-- コントローラアクションから割り当てた$productsを繰り返し処理 --> <?php foreach ($products as $product) : ?> <tr> <!-- 各アルバムのタイトルとアーティストを表示するテーブルを作成 --> <!-- ビュースクリプトに渡す変数と内部で作成した変数を区別するために、 $this->{variable name} を使用してアクセスする --> <td><?= $this->escapeHtml($product->id) ?></td> <td><?= $this->escapeHtml($product->itemName) ?></td> <td><?= $this->escapeHtml(number_format($product->price)) ?></td> </tr> <?php endforeach; ?> </table> <!-- クロスサイトスクリプティング(XSS)対策のために、escapeHtml()ビューヘルパーを常に使用 -->
作成・編集:module/Product/view/product/product/add.phtml
<?php $title = '商品の新規登録'; $this->headTitle($title); ?> <h1><?= $this->escapeHtml($title) ?></h1> <?php // 要素にデフォルトの CSS クラスとプレースホルダーテキストを提供する。 $itemName = $form->get('item_name'); $itemName->setAttribute('class', 'form-control'); $itemName->setAttribute('placeholder', '商品名'); $price = $form->get('price'); $price->setAttribute('class', 'form-control'); $price->setAttribute('placeholder', '商品単価'); // 送信ボタン用の CSS クラスを提供する。 $submit = $form->get('submit'); $submit->setAttribute('class', 'btn btn-primary'); $form->setAttribute('action', $this->url('product', ['action' => 'add'])); $form->prepare(); echo $this->form()->openTag($form); ?> <!-- フォームグループの div で要素をラップし、その中でラベル、要素、エラーを別々にレンダリングする。 --> <div class="form-group"> <?= $this->formLabel($itemName) ?> <?= $this->formElement($itemName) ?> <span class="text-danger"><?= $this->formElementErrors()->render($itemName, ['class' => 'help-block']) ?></span> </div> <div class="form-group"> <?= $this->formLabel($price) ?> <?= $this->formElement($price) ?> <span class="text-danger"><?= $this->formElementErrors()->render($price, ['class' => 'help-block']) ?></span> </div> <?php echo $this->formSubmit($submit); echo $this->formHidden($form->get('id')); echo $this->form()->closeTag();
3-5. 最後に画面を確認
下記URLにアクセスします。
卵かけご飯を登録してみます。
登録できました!
おわりに
今回は、商品データを Products テーブルに登録する、登録機能を作成しました。
次回、 ⑤ 編集・削除機能の作成 を投稿します。
「Web系自社開発はどんな働き方で、どんな魅力や苦労があるんだろう?」
— やまて|Webエンジニア2年目 (@r_yamate) 2022年3月29日
と情報収集したい人にとっては、普段SNS上に生息してないタイプのベテランエンジニアのリアルを聞ける機会👂自社のイベントだけどこっそり出席!…
4/12 19:00〜https://t.co/er0GAfXCXy https://t.co/XKgU8289b6
来週は自社のこのイベントに参加!(視聴者として…)
研修時のメンターの方がお一人いらっしゃるけど、こういうお話は聞いたことないし気になります。