内容へ移動
Ground Sunlight
Windowsで作る - PHPプログラミングの開発環境
ユーザ用ツール
ログイン
サイト用ツール
検索
ツール
文書の表示
以前のリビジョン
バックリンク
最近の変更
メディアマネージャー
サイトマップ
ログイン
>
最近の変更
メディアマネージャー
サイトマップ
トレース:
apricot:app:user-edit
この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。
====== Apricot ユーザ登録画面 ====== --- //[[http://www.y2sunlight.com|y2sunlight]] 2020-05-11// [[apricot:top|Apricot に戻る]] 関連記事 * [[apricot:configuration|Apricot プロジェクトの作成]] * [[apricot:public|Apricot 公開フォルダ]] * [[apricot:core:top|Apricot コア]] * Apricot アプリ * [[apricot:app:top|Apricot アプリ作成の準備]] * [[apricot:app:home|Apricot ホーム画面]] * [[apricot:app:error|Apricot エラー画面]] * [[apricot:app:db-model|Apricot データベースとモデル]] * [[apricot:app:user-list|Apricot ユーザ一覧画面]] * Apricot ユーザ登録画面 * [[apricot:app:validation|Apricot バリデーション]] * [[apricot:app:transaction|Apricot トランザクション]] * [[apricot:ext:middleware|Apricot 拡張]] [[apricot:app:user-list|ユーザ一覧画面]]に引き続き、ユーザ登録画面を作ります。本章の前にユーザ一覧画面もご覧下さい。尚、ルーティング設定に関しては既にユーザ一覧画面で終わっているので、[[apricot:app:user-list#ルーティング|そちら]]を参照して下さい。 ---- ===== ユーザモデル ===== ユーザ登録用にユーザモデル( User )を変更します。 {{fa>folder-open-o}} ** /apricot/app/Model ** <code php User.php> <?php namespace App\Models; use App\Foundation\Model; use ORM; /** * ユーザモデル */ class User extends Model { /** * ユーザ新規保存 * {@inheritDoc} * @see \App\Foundation\Model::insert() */ public function insert(array $inputs):ORM { // 新規登録時、パスワードは必須 // パスワード暗号化 $inputs['password'] = password_hash($inputs['password'], PASSWORD_DEFAULT); // 新規保存 return parent::insert($inputs); } /** * ユーザデータ更新 * {@inheritDoc} * @see \App\Foundation\Model::update() */ public function update($id, array $inputs):ORM { // データ更新時、パスワードは入力した場合のみ変更 if(empty($inputs['password'])) unset($inputs['password']); // パスワード暗号化 if(array_key_exists('password', $inputs)) { $inputs['password'] = password_hash($inputs['password'], PASSWORD_DEFAULT); } // データ更新 return parent::update($id, $inputs); } } </code> * Modelクラスの insert() と update() をオーバーライドし、password を暗号化して保存します。 * update()では、パスワードは入力した場合のみ変更します。 \\ ===== ユーザコントローラ ===== ユーザ登録用にユーザコントローラ( UserController )も変更します。 {{fa>folder-open-o}} ** /apricot/app/Controllers ** <code php UserController.php> <?php namespace App\Controllers; use App\Exceptions\ApplicationException; use App\Foundation\Controller; use App\Models\User; use Core\Input; /** * ユーザコントローラ */ class UserController extends Controller { /** * User * @var \App\Models\User */ private $user; /** * ユーザコントローラの生成 */ public function __construct() { // モデル $this->user = new User(); } /** * ユーザ一覧 * @return \Core\Foundation\Response */ public function index() { // 全件検索 $users = $this->user->findAll(); return render("user.index", ["users"=>$users]); } /** * ユーザ新規登録 * @return \Core\Foundation\Response */ public function create() { // 新規作成 $user = $this->user->create(); return render("user.create", ["user"=>$user]); } /** * ユーザレコード挿入 * @return \Core\Foundation\Response */ public function insert() { $inputs = Input::all(); try { // ユーザレコード挿入 $user = $this->user->insert($inputs); } catch(\Exception $e) { throw new ApplicationException(__('messages.error.db.insert'),$e->getMessage(),0,$e); } // ユーザ一編集画面にリダイレクト return redirect(route("user/{$user->id}/edit"))->with('msg',__('messages.success.db.insert')); } /** * ユーザ編集 * @return \Core\Foundation\Response */ public function edit(int $id) { // 主キー検索 $user = $this->user->findOne($id); if ($user!==false) { return render("user.edit", ["user"=>$user]); } else { return redirect(route("users"))->withOldErrors(); } } /** * ユーザレコード更新 * @param int $id * @return \Core\Foundation\Response */ public function update(int $id) { $inputs = Input::all(); try { // レコード更新 $this->user->update($id, $inputs); } catch(ApplicationException $e) { throw $e; } catch(\Exception $e) { throw new ApplicationException(__('messages.error.db.update'),$e->getMessage(),0,$e); } // ユーザ一編集画面にリダイレクト return redirect(route("user/{$id}/edit"))->with('msg',__('messages.success.db.update')); } /** * ユーザレコード削除 * @param int $id * @return \Core\Foundation\Response */ public function delete(int $id) { try { // レコード削除 $this->user->delete($id); } catch(ApplicationException $e) { throw $e; } catch(\Exception $e) { throw new ApplicationException(__('messages.error.db.delete'),$e->getMessage(),0,$e); } // ユーザ一覧画面にリダイレクト return redirect(route("users"))->with('msg',__('messages.success.db.delete')); } } </code> * **create()** : ユーザ新規登録 * Userモデルのcreate()で新しいユーザを作成します * ヘルパー関数render()を呼び出してレスポンスをレンダリングしています * **render(string $view=null, array $variables=[])** - $view : テンプレート名\\ 上例では assets/views/user/create.blade.php がテンプレートファイルになります - $variables : テンプレート変数の連想配列\\ 上例では新しいユーザ( $user )をテンプレートに渡しています * **insert()** : レコード挿入 * Input::all()でフォームデータを取得します * Userモデルのinsert()でユーザレコードを挿入します * エラーの場合、ApplicationException をスローします * 処理成功の場合、ヘルパー関数redirect()でユーザ編集(''user/{id}/edit'')にリダイレクトします * **edit(int $id)** : ユーザ編集 * UserモデルのfindOne($id)でユーザを検索します。 * 検索エラーの場合、ヘルパー関数redirect()でユーザ一覧(''users'')にリダイレクトします * 検索成功の場合、ヘルパー関数render()を呼び出してレスポンスをレンダリングしています * **render(string $view=null, array $variables=[])** - $view : テンプレート名\\ 上例では assets/views/user/edit.blade.php がテンプレートファイルになります - $variables : テンプレート変数の連想配列\\ 上例では検索したユーザ( $user )をテンプレートに渡しています * **update(int $id)** : レコード更新 * Input::all()でフォームデータを取得します * Userモデルのupdate()でユーザレコードを更新します * エラーの場合、ApplicationException をスローします * 処理成功の場合、ヘルパー関数redirect()でユーザ編集(''user/{id}/edit'')にリダイレクトします * **delete(int $id)** : レコード削除 * Userモデルのdelete()でユーザレコードを削除します * エラーの場合、ApplicationException をスローします * 処理成功の場合、ヘルパー関数redirect()でユーザ一覧(''users'')にリダイレクトします > 入力値のチェックは後述の[[apricot:app:validation|バリデーション]]で、エラー処理については[[apricot:app:transaction|トランザクション]]で処理を実装します。この段階ではエラーが発生するとApplicationException がスローされ[[apricot:app:error|エラー画面]]が表示されます(デバッグ時はWhoops提供のPrettyErrorHandlerのデバッグ画面が表示されます)。 \\ ===== HTMLテンプレート ===== ユーザ登録用のHTMLテンプレートは2つあります: * 新規登録用 --- create.blade.php * 編集用 --- edit.blade.php Apricotでは出来るだけシンプルな実装を示すようにクライアント側のバリデーションは行っていません。必要に応じて追加してご使用下さい。尚、入力値のチェックは後述のサーバー側の[[apricot:app:validation|バリデーション]]で行います。 また、以下のテンプレートでは、パスワードの確認入力がありません。これについても後述のバリデーションの章で追加する予定です。パスワードは新規登録時は必須入力ですが、更新時はパスワードを入力した場合のみ変更する仕様になっています。 ==== 新規登録用のテンプレート ==== 以下にユーザコントローラの create アクションでレンダリングしているHTMLテンプレートを示します。 {{fa>folder-open-o}} ** /apricot/assets/views/user ** <code php create.blade.php> {{-- 親レイアウト --}} @extends('layout') {{-- 追加スクリプト --}} @push('scripts') @endpush {{-- タイトル --}} @section('title', __('messages.user.create.title')) {{-- コンテンツ --}} @section('content') <form method="POST" name="fm"> {{-- account --}} <div class="form-group row"> <label for="account" class="col-md-2 col-form-label">{{__('messages.user.create.account')}}</label> <div class="col-md-10"> <input type="text" name="account" id="account" class="form-control" value="{{old('account',$user->account)}}" placeholder="{{__('messages.user.create.hint_account')}}"> </div> </div> {{-- password --}} <div class="form-group row"> <label for="password" class="col-md-2 col-form-label">{{__('messages.user.create.password')}}</label> <div class="col-md-10"> <input type="text" name="password" id="password" class="form-control" value="{{old('password')}}" placeholder="{{__('messages.user.create.hint_password')}}"> </div> </div> {{-- email --}} <div class="form-group row"> <label for="email" class="col-md-2 col-form-label">{{__('messages.user.create.email')}}</label> <div class="col-md-10"> <input type="text" name="email" id="email" class="form-control" value="{{old('email',$user->email)}}" placeholder="{{__('messages.user.create.hint_email')}}"> </div> </div> {{-- note --}} <div class="form-group row"> <label for="note" class="col-md-2 col-form-label">{{__('messages.user.create.note')}}</label> <div class="col-md-10"> <input type="text" name="note" id="note" class="form-control" value="{{old('note',$user->note)}}" placeholder="{{__('messages.user.create.hint_note')}}"> </div> </div> {{-- button --}} <div class="mt-4"> <button type="button" id="btn_back" class="btn btn-secondary" onclick="location.href='{{route('users')}}'">{{__('messages.user.create.btn_back')}}</button> <button type="button" id="btn_cancel" class="btn btn-secondary" onclick="location.href='{{$_SERVER['REQUEST_URI']}}'">{{__('messages.user.create.btn_cancel')}}</button> <button type="post" id="btn_insert" class="btn btn-secondary" formaction="{{route("user/insert")}}">{{__('messages.user.create.btn_insert')}}</button> </div> </form> @endsection </code> * ''extends'', ''push'', ''section'' の各ディレクティブについては、[[apricot:app:top#htmlテンプレート|スタブ画面]] を参照して下さい。 * ボイラープレート''<nowiki>__</nowiki>()'', '' route()'' については、[[apricot:app:top#layoutbladephp|layout.blade.php]] を参照して下さい。 * **ユーザ新規登録** * テンプレート変数 ''$user'' を使いユーザデータを表示しています。 * ボイラープレート''old()''は 前回の入力値を取得する[[apricot:core:response-class#ヘルバー関数]]です。前回値が存在しない場合は、テンプレート変数 ''$user'' の値を表示します(前回値が存在するのはバリデーションなどのエラーが発生した場合だけです)。 * [保存]ボタン押下で、フォームデータを ''route("user/insert")'' に送信します。 HTMLテンプレートに関しては本編[[http://www.y2sunlight.com/ground/doku.php?id=basic-library:bladeone:3.37|BladeOne]]のリンクを項を参照して下さい。 \\ ==== 編集用のテンプレート ==== 以下にユーザコントローラの edit アクションでレンダリングしているHTMLテンプレートを示します。 {{fa>folder-open-o}} ** /apricot/assets/views/user ** <code php edit.blade.php> {{-- 親レイアウト --}} @extends('layout') {{-- 追加スクリプト --}} @push('scripts') @endpush {{-- タイトル --}} @section('title', __('messages.user.edit.title')) {{-- コンテンツ --}} @section('content') <form method="POST" name="fm"> {{-- id --}} <input type="hidden" name="id" id="id" value="{{old('id',$user->id)}}"> {{-- account --}} <div class="form-group row"> <label for="account" class="col-md-2 col-form-label">{{__('messages.user.edit.account')}}</label> <div class="col-md-10"> <input type="text" name="account" id="account" class="form-control" value="{{old('account',$user->account)}}" readonly> </div> </div> {{-- password --}} <div class="form-group row"> <label for="password" class="col-md-2 col-form-label">{{__('messages.user.edit.password')}}</label> <div class="col-md-10"> <input type="text" name="password" id="password" class="form-control" value="{{old('password')}}" placeholder="{{__('messages.user.edit.hint_password')}}"> </div> </div> {{-- email --}} <div class="form-group row"> <label for="email" class="col-md-2 col-form-label">{{__('messages.user.edit.email')}}</label> <div class="col-md-10"> <input type="text" name="email" id="email" class="form-control" value="{{old('email',$user->email)}}" placeholder="{{__('messages.user.edit.hint_email')}}"> </div> </div> {{-- note --}} <div class="form-group row"> <label for="note" class="col-md-2 col-form-label">{{__('messages.user.edit.note')}}</label> <div class="col-md-10"> <input type="text" name="note" id="note" class="form-control" value="{{old('note',$user->note)}}" placeholder="{{__('messages.user.edit.hint_note')}}"> </div> </div> {{-- version_no --}} <input type="hidden" name="version_no" id="version_no" value="{{old('version_no',$user->version_no)}}"> {{-- button --}} <div class="mt-4"> <button type="button" id="btn_back" class="btn btn-secondary" onclick="location.href='{{route('users')}}'">{{__('messages.user.edit.btn_back')}}</button> <button type="post" id="btn_delete" class="btn btn-secondary" onclick="return confirm('{{__('messages.user.edit.msg_delete')}}');" formaction="{{route("user/{$user->id}/delete")}}">{{__('messages.user.edit.btn_delete')}}</button> <button type="button" id="btn_cancel" class="btn btn-secondary" onclick="location.href='{{$_SERVER['REQUEST_URI']}}'">{{__('messages.user.edit.btn_cancel')}}</button> <button type="post" id="btn_update" class="btn btn-secondary" formaction="{{route("user/{$user->id}/update")}}">{{__('messages.user.edit.btn_update')}}</button> </div> </form> @endsection </code> * ''extends'', ''push'', ''section'' の各ディレクティブについては、[[apricot:app:top#htmlテンプレート|スタブ画面]] を参照して下さい。 * ボイラープレート''<nowiki>__</nowiki>()'', '' route()'' については、[[apricot:app:top#layoutbladephp|layout.blade.php]] を参照して下さい。 * **ユーザ編集** * テンプレート変数 ''$user'' を使いユーザデータを表示しています。 * ボイラープレート''old()''は 前回の入力値を取得する[[apricot:core:response-class#ヘルバー関数]]です。前回値が存在しない場合は、テンプレート変数 ''$user'' の値を表示します(前回値が存在するのはバリデーションなどのエラーが発生した場合だけです)。 * 楽観的ロックを行う為にユーザデータの ''version_no'' を hidden で持っている点に留意して下さい。 * [保存]ボタン押下で、フォームデータを ''route("user/{id}/update")'' に送信します。 * [削除]ボタン押下で、フォームデータを ''route("user/{id}/delete")'' に送信します。 HTMLテンプレートに関しては本編[[http://www.y2sunlight.com/ground/doku.php?id=basic-library:bladeone:3.37|BladeOne]]のリンクを項を参照して下さい。 \\ ===== 翻訳テキスト ===== 翻訳ファイル( messages.php )を以下のように変更します。 {{fa>folder-open-o}} ** apricot/assets/lang/ja ** <code php messages.php> <?php return [ ... 'user'=>[ 'index'=> [ ... ], 'create'=>[ 'title'=>'ユーザ新規登録', 'account'=>'アカウント', 'password'=>'パスワード', 'password_confirmation'=>'パスワード(確認)', 'email'=>'メールアドレス', 'note'=>'備考', 'hint_account'=>'半角英数字で入力して下さい', 'hint_password'=>'パスワードを入力して下さい', 'hint_password_confirmation'=>'パスワードを再入力して下さい', 'hint_email'=>'apricot@sample.com', 'hint_note'=>'必要な場合は入力して下さい', 'btn_back'=>'戻る', 'btn_cancel'=>'キャンセル', 'btn_insert'=>'保存', ], 'edit'=>[ 'title'=>'ユーザ編集', 'account'=>'アカウント', 'password'=>'パスワード', 'password_confirmation'=>'パスワード(確認)', 'email'=>'メールアドレス', 'note'=>'備考', 'created_at'=>'登録日', 'updated_at'=>'更新日', 'hint_password'=>'変更する場合は入力して下さい', 'hint_password_confirmation'=>'パスワードを再入力して下さい', 'hint_email'=>'apricot@sample.com', 'hint_note'=>'必要な場合は入力して下さい', 'btn_back'=>'戻る', 'btn_delete'=>'削除', 'btn_cancel'=>'キャンセル', 'btn_update'=>'保存', 'msg_delete'=>'削除します。よろしいですか?', ], ], ]; </code> * ユーザ新規登録用の翻訳テキストを ''user.create'' に追加します。 * ユーザ編集用の翻訳テキストを ''user.edit'' に追加します。 \\ ===== テスト実行 ===== ユーザ登録をしてみましょう。ブラウザ上で以下のURLにアクセスしてみて下さい。 <code> http://localhost/ws2019/apricot/public/ </code> [Users]メニューをクリックしユーザ一覧画面を表示します。 [{{apricot:app:app05.png?nolink}}] ■ [新規]ボタンを押して下さい。 [{{apricot:app:app06.png?nolink}}] ■ データを入力して[保存]ボタンを押します。\\ ■ 保存に成功すると以下の画面が表示されます。 [{{apricot:app:app07.png?nolink}}] ■ データを修正して[保存]ボタンを押します。\\ ■ 保存に成功すると画面が更新されます。 \\
apricot/app/user-edit.txt
· 最終更新: 2020/06/03 14:15 by
tanaka
ページ用ツール
文書の表示
以前のリビジョン
バックリンク
文書の先頭へ