見た映画をメモするwebアプリが欲しいので作ろうと思い、作ったときの自分用の細かいメモ。(全ソースはないです)
この間作ったhomestead環境で作ってmixhostにデプロイして動作確認だけしました。

プロジェクト作る
sudo composer create-project laravel/laravel --prefer-dist plot
権限変更
sudo chown -R vagrant:vagrant /var/www/plot
データベース作成
mysql -u homestead -p create database plot_db;
.env編集
該当箇所だけ下記に編集
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=plot_db DB_USERNAME=homestead DB_PASSWORD=secret
認証機能つける
下記によるとLaravel8は認証機能周りが7変わったらしいので、記事を参考に認証機能をインストール

cd /var/www/plot/ composer require laravel/jetstream php artisan jetstream:install livewire php artisan migrate npm install && npm run dev
簡易サーバー起動
cd /var/www/plot/ php -S 0.0.0.0:8080 -t public
表示を確認
vagrantで作った環境なのでポート指定して表示を確認。
http://192.168.33.10:8080
ウェルカムページの右上にログインと登録機能がついてるのが確認できた。
ルーティング
routes/web.php
listとviewへのルートを追加する
Route::get('/list', function () { return view('list'); }); Route::get('/edit/{id}', function ($id) { return view('edit'); });
viewの作成
viewのlist、editに対応したファイルつくる。(内容は省略、ログイン時だけ表示されるように設定した)
resources/views/edit.blade.php
resources/views/list.blade.php
publicにファイル配置
{{asset()}}はpublicフォルダ下を見に行くので、使うCSSやjsをpublicフォルダ下に配置する。
テーブル作成
複数形にしないといけないらしいので末尾にsつけた「memos」テーブルを作る
php artisan make:migration create_memos_table
マイグレーションファイル編集
memo/database/migrations/2020_10_02_021545_create_memos_table.php
up関数だけ下記に変更する。up関数に入れたものがmigrateしたときにtableのカラムになる。
public function up() { Schema::create('memos', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->date('register_date'); $table->string('note'); $table->text('memo'); $table->string('links'); $table->timestamps(); }); }
Laravel5.5ではstringを挿入する際に設定しないとエラーになるらしい、一応つけておく
Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Schema; public function boot() { // Schema::defaultStringLength(191); }
マイグレーション実行
php artisan migrate
「plot_db」データベースに「memos」テーブルができているか確認
descのtypeによると長さが191となっているので設定できているようだ。
mysql> use plot_db Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +------------------------+ | Tables_in_plot_db | +------------------------+ | failed_jobs | | memos | | migrations | | password_resets | | personal_access_tokens | | sessions | | users | +------------------------+ 7 rows in set (0.00 sec) mysql> desc memos; +---------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+--------------+------+-----+---------+----------------+ | id | int unsigned | NO | PRI | NULL | auto_increment | | title | varchar(191) | NO | | NULL | | | register_date | date | NO | | NULL | | | note | varchar(191) | NO | | NULL | | | memo | text | NO | | NULL | | | links | varchar(191) | NO | | NULL | | | created_at | timestamp | YES | | NULL | | | updated_at | timestamp | YES | | NULL | | +---------------+--------------+------+-----+---------+----------------+ 8 rows in set (0.01 sec)
モデル作成
テーブル「memos」に対して、「Memo」とする。
php artisan make:model Memo
Memo.phpができるらしいので確認
memo/app/Models/Memo.php
コントローラー作成
cd /var/www/memo
php artisan make:controller MemoController
本格的にルーティングを書く
routes/web.php
Laravel8からはnamespace「App\Http\Controllers\」を記載しないとMemoControllerを参照してくれないようだ。
「App\Http\Controllers\MemoController@save」と書くことで「MemoController」の「save」関数を参照してくれる
記載しない場合、「Target class [MemoController] does not exist.」というエラーが出る。
Route::get('/', function () { return view('welcome'); }); Route::get('/list',"App\Http\Controllers\MemoController@list")->name('list'); Route::get('/add', "App\Http\Controllers\MemoController@add")->name('add'); Route::get('/edit/{id}', "App\Http\Controllers\MemoController@edit")->name('edit'); Route::post('/api/single', "App\Http\Controllers\MemoController@single")->name('single'); Route::post('/api/save', "App\Http\Controllers\MemoController@save")->name('save'); Route::post('/api/delete', "App\Http\Controllers\MemoController@delete")->name('delete'); Route::post('/api/multi', "App\Http\Controllers\MemoController@multi")->name('multi'); Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () { return view('dashboard')->withHeaders([ 'Cache-Control' => 'no-store', ]);; })->name('dashboard');
Controllerを書く
各CLUD処理を書いていく。
(バリデート、エスケープはあまり調べず作ったのでそのまま使用しないほうがいい)
plot/app/Http/Controllers/MemoController.php
<?php namespace App\Http\Controllers; use App\Models\Memo; use Illuminate\Database\Eloquent\Relations\HasOneThrough; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; class MemoController extends Controller { /** * 一覧ページの表示 * @param Request $request * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function list(Request $request){ return view('list')->withHeaders([ 'Cache-Control' => 'no-store', ]); } /** * 削除ページの表示 * @param Request $request * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Request $request) { return view('edit',["id"=>$request->id])->withHeaders([ 'Cache-Control' => 'no-store', ]); } /** * 新規作成ページの表示 * @param Request $request * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function add(Request $request) { return view('edit',["id"=> -1]); } /** * 保存時API * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function save(Request $request){ if(empty($request->title) || empty($request->register_date) || empty($request->note) || empty($request->memo) || empty($request->links) ){ return response()->json(['status'=> "E001",'message'=> "未入力の項目があります"]); } $rules = [ 'title' => ['required', 'string','max:191'], 'register_date' => ['required'], 'note' => ['required', 'string','max:191'], 'memo' => ['required', 'string'], 'links' => ['required', 'string'], ]; $this->validate($request, $rules); if(empty($request->id) || $request->id == "-1"){ // 追加時 $memo = new Memo; $memo->title = $request->title; $memo->register_date = $request->register_date; $memo->note = $request->note; $memo->memo = $request->memo; $memo->links = $request->links; $memo->save(); return response()->json($memo); }else{ // 更新時 $memo = Memo::find($request->id); $memo->title = $request->title; $memo->register_date = $request->register_date; $memo->note = $request->note; $memo->memo = $request->memo; $memo->links = $request->links; $memo->update(); return response()->json($memo); } } /** * 削除用API * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function delete(Request $request){ if(empty($request->id) ){ return response()->json(['status'=> "E004",'message'=> "idがありません",]); } // 削除時 $res = Memo::destroy($request->id); return response()->json($res); } /** * リスト取得用API * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function multi(Request $request){ return response()->json(Memo::all(["id","title","register_date","note"])); } /** * 単一データ取得用API * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function single(Request $request){ if(empty($request->id)){ return response()->json(['status'=> "E002",'message'=> "idが一致しません",]); }elseif ($request->id == -1){ return response()->json([]); } $memo = Memo::find($request->id); if(empty($memo->id)){ return response()->json(['status'=> "E003",'message'=> 'データの取得に失敗しました',]); } return response()->json($memo); } }
apiにアクセスするjs書く
jsでルーティングしたURLにアクセスする際にはCSRF対策がいるのでhtmlヘッダとajaxヘッダに追加する。
<meta name="csrf-token" content="{{ csrf_token() }}">
js本体は下記のような感じで書いてた。
jQuery(function($){ $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); $.ajax({ type: 'POST', url: "/api/single", dataType:'json', data: {"id":{{ $id }}} }).done(function(response) { let id = {{ $id }}; // idが-1の場合は新規とみなす if(id === -1){ $("input[name='btn-delete']").hide(); return; } // アイテム取得 if(response.status){ alert(response.status + ":" + response.message); }else { $("input[name='title']").val(response.title); $("input[name='register_date']").val(response.register_date); $("input[name='note']").val(response.note); $("textarea[name='memo']").val(response.memo); $("textarea[name='links']").val(response.links); let links = response.links.split("\n"); let html = "<ul>"; for (let i = 0; i < links.length; i++) { if (links[i].indexOf("http") !== 0) continue; html += "<li><a href='" + links[i] + "' target='_blank'>" + links[i] + "</a></li>"; } $("#links-view").val(html); } }).fail(function(xhr) { console.log(xhr); alert("通信に失敗しました") }).always(function(xhr, msg) { //通信完了時の処理 }); });
mixhostへのデプロイ
今回はサブドメインに配置するのでサブドメインを作る。
「aaa.example.com」のような感じのサブドメイン。
cPanelからlaravelがインストールできるので、サブドメインのルートにlaravelをインストールする。
mysql(MariaDB)にデータベースとユーザーを追加する。
.env.sampleをコピーして、名前を変更し.envをつくる。上でDBに追加したデータベース名、ユーザー名、パスワードを転記する。
サブドメイン(aaa.example.com)の管理ページでルートをpublicにする。
サーバーにファイルをコピーする。(上で出てきたファイルを主にコピーする)
必要なライブラリなどはcomposerでインストール。
ターミナルから下記を実行してtableもつくる。
composer install php artisan migrate
うまく動かないときはキャッシュをクリアをしてみる。
ブラウザのキャッシュをクリアしたり、プライベートモードで開いてみたりする。
php artisan config:clear
ドメインの管理会社のページへ行き、DNSにサブドメインとサーバーのIPをAで追加する。
「000.000.000.000」がサーバーのIPアドレスの場合は下記のような感じ。
aaa A 000.000.000.000
これを行うとサブドメインで、laravelアクセスできるようになる。
おわり。