おさらい
もう誰も横浜の果てで涙という名の同窓会だけ見えないRPGのキャラシ保管庫を作成しています。
やりたいことは
前回でダミーデータは表示できるようになったので、あと最低限必要なのは
- 実際の俺表データを格納する
- 俺表を取得できるようにする
- キャラクターデータを保存する
くらいですかね。
保存の方式がちょっとあやふやなんですけど。
ちゃちゃっと進めていきます。
製造
実際のデータを作る
データをよくよく見たら、「〜〜の〜〜で」が実質1つの項目になっていました。
「会社のエリートで」みたいな感じですね。
なので設定は8つではなく6つになります。
あとで修正せねば……。
idに関しては、「〜〜の〜〜で」がどちらも18種類、表の顔の「。」が12種類、裏の顔の「し・だし・。」が36種類。
ということは3桁でこんな感じで番号を振れば良さそうです。
設定 | 番号範囲 |
---|---|
表の「〜の〜で」 | 101〜118 |
表の「。」 | 201〜212 |
裏の「〜の〜で」 | 301〜318 |
裏の「し・だし・。」 | 401〜436 |
データの方は以前に作成したダイスボットから持ってきて、Seederに配列を作り。
foreachで1件ずつinsertしました。
単純。
俺表を取得できるようにする
ボタンを押すと、一旦コントローラーに入力情報をpostする。
その後、データを取得したりなんなりして更新した変数を引数として、改めてビューを開き直す。
そんな感じですかね……?
ビュー
データが無いときにだけ俺表取得ボタンを押せるようにします。
俺表関連のパラメータ(なんでもいい)のemptyを判定する@if
とかで括ればOKですね。
やることはそれだけ……と思っていたんですが、魔が差して、気がついたらほぼ1日かけてめっちゃレスポンシブ対応してました。
ちなみに配列にしたいとか言ってた部分ですが、軽く調べて『mysqlの型に配列はない』と書いてあってそりゃそうだってなりました(馬鹿)。
というわけで、処理の前段で配列を作るようにしました。
競合対策(気の迷い)
さて、このボタンを押すと現在の入力内容をpostしつつリダイレクトで戻ってくるわけですが。
保存も当然postなので競合します。
ボタンのnameで判定して、コントローラー側で分岐すればいいみたいです。
まあ、今はスルーで。
ルーティング
Route::post('/actor/{id_rand}', 'CharacterController@submit');
新規作成時点でもid_randは内部的には取得しているので、それをくっつけて渡してやります。
コントローラー
基本的に入力内容を$characterに格納して、もう一度actorビューに戻るわけですが。
たぶん保存機能も同じことをしそうです。
えっと……
protected function submit(Request $request, $id_rand = '')
{
$character = null_escape(Character::where('id_rand', $id_rand)->first(), new Character);
// $character情報を更新する
$character = array_merge($character, $request);
// 俺表取得の場合
if (Input::get('createOre'))
{
// 取得範囲は決まっているので、ここではore_idを決定するだけ
//表の「〜の〜で」|101〜118
//表の「。」|201〜212
//裏の「〜の〜で」|301〜318
//裏の「し・だし・。」|401〜436
$character->omote1_id = rand(101, 118);
$character->omote2_id = rand(201, 212);
$character->ura1_id = rand(301, 318);
$character->ura2_id = rand(401, 436);
$character->ura3_id = rand(401, 436);
$character->ura4_id = rand(401, 436);
}
// 真実に気付いてしまったので中断
嫌なことに気付きました。
気付いてしまった
一回しか押せないボタンとか意味ないですね?
最初から値が入ってる変数を渡せばいいだけでした。
(あと微妙に、入力内容を持ったまま戻ってくるのが面倒そう……)
というわけで修正していきます。
### コントローラー
public function show($id_rand = '')
{
$character = null_escape(Character::where('id_rand', $id_rand)->first(), new Character);
if (empty($character->id_rand))
{
$character->id_rand = str_random(20);
//表の「〜の〜で」|101〜118
//表の「。」|201〜212
//裏の「〜の〜で」|301〜318
//裏の「し・だし・。」|401〜436
$character->omote1_id = rand(101, 118);
$character->omote2_id = rand(201, 212);
$character->ura1_id = rand(301, 318);
$character->ura2_id = rand(401, 436);
$character->ura3_id = rand(401, 436);
$character->ura4_id = rand(401, 436);}
return view('actor')->with([
'character' => $character,
'ore' => $this->getOre($character),
]);
}
新規作成のときにid_randと一緒に俺表のidを渡してやることにします。
ちなみに、俺表のidはキャラシ画面では表示しないものの、何処かに保存しておく必要があるのでhiddenで持っておくようにしています。
キャラクターデータを保存する
俺表ができてしまったので、submitというか保存機能を修正します。
ビュー
<script type="text/javascript">
function checkPassword ()
{
try
{
// passwordを取得
var p = document.f.password.value;
// 空文字でなければハッシュ値を生成
if (p != '') document.f.password_hash.value = getHash(p);
var current_password = '{{ $character->password_hash }}';
// 現在のパスワードが空なら何が来てもtrue(パスワードは新しいものに変わる)
if (current_password == '' || current_password == document.f.password_hash.value)
{
// パスワードはPOSTさせない
document.f.password.value = '';
return true;
}
alert('パスワードが違います');
return false;
}
catch (e)
{
console.log(e);
alert('やばたん');
}
finally
{
return false;
}
}
function getHash(str)
{
var shaObj = new jsSHA("SHA-256", "TEXT");
shaObj.update(str);
var hash = shaObj.getHash("HEX");
return hash;
}
</script>
〜〜〜〜〜
<div class="row my-5">
<div class="col-12 px-3">
<div class="row mb-3">
<div class="col-3 col-md-4 mb-1 px-1">
<input type="password" class="form-control" id="password" name="password" value="">
<input type="hidden" class="form-control" name="password_hash" value="">
</div>
<div class="col-3 col-md-4 mb-1">
<input type="submit" class="btn btn-primary form-control" name="save" value="保存" onclick="return checkPassword();">
</div>
</div>
<div class="row">
<div class="col small">※パスワードは入力しないでも保存ができますが、一度入力するとそれ以降同じパスワードの入力が必要になります。</div>
</div>
</div>
</div>
申し訳程度にパスワードをつけました。
SNSログインとはなんだったのか。
パスワードはハッシュなので気軽に持ってきています。
入力された値のハッシュ値と比較します。
パスワードがなにもない場合は特に変更しないようにしています。
パスワードがない状態でパスワードが入力された場合は、素通しして以降そのパスワードが有効になります。
怖い。
パスワードがある場合は、普通にハッシュ値を比較します。
マイグレーション
$table->string('password_hash')->nullable();
パスワードの項目を追加します。
コントローラー
protected function submit(Request $request, $id_rand = '')
{
$character = null_escape(Character::where('id_rand', $id_rand)->first(), new Character);
// $character情報を更新する
if (empty($character->id_rand)) $character->id_rand = $id_rand;
$character->password_hash = $request->password_hash;
$character->player_name = $request->player_name;
$character->actor_name = $request->actor_name;
$character->organization = $request->organization;
$character->age = $request->age;
$character->gender = $request->gender;
$character->photo = $request->photo;
$character->good = $request->good;
$character->evil = $request->evil;
$character->social = $request->social;
$character->most_important = $request->most_important;
$character->omote1_id = $request->omote1_id;
$character->omote1_free = $request->omote1_free;
$character->omote2_id = $request->omote2_id;
$character->omote2_free = $request->omote2_free;
$character->ura1_id = $request->ura1_id;
$character->ura1_free = $request->ura1_free;
$character->ura2_id = $request->ura2_id;
$character->ura2_free = $request->ura2_free;
$character->ura3_id = $request->ura3_id;
$character->ura3_free = $request->ura3_free;
$character->ura4_id = $request->ura4_id;
$character->ura4_free = $request->ura4_free;
$character->kill1 = $request->kill1;
$character->kill2 = $request->kill2;
$character->kill3 = $request->kill3;
$character->kill4 = $request->kill4;
$character->kill5 = $request->kill5;
$character->memo = $request->memo;
$character->save();
return redirect('/actor/'.$character->id_rand);
}
array_mergeとか使えるかなーとか期待したんですが、arrayじゃねーよって怒られました。
地道に全項目をぶち込んでます。
とりあえず一通りできた……?
画像アップロードとかログインとか、やりたかったけど後回しにしている部分が残ってますが。
とりあえず最低限動くようになりました。
やったー。
最大文字数とかその辺の制御をほっぽってるので何かしらエラーは吐きそうですけど……。
あとはあれですね。
actor.blade.phpで上昇したbootstrapの知識をもとにしてcharacters.blade.phpを見るとありえん汚い
という点にどこまで折り合いをつけるかですね……。