キャラクター作成が(手順は楽なんですけど、参照するものが多いのと書き写す文字が長くて)だるいので簡略化したいと思っていたのでやってみます。
前準備
laravelとかhomesteadの知識の獲得
これとかわかりやすいです。
おすすめ。
いまさらですけど環境はlaravel5.5にPHP7でHomesteadです。
laravelプロジェクト作成
$ laravel new nsna
never see, never againの略字です。
いろいろ初期化
composer
$ composer update
php artisanとか使えなくてビビりました。
.env
.env.exampleを修正して適当に作成します。
デフォルトではDBはhomesteadとかになってますが、そのまま使っているプロジェクトが存在する場合、そのままmigrateすると既存のDBが持っていかれます。
(そもそも既存のDB名も変えておくべきなんですかね)
DBはdatabaseだけ適当にnsnaとかに変更しておきます。
DB作成
mysql -u homestead
でmysqlに接続し、create database nsna
とかでDBを作成しました。
なんか設定をする余地はあるらしいですがスルーしました。
github登録
githubでリポジトリを作って、表示されるurlをremoteに登録してpushします。
$ git add .
$ git commit -m "first"
$ git remote add origin https://~~~~
$ git push origin master
ローカルアクセス
Homestead.yamlをいじってアクセスできるようにしておきます。
sites:
に以下を追加します。
- map: moumienai.test
to: /home/vagrant/code/nsna/public
yamlを更新したので$ homestead up --provision
で設定を反映させます。
具体的には仮想マシンを再起動させるようです。
さらに$ sudo vi /private/etc/hosts
でhostsを修正します。
198.162.10.10 moumienai.test
こちらも修正したので反映が必要です。
バージョンごとに方法が違うらしいです。
さて、試しに見てみます。
これは……たぶんうまく行ってませんね……。
メッセージに書いてあるとおり、XMLファイルとして認識されているようです。
しらんがな。
ちょっと原因がわかりませんので、困ったときのvagrant destroy
。
直りました。
やれやれです。
前準備は以上。
あ、必要ならルールブックも買っておきましょう。
key:generateとかは別にしてもしなくても。
いや本番では必要ですが。
設計
イメージとしてはこんな感じです。
- キャラクターの自動生成ができる。
- 自動生成したキャラクターを保存できる。
- 保存したキャラクターを参照できる。
- キャラクターのデータを修正できる。
- Twitterと紐付けることでログイン的なことができる。
僕のオンセ事情がツイッター&どどんとふ&適当なボイスチャット(discord多め)環境なんで、そのあたりだけで完結できればいいかなと。
というわけでテーブル構造はユーザー情報とキャラクター情報、あとキャラ作成のための情報があれば十分そうです。
画面はこんな感じ?
- トップ画面(キャラクター一覧がずらっと)
- キャラクター作成画面(保存もできる)
- ユーザー画面(Twitterログインで表示、保存したキャラが表示される)
キャラクター作成画面はなんか適当な文字列をURLにくっつけてアクセスするような感じですね。
ユーザー画面はTwitterのidをつければアクセスできるんでしょう。(作るのは僕ですけど)
修正できるようにしつつ、作成したキャラクターとTwitterをどう紐付けるかは考えどころですね。
連携すれば修正できる、連携解除は本人しかできない、みたいな感じでしょうか。
いずれにしてもそこは後回しでもいいかも。
あとキャラクターの編集は開きっぱなしにして、セッション終了時に保存するのが普通なのでセッション時間とかそのへんも気をつけられたら気をつけたいところです。
これも後回しになりそう。
キャラクター作成に関して
ここはちょっと考えておく必要がありそうなのでもう少し掘り下げます。
アクセスするたびにキャラクター作成が自動で走るというのはややクレイジーなので、わけてやる必要がありそうです。
作成ボタンを押すとキャラクターシートのページが表示されるみたいな感じですね。
たぶん、普通にキャラクターシートにアクセスする場合と同じviewになりそうです。
渡すデータも同じですね。
urlは /characters/new
とか /characters/{id}
みたいになるのかな……。
能力値(良心、邪心、社会信用度)の計算は、view側というかjavascriptでやることになりそうです。
とすると渡す情報は、ルールで固定で決まる情報と、現在値と、自由記入の情報……って感じになりそうですね。
まあ、作るのぼk(ry
製造
現状確認
web.phpを見てルーティングを確認します。
トップにアクセスするとwelcomeを返す……としか書かれてません。
というかviewがwelcomeしか存在しない……
いままでハウツー記事を参考に作ったことしかなかったので、この状態のプロジェクトをじっくり眺めるのがわりと新鮮です。
migrationにはusersとpasswordsがあるし、controllerもauthとかLoginControllerとかがあります。
が、接続する手段は初期状態には存在しないみたいですね。
ふーん。(薄い感想)
キャラクター一覧画面
ひとまず重要そうなところから作成していきます。
たぶん、キャラクターテーブルから最新何件かを取得して一覧で表示したり、新規作成ボタンがあったりする画面です。
もしかするとトップページかもしれません。
いや、もしかしなくてもトップページですね。
ログインボタンもありそうです。
DB
$ php artisan make:migration CreateCharactersTable
最初「Characters」って名前で作成しちゃったんですけど、この名前で作成するとクラスの中身がちょっと変わるんですね。
それを下地にしつつ適当に作成します。
public function up()
{
Schema::create('characters', function (Blueprint $table) {
$table->increments('id');
$table->string('id_rand');
$table->integer('uid')->unsigned()->nullable();
$table->string('player_name')->nullable();
$table->string('actor_name')->nullable();
$table->string('organization')->nullable();
$table->string('age')->nullable();
$table->string('gender')->nullable();
$table->string('photo')->nullable();
$table->string('good')->nullable();
$table->string('evil')->nullable();
$table->string('social')->nullable();
$table->string('most_important')->unsigned()->nullable();
$table->integer('omote1_id')->unsigned()->nullable();
$table->string('omote1_free')->nullable();
$table->integer('omote2_id')->unsigned()->nullable();
$table->string('omote2_free')->nullable();
$table->integer('omote3_id')->unsigned()->nullable();
$table->string('omote3_free')->nullable();
$table->integer('ura1_id')->unsigned()->nullable();
$table->string('ura1_free')->nullable();
$table->integer('ura2_id')->unsigned()->nullable();
$table->string('ura2_free')->nullable();
$table->integer('ura3_id')->unsigned()->nullable();
$table->string('ura3_free')->nullable();
$table->integer('ura4_id')->unsigned()->nullable();
$table->string('ura4_free')->nullable();
$table->integer('ura5_id')->unsigned()->nullable();
$table->string('ura5_free')->nullable();
$table->string('kill1')->nullable();
$table->string('kill2')->nullable();
$table->string('kill3')->nullable();
$table->string('kill4')->nullable();
$table->string('kill5')->nullable();
$table->text('memo')->nullable();
$table->timestamps();
});
}
外部キーは嫌いなのでスルーします。
データ的な部分は別のテーブルから読み出すようにします。
すべてnullableにしているので適当なデータが作れるよやったね。
初期データ
……というわけにもいかないので初期データを作成できるようにしておきます。
5.6じゃないですけど。
fakerを入れます。
$ composer require fzaninotto/faker
$ php artisan make:seeder CharactersTableSeeder
Seederを設定します。
public function run()
{
$faker = Faker\Factory::create('ja_JP');
for ($i = 0; $i < 20; $i++)
{
DB::table('characters')->insert([
'id_rand' => str_random(20),
'uid' => $faker->unique()->randomNumber(),
'player_name' => $faker->unique()->userName(),
'actor_name' => $faker->unique()->userName(),
'created_at' => $faker->dateTime(),
'updated_at' => $faker->dateTime(),
]);
}
}
public function run()
{
$this->call([
CharactersTableSeeder::class,
]);
}
末尾に--seed
をつけてmigrateすればデータが発生するようです。
モデル
$ php artisan make:model Character
protected $guarded = [
'id', 'id_rand',
];
fillableとかhiddenとかよく知らなかったんですけど。
fillableがデータ入れていい項目の指定、guardedが入れさせたくない指定、hiddenが気軽に渡したくないデータの指定って感じ?
もう少し理解が必要そうですけどふんわりとスルーします。
最低限、idあたりは変わっちゃあかんやろってことでガードしておきます。
パスワードとかは入ってないのでhiddenは不要そうです。
コントローラー
$ php artisan make:controller CharacterController
use App\Character;
// 〜〜〜〜〜
protected function index()
{
$characters = Character::orderBy('id', 'desc')->paginate(10);
return view('characters', compact('characters'));
}
これを見つつpaginateとか使ってみます。
ビュー
php artisan make:auth
で作成されたビューがとてもbootstrap的なので、それを流用します。
@extends('layouts.app')
@section('content')
<div class="container">
<h1 class="d-none d-sm-block">もう誰も横浜の果てで涙という名の同窓会だけ見えない キャラクターシート保管庫</h1>
<h5 class="d-sm-none">もう誰も横浜の果てで涙という名の同窓会だけ見えない キャラクターシート保管庫</h5>
</div>
<div class="container character-list">
<div class="row justify-content-center">
<div class="col-xs-2 panel-heading">No</div>
<div class="col-xs-5 panel-heading">アクター名</div>
<div class="col-xs-5 panel-heading">プレイヤー名</div>
</div>
@foreach ($characters as $c)
<div class="row justify-content-center panel panel-default">
<div class="col-xs-2 panel-body">{{ $c->id }}</div>
<div class="col-xs-5 panel-body"><a href="{{ url('character')."/".$c->id_rand }}">{{ $c->actor_name }}</a></div>
<div class="col-xs-5 panel-body"><a href="{{ url('user')."/".$c->uid }}">{{ $c->player_name }}</a></div>
</div>
@endforeach
{{ $characters->links() }}
</div>
@endsection
.panel-heading{
background-color: lightgray;
border: solid 0.1px gray;
padding: 5px 20px 5px 20px;
}
.panel-body{
background-color: ghostwhite;
border: solid 0.1px gray;
padding: 5px 20px 5px 20px;
}
.character-list{
min-width: 600px;
margin-left: 1rem;
margin-right: 1rem;
}
.character-list > .row > .col-xs-2{
min-width: 100px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.character-list > .row > .col-xs-5{
width: 250px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.pagination{
margin-top: 1rem;
}
見よう見まねでcssも追加してレスポンシブっぽくしました。
app.blade.phpで呼び出すようにしています。
ルーティング
Route::get('/', 'CharacterController@index');
しれっとトップにしておきます。
こんな感じ。
続く
長くなりすぎました。
続きます。