見た映画をメモする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アクセスできるようになる。
おわり。