- 投稿日:2021-01-24T22:08:24+09:00
【初心者】PHPエラー箇所の特定方法(MAMP)
①ターミナルでMAMP内のログファイルに移動
ApplenoMacBook-Air:~ ユーザー名$ cd/Applications/MAMP/logslogsの中の、php_error.logファイルにてエラーが吐き出されている。
②tailコマンドを実行(-fは、ファイルが更新されても常に追い続けてくれる)
ApplenoMacBook-Air:~ ユーザー名$ $ tail -f php_error.log③場所の特定が完了
ApplenoMacBook-Air:~ ユーザー名$ tail -f php_error.log [24-Jan-2021 21:46:13 Asia/Tokyo] PHP Notice: Undefined variable: statusee in /Applications/MAMP/htdocs/ディレクトリ/application/core/View.php on line 63 [24-Jan-2021 21:46:13 Asia/Tokyo] PHP Notice: Undefined variable: statusee in /Applications/MAMP/htdocs/ディレクトリ/application/core/View.php on line 111
- 投稿日:2021-01-24T19:50:45+09:00
【PHP】初中級者が解くべき過去問精選 100 問を解いてみた【6問目/100】
アルゴリズムのアウトプット
ということで、
レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編:目指せ水色コーダー!】@e869120さんAtCoder で水色コーダー、つまりレーティング 1200 を少ない問題数で達成するために、茶色コーダー・緑コーダーにとって適切な教育的良問を 100 問集めました。
こちらの記事の初中級者が解くべき過去問精選 100 問
をPHPで解いていきます。<?php $s = trim(fgets(STDIN)); $number = trim(fgets(STDIN)); $numToArr = str_split($number); $ansList = []; $firstList = []; $secondList = []; for ($i = 0; $i < $s; $i++) { //1桁目の組み合わせが既に出てきている場合は飛ばす if(in_array($numToArr[$i], $firstList)) {continue;} $firstList[] = $numToArr[$i]; for ($j = $i + 1; $j < $s; $j++) { //1桁目、2桁目の組み合わせが既に出てきている場合は飛ばす if ($i >= $j) {continue;} if(in_array($numToArr[$i] . $numToArr[$j], $secondList)) {continue;} $secondList[] = $numToArr[$i] . $numToArr[$j]; for ($k = $j + 1; $k < $s; $k++) { if ($j >= $k) {continue;} $ansList[] = $numToArr[$i] . $numToArr[$j] . $numToArr[$k]; } } }既に出てきたものをチェックするために、配列を持っておくことで計算量をへらす。
- 投稿日:2021-01-24T19:25:37+09:00
Dockerコンテナ間でのFTPアップロードするためのdocker-compose.ymlの書き方
PHP+ApacheからFTPサーバーへデータをアップロードするアプリケーションを開発するために、まずはDockerで開発環境を作ることになりました。
その際に、コンテナ(Apache + php)とコンテナ(Pure-FTPd)の間の通信でハマったので、記事にまとめます。バージョン情報
- PHP 7.4
- Apache 2.4
- Pure-FTPd v1.0.47
結論
最終的な
docker-compose.yml
とPHPのプログラムの記述はこんな感じ。docker-compose.yml
docker-compose.ymlversion: '3.7' services: app: build: . ports: - 443:443 volumes: - .:/var/www/html ftp-server: image: stilliard/pure-ftpd:latest ports: - "21:21" - "30000-30009:30000-30009" volumes: - ./ftp/data:/home/ftpusers environment: - PUBLICHOST=ftp-server - FTP_USER_NAME=ftp_user - FTP_USER_PASS=ftp_password - FTP_USER_HOME=/home/ftpusersFTPでアップロードするプログラム
ftp_upload.php$ftp_server = 'ftp-server'; $ftp_port = 21; $ftp_user_name = 'ftp_user'; $ftp_user_pass = 'ftp_password'; $ftp_send_file = '/hoge/data.txt'; $ftp_remote_file = '/hoge/data.txt'; // FTPサーバへ接続する $conn_id = ftp_connect($ftp_server, $ftp_port); if($conn_id == false){ echo "FTPサーバへの接続失敗"."\n"; exit(); } // ユーザー名とパスワードでログインする $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass); if($login_result == false){ echo "FTPサーバへのログイン失敗"."\n"; // 接続を閉じる ftp_close($conn_id); exit(); } //パッシブモードに設定 ftp_pasv($conn_id, true); // ファイルをアップロードする if (ftp_put($conn_id, $ftp_remote_file, $ftp_send_file, FTP_BINARY)) { echo "UPLOAD 成功"."\n"; } else { echo "UPLOAD 失敗"."\n"; } // 接続を閉じる ftp_close($conn_id);Dockerfileはあまり重要ではないので割愛します。
重要なところ
docker-compose.ymlversion: '3.7' services: # 省略 ftp-server: # 省略 environment: - PUBLICHOST=ftp-serverftp_upload.php$ftp_server = 'ftp-server';解説
参考記事
Dockerはコンテナ名を使用してコンテナ間の通信をするそう。
なので、docker-compose.ymlversion: '3.7' services: # 省略 ftp-server:ここで設定したサービス名(
container_name
で明示的にしていないとサービス名がコンテナ名となる)と、docker-compose.yml# 省略 environment: - PUBLICHOST=ftp-serverこの
PUBLICHOST
を合わせておかないと、Docker間でのFTP通信ができない。(ホスト名が違うとエラーが出る)
docker-compose.yml
内の項目を合わせたら、これでFTPサーバー側の設定はできたので、ftp_upload.php$ftp_server = 'ftp-server';上記のようにアプリ側でコンテナ名(ホスト名)を指定して、プログラムを実行すれば無事アップロードが成功する。(はず)
- 投稿日:2021-01-24T18:54:13+09:00
【PHP】メッセージ通知数表示
学習内容を備忘録としてまとめます。
メッセージ通知数表示機能を実装しましたので、作成方法を記載します。
※通知数の表示は赤枠で囲っています
メッセージ機能については、下の記事で説明しているので割愛します。
実装方法
実装方法について記載していきます。
テーブル構成
messatge_relationテーブル
にmessage_count
を追加します。
このカラムは、ユーザー間にメッセージのやり取りがあった際にインクリメントされ、
通知数を表示するときはmessage_count
カラムから、値を取り出して表示させます。全体の流れ
本機能を、関数とカラム値の遷移を踏まえて全体的な流れをみていきます。
通知数をカウント
では、メッセージのやり取りがある際に
message_count
カラムの値をインクリメントするよう実装します。message_add.php: $stmt->execute($data); $dbh = null; if (!check_relation_message($user_id, $destination_user_id)) { insert_message($user_id, $destination_user_id); } insert_message_count($user_id,$destination_user_id); //ココ set_flash('sucsess', 'メッセージを送信しました'); header('Location:../message/message.php?user_id=' . $destination_user_id . ''); :メッセージを送信するときに、
insert_message_count
で値をインクリメントしています。insert_message_count($user_id,$destination_user_id);引数には
自分のユーザーID
と送信先のユーザーID
を渡しています。function insert_message_count($user_id,$destination_user_id){ try { $dsn='mysql:dbname=db;host=localhost;charset=utf8'; $user='root'; $password=''; $dbh=new PDO($dsn,$user,$password); $sql = "UPDATE message_relation SET message_count = message_count + 1 WHERE ((user_id = :user_id and destination_user_id = :destination_user_id) or (user_id = :destination_user_id and destination_user_id = :user_id)) and user_id = :user_id"; $stmt = $dbh->prepare($sql); $stmt->execute(array(':user_id' => $user_id, ':destination_user_id' => $destination_user_id)); return $stmt->fetch(); } catch (\Exception $e) { error_log('エラー発生:' . $e->getMessage()); set_flash('error',ERR_MSG1); } }
UPDATE
文でmessage_count
をインクリメントしています。
条件文(where)ではメッセージのやり取りをしているユーザー同士のIDから該当のmessage_relation
の列を取得して、message_relation.user_id
がログイン中のユーザーIDと一致するようにしています。
message_relation.user_id
をログイン中のユーザーidとする理由としては、表示する通知数を取得する際にこちらのカラムを利用するからです。
後ほど、詳しく説明します。通知数を表示
相手からメッセージが届いていた時に、通知数を表示する処理を実装します。
message_top.php: foreach ($message_relations as $message_relation): if($message_relation['destination_user_id']==$current_user['id']){ $destination_user=get_user($message_relation['user_id']); }else{ $destination_user=get_user($message_relation['destination_user_id']); } $bottom_message=get_bottom_message($current_user['id'],$destination_user['id']); $new_message_count=current(new_message_count($current_user['id'],$destination_user['id'])); //ココ ?> : <div class="message_notification"> <span id="message_count"> <?php if($new_message_count!=0){ // print''.$new_message_count.''; //ココ }?> // </span> </div> :変数
$new_message_count
に通知数を渡します。function new_message_count($user_id,$destination_user_id){ try { $dsn='mysql:dbname=db;host=localhost;charset=utf8'; $user='root'; $password=''; $dbh=new PDO($dsn,$user,$password); $sql = "SELECT message_count FROM message_relation WHERE ((user_id = :user_id and destination_user_id = :destination_user_id) or (user_id = :destination_user_id and destination_user_id = :user_id)) and user_id = :destination_user_id"; $stmt = $dbh->prepare($sql); $stmt->execute(array(':user_id' => $user_id, ':destination_user_id' => $destination_user_id)); return $stmt->fetch(); } catch (\Exception $e) { error_log('エラー発生:' . $e->getMessage()); set_flash('error',ERR_MSG1); } }引数のユーザーIDから通知数を取得しており、
条件文(where)では自分と相手のIDからmessage_relation
の列を探して、user_id
が相手のIDのものを取得しています。
そうすることで、先ほどインクリメントしていたmessage_count
カラムの値が取得できます。message_top.php: <div class="message_notification"> <span id="message_count"> <?php if($new_message_count!=0){ // print''.$new_message_count.''; //ココ }?> // </span> </div> :あとは表示したい場所に
$new_message_count
を表示させます。
0のときは表示をしないようにします。通知数をリセット
メッセージ画面を開いたときに通知数を0にします。
これをしないとメッセージトップ画面に戻っても、まだ通知数が表示されてしまうからです。message.php: $messages = get_messages($current_user['id'], $destination_user['id']); $bottom_message=get_bottom_message($current_user['id'],$destination_user['id']); reset_message_count($current_user['id'],$destination_user['id']); //ココ ?> <body> :
reset_message_count
関数では該当のカラムに0を渡します。function reset_message_count($user_id,$destination_user_id){ try { $dsn='mysql:dbname=db;host=localhost;charset=utf8'; $user='root'; $password=''; $dbh=new PDO($dsn,$user,$password); $dbh->beginTransaction(); $sql = 'UPDATE message_relation SET message_count = 0 WHERE ((user_id = :user_id and destination_user_id = :destination_user_id) or (user_id = :destination_user_id and destination_user_id = :user_id)) and user_id = :destination_user_id'; $stmt = $dbh->prepare($sql); $stmt->execute(array(':user_id' => $user_id, ':destination_user_id' => $destination_user_id)); $dbh->commit(); } catch (\Exception $e) { error_log('エラー発生:' . $e->getMessage()); set_flash('error',ERR_MSG1); $dbh->rollback(); reload(); } }先ほどの
new_message_count
関数と同様の条件文(where)で列を取得して、0を渡します。上記が実装できれば、トップの動作画面のようになると思います。
【おまけ】新規メッセージ件数の通知
新しいメッセージがあると、ログイン時に件数を通知する機能を実装します。
フラッシュメッセージ機能については、下の記事で説明しているので割愛します。
新規メッセージ数の取得
ログイン時に新しいメッセージあるか、DBを確認します。
user_login_check.php: $_SESSION['user_id']=$rec['id']; $_SESSION['user_name']=$rec['name']; if(current(message_count($_SESSION['user_id']))!=0){ //ココ set_flash('sucsess','ログインしました メッセージが'.current(message_count($_SESSION['user_id'])).'件届いています'); //ココ }else{ set_flash('sucsess','ログインしました'); } header('Location:user_top.php?page_id='.$rec['id'].'&type=main'); :新規メッセージがあれば、
message_count
関数を使用して件数をフラッシュメッセージで表示します。
- 投稿日:2021-01-24T18:29:22+09:00
【PHP】初中級者が解くべき過去問精選 100 問を解いてみた【5問目/100】
アルゴリズムのアウトプット
ということで、
レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編:目指せ水色コーダー!】@e869120さんAtCoder で水色コーダー、つまりレーティング 1200 を少ない問題数で達成するために、茶色コーダー・緑コーダーにとって適切な教育的良問を 100 問集めました。
こちらの記事の初中級者が解くべき過去問精選 100 問
をPHPで解いていきます。<?php $s = trim(fgets(STDIN)); $s = str_replace(array("\r\n","\r","\n"), '', $s); $s = explode(" ", $s); $priceA = $s[0]; $priceB = $s[1]; $priceC = $s[2]; $needA = $s[3]; $needB = $s[4]; $priceList = []; //AとBの少ない方の数分をABで買って足りないを買い足す場合 $buyA = 0; $buyB = 0; $buyC = min($needA, $needB) * 2; if ($needA <= $needB) { $buyB = $needB - $buyC / 2; } else { $buyA = $needA - $buyC / 2; } $priceList[] = $buyA * $priceA + $buyB * $priceB + $buyC * $priceC; //Cを買わない場合 $priceList[] = $priceA * $needA + $priceB * $needB; //Cのみ買う場合 $priceList[] = $priceC * 2 * max($needA, $needB); echo min($priceList) . "\n"; }全列挙するとオーバーフローするので、条件別に分けて計算量を減らす問題
- 投稿日:2021-01-24T18:29:11+09:00
【最新版】はじめてのLaravel!Laradockを用いたLaravel開発環境構築
- 最終編集日(2021年1月)
- PHP、Dockerのインストールも後日投稿予定です。アカウントをフォローしてお待ちください!
環境構築だけ読みたい方は、Laravelの環境構築まで読み飛ばしてください。
概要
本記事は、PHPのフレームワークであるLaravelの環境構築を開設した記事です。
構築する Laravel 及び PHP のバージョンは以下になります。
- Laravel 8.x
- PHP 7.4
初めてLaravelを使う方、一度環境構築で挫折した方でもつまずかないことを心掛けて執筆しました。
何かわからないことことがありましたら、コメントでお知らせください!
環境
Docker for Desktopのインストールが必要になります
- Mac
- Windows
- Windows 10 homeの方は、Windowsをバージョン2004,ビルド19041以上にアップデートした上でWSL 2のインストールが必要になります
- Docker Toolboxでも環境構築をすることはできますが、一部コマンドが異なる場合があります
- 本記事では
MySQL
を使います。PostgreSQL
での環境構築も可能ですが、Laradockの起動で一部コマンドが異なります。Laradock で使用できる PHP バージョン早見表
Laradockで使用できるPHP、Laravelのバージョンは以下の通りです。
※2021年1月現在公式サポートされているPHPのバージョンのみ記載しています。
PHPバージョン Laradock対応 7.3 〇 7.4 〇 8.0 × 前提条件
- gitをインストールしていること
- Docker for Desktopをインストールしていること
Terminalで以下のコマンドを実行して正しく出力されるかを確認してください。
$ git --version git version 2.9.0 $ docker --version Docker version 19.03.1, build 74b1e89e8a $ docker-compose --version docker-compose version 1.24.1, build 4667896b※Dockerのバージョンは
17.12
以降である必要があります。
(参考) Getting StartedLaravelの環境構築
それでは実際にLaravelの環境構築を行っていきましょう。
プロジェクトディレクトリの作成
mkdir
コマンドでLaradock
をインストールするディレクトリを作成します。ここでは、laravel-workspace
としています。mkdir laravel-workspace
cd
コマンドで作成したディレクトリに移動します。cd laravel-workspaceLaradockのインストール
Laradockをインストールしていきます。
以下のコマンドを実行します。
$ git clone https://github.com/Laradock/laradock.gitインストールが終わると以下のように表示されます。
$ git clone https://github.com/Laradock/laradock.git Cloning into 'laradock'... remote: Enumerating objects: 11524, done. remote: Total 11524 (delta 0), reused 0 (Rdelta 0), pack-reused 11524eceiving objects: 100% (11524/11524), 11.36 MiB | 3Receiving objects: 100% (11524/11524), 11.42 MiB | 346.00 KiB/s, done. Resolving deltas: 100% (6203/6203), done. Checking connectivity... done.
laradock
ディレクトリが作成されていることがわかります。$ ls laradock/
Laradock
のインストールは以上です.env ファイルの編集
.env
ファイルを編集することで、プロジェクトの環境変数を定義していきます。使用するデータベースやPHPのバージョンなどもここで指定します。
cd
コマンドを使って先ほど作成されたlaradock
ディレクトリに移動しましょう。$ cd laradock
laradock
ディレクトリの中には、env-example
という.env
のサンプルがあります。これをコピーして使用します。以下のコマンドでコピーしてください。cp env-example .env
.env
を編集していきます。お好きなエディタで.env
ファイルを開いてください。1.プロジェクトの相対パスの指定
プロジェクトを作成するにあたり、パスを指定します。
ここでは、laravel-project
というプロジェクトをlaradock
同じ階層に作成します。laravel-workspace ├── laradock └── laravel-project8行目を以下のように編集してください。
.env- APP_CODE_PATH_HOST=../ + APP_CODE_PATH_HOST=../laravel-project2.データベースのディレクトリ変更
デフォルトでは、データベースなどがホームディレクトリに保存されるようになっています。
プロジェクトディレクトリ配下に作成されるように設定を変更しましょう。17行目を以下のように編集してください。
.env- DATA_PATH_HOST=~/.laradock/data + DATA_PATH_HOST=.laradock/data3. コンテナ名の変更
ここでは、Dockerを起動するときのコンテナ名を指定していきます。「コンテナ?」という方はコピペしていただいて構いません。
※Dockerに関しては「いまさらだけどDockerに入門したので分かりやすくまとめてみた」の記事が非常にわかりやすいです。36行目を以下のように編集してください。
.env- COMPOSE_PROJECT_NAME=laradock_ + COMPOSE_PROJECT_NAME=laravel-project4. PHPのバージョン設定
PHPのバージョンを設定します。
42行目を使用したいPHPのバージョンに変更します。
ここでは、PHP 7.4
を指定します。.env- PHP_VERSION=7.3 + PHP_VERSION=7.42021年1月現在のLaradockがサポートしているPHPのバージョンに関してはこちらをご覧ください。
Laradockの起動
それではLaradockを起動していきます。
laradock
ディレクトリで以下のコマンドを実行してコンテナを起動します。※
postgres
を使用している場合は、mysql
の部分をpostgres
に置き換えてください。$ docker-compose up -d php-fpm nginx mysql workspace以下のように表示されればOKです。
$ docker-compose up -d nginx mysql workspace . . . Creating laravel-project_docker-in-docker_1 ... done Creating laravel-project_mysql_1 ... done Creating laravel-project_workspace_1 ... done Creating laravel-project_php-fpm_1 ... done Creating laravel-project_nginx_1 ... doneLaravelアプリケーションの作成
それではLaravelのアプリケーションを作成していきます。以下のコマンドを実行してください。
$ docker-compose exec workspace bash以下のような表示になれば正常に
bash
が起動できています。$ docker-compose exec workspace bash root@6095e16a845d:/var/www#コマンドの最後には、Laravelのバージョンを指定しています。2021年現在、最新版は
Laravel8.x
です。ここでは8.*
を指定していますが、コマンドの最後の数字を変えることで、別のバージョンのLaravelでアプリケーションを作成をすることができます。# composer create-project --prefer-dist laravel/laravel="8.*" .※アプリケーションの作成には少し時間がかかります。
Application key set successfully.
と表示されればアプリケーションの作成は完了です。以下のようにプロジェクトの相対パスの指定で指定した名前と同じフォルダが作成されています。
laravel-workspace ├── laradock └── laravel-projectアプリケーションの確認
http://localhost にアクセスしてLaravelプロジェクトが作成されているか確認してみましょう。
上記のように表示されていれば正常にアプリケーションが作成されています。
コンテナの停止
コンテナを停止するときは以下のコマンドで停止することができます。
$ docker-compose stop参考
※本記事はTechpitの教材を一部修正したものです。
最後まで読んでいただきありがとうございました。今後も、PHP・Laravelに関する記事を投稿していきますので、もしよろしければ、Techpitをフォローしてお待ちください!
- 投稿日:2021-01-24T17:35:13+09:00
Docker上のLaravelにJetstreamをインストールする。
https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4
https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4
上記の記事を参考に構築したLaravel8に、Jetstreamをインストールします。ComposerでJetstreamをインストールする
まず、Laravelをインストールしたコンテナに入ります。
$ docker-compose exec [コンテナ名] [コマンド名]次にcomposerコマンドを実行します。
$ composer require laravel/jetstreamjetstream:installを実行
フロントエンドスタックとして、LivewireかInertiaを指定します。
Livewireはテンプレート言語にLaravelのBladeを利用します。
一方、InertiaはVue.jsを利用します。
どちらの場合も、--teamsをつけることでチームサポートを有効にできます。$ php artisan jetstream:install livewire $ php artisan jetstream:install livewire --teams$ php artisan jetstream:install inertia $ php artisan jetstream:install inertia --teamsnpmの依存パッケージをインストール・構築
npmがインストールされているコンテナで実行します。
$ npm install && npm run devデータベースをマイグレートする
こちらは再びLaravelのコンテナで実行します。
$ php artisan migrate確認
Laravelのホーム画面を確認すると、右上にログイン画面、ユーザー登録画面へのリンクが表示されており、それぞれの画面へ遷移できます。
composer require aravel/jetstream でメモリエラーが出た場合
php.iniファイルのmemory_limitを一時的に無制限にすることで対応可能です。
インストール後、memory_limitの値を元に戻しておいてください。php.inimemory_limit = 256M↓
php.inimemory_limit = -1
- 投稿日:2021-01-24T17:27:23+09:00
共同開発講座を受講中にコツコツ書いた「詰まったメモ」をジャンル別に全て公開します【データベース(migration/seeding)編】
はじめに
タイトルの通り、共同開発講座を受講中に起きたトラブルや詰まりポイントをまとめたメモ(約50記事)をジャンル別に全て公開します。
ジャンルは以下の通りなので、気になるものがあればぜひご覧ください。【ジャンル一覧】
・GitHub関連
・Laravel関連
・データベース(migration/seeding)関連
・環境関連
・総まとめ集下記の点を、ご了承ください。
・ジャンルで統一しているため、内容に関しては統一性はありません。
・メモの難易度もバラバラです。
・初学者向けの内容となっております。
・自分用のメモを転用しておりますので、表現が稚拙な部分があるかと思います。
・あくまで僕のメモです!!・Laravelのカラム作成で使えるデータ型
- increments('id') ... 「符号なしINT」を使用した自動増分ID(主キー)
- binary('カラム名') ... バイナリデータカラム
- boolean('カラム名') ... 真偽値カラム
- char('カラム名', 長さ) ... 長さを指定する文字列カラム
- date('カラム名') ... 日付カラム
- time('カラム名') ... 時間カラム
- dateTime(カラム名) ... 日時カラム
- double('カラム名', 桁数, 小数点以下桁数) ... ○桁で小数点以下×桁の小数カラム
- enum('カラム名', ['定数', '定数']) ... ENUMカラム
- integer('カラム名') ... 数値データカラム
- json('カラム名') ... JSONフィールドカラム
- timestamp('カラム名') ... TIMESTAMPカラム
- timestamps() ... created_atとupdate_atカラム
- nullableTimestamps() ... NULL値を許す以外、timestamps()と同じ
- string('カラム名') ... VARCHARカラム
- string('カラム名', 長さ) ... 長さ指定のVARCHARカラム
- text('カラム名') ... TEXTカラム
・migration時の外部キー制約エラー
外部キー制約をつけてマイグレーションをするとエラーが起きてしまう件について
まず外部キー制約について
外部キー制約の一例
$table->foreign('sale_status_id')->references('sale_status_id')->on('m_sales_statuses')->onDelete('cascade');解説
子テーブルのカラムとして定義したsale_status_idを外部キーと指定し、それはm_sales_statusesというテーブルのsale_status_idというカラムと紐付くこととする
onDelete(‘cascade’)・・・親テーブルの行を削除したときに、子テーブルないの一致する行を自動的に削除されるようにするオプションのこと。例えばユーザーが消えるとそのユーザが持っている動画が消える等。
エラー内容を見ていきます
エラー内容
Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `m_products` add constraint `m_products_sale_status_id_foreign` foreign key (`sale_status_id`) references `m_sales_statuses` (`sale_status_id`))原因
①データの型が合っていない
Integer やstring、unsignedなど
上記のカラム作成で使えるデータ型を確認する(これが割と間違ってることが多い)②マイグレーションする順番が違う(作成順序が違う)
親テーブルと子テーブルがあるが、先に参照される側の親テーブルを先にマイグレーションしてテーブルを作成しておかないといけない。
親テーブルが存在して初めて、外部キー制約を記述したものをマイグレーションできる・seeding時のエラー
migrationはできたけどデータの流し込み(seedingがうまくいかない)
seedingを行うとエラーが発生するエラー内容
Illuminate\Database\QueryException : SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`laravel`.`m_products`, CONSTRAINT `m_products_sale_status_id_foreign` FOREIGN KEY (`sale_status_id`) REFERENCES `m_sales_statuses` (`sale_status_id`) ON DELETE CASCADE) (SQL: insert into `m_products` (`product_id`, `product_name`, `category_id`, `price`, `description`, `sale_status_id`, `product_status_id`, `resist_date`, `user_id`, `delete_flag`) values (1, 黒毛和牛サーロイン, 1, 8000, なめらかでとろける食感と、甘くコクがある上品な香りが特徴です, 1, 1, 2020-11-22 12:16:43, 1, ))原因と解説
子テーブルに外部キー制約が存在する場合、seedingの順番にも気をつける必要がある。
親テーブルより先に子テーブルをmigrationした場合にエラーが出たのと同様の理由でエラーが出る。
seeding時も親テーブルにデータが入っていない状態で、外部キーがある子テーブルにデータを流し込むとエラーが発生する。
seedingに関しても親→子の順番でseedingを行わなければならない・SQL 1364 エラー
ブラウザ上でフォームを飛ばした時に起こるエラーです
エラー内容
SQLSTATE[HY000]: General error: 1364 Field 'user_classification_id' doesn't have a default valueエラーの意味
「user_classification_idのデフォルト値がない」
つまり…
「データベースにデータを登録する際に、user_classification_idの値がないとダメですよ」
っていう意味。
デフォルト値をつけろと言われている。解決策
今回はフォームにuser_classification_idの要素を入力する欄がなかったため、データを登録時に送ることができなかった。
でも、データベースのusersテーブルにはuser_classification_idが存在するため、どうにかしてデータを入れないといけない。
そこで、migrationの段階で手を打っておく必要がある。
具体的には、migrationでusersテーブルのカラム定義の際に、修飾子をつけること。
修飾子は ->nullable() もしくは ->default(○○)
つまり存在しなくても良しとするか、デフォルト値を予め設定しておく。というような修飾子をつけて、マイグレーションすることでこのエラーは解決する。
ただ、可能な限り ->default(○○) を使ったほうがいい。例)m_users.php(マイグレーションファイル)
public function up() { Schema::create('m_users', function (Blueprint $table) { $table->increments('id'); $table->string('password', 64); $table->string('last_name', 16); $table->string('first_name', 16); $table->integer('zipcode'); $table->string('prefecture', 16); $table->string('municipality', 16); $table->string('address', 32); $table->string('apartments', 32); $table->string('email', 128); $table->string('phone_number', 16); $table->integer('user_classification_id')->unsigned()->default(1);//←ここ!! //外部キー制約 $table->foreign('user_classification_id')->references('id')->on('m_users_classifications')->onDelete('cascade'); $table->string('company_name', 128)->nullable();//←ここ!! $table->char('delete_flag', 1)->nullable();//←ここ!! $table->rememberToken(); $table->timestamps(); }); }・マイグレーション実行コマンド
カラムの追加をしたいときのマイグレーションファイルの作成コマンド
$ php artisan make:migration add_title_to_users_tables - -table=usersマイグレーション実行コマンド
php artisan migrate:reset全てのテーブルにおいて今まで実行したマイグレーションを初期化。
再度migrationは実行されない。php artisan migrate:refresh全てのテーブルにおいて今まで実行したマイグレーションを初期化
再度migrationを実行する。php artisan migrate:fresh全てのテーブルを削除。
再度migrationを実行する。php artisan migrate:rollback最後に実行したマイグレーションを元に戻す。
Step オプションをつけると元に戻す回数を指定できる。・migration と seeding の総まとめ
マイグレーションとは
ザックリ言うとテーブルを作成するための作業
マイグレーションファイルをコマンドで作成し、作りたいテーブルのカラムを記載していく。
記載したファイルをコマンドでマイグレーションすると、データベースにテーブルが作成される。
また、マイグレーションファイルにはカラムに対してデータ型や修飾子、FKを記載しておくとマイグレーション実行時に反映される。
ただ、FKの関係でマイグレーションする順番が重要になってくるので、マイグレーションファイルを作成する順番に気を付ける。(FKで指定されているテーブルがないと、エラーが起こるので、先に親テーブルからマイグレーションされるように作成順番を考える。→子テーブルを後に作成する)
今回はphpmyadminを使用しているので、ブラウザ上で視覚的に確認することができる。
Phpmyadmin上で、使用するデータベースを作成しておかないと、テーブルをその中に作ることができないので注意マイグレーションファイルの作成(カラム、FK、その他修飾子の作成)
php artisan make:migration ファイル名
でファイル作成。ファイルの中身はこんな感じ
public function up() { Schema::create('m_products', function (Blueprint $table) { $table->increments('id'); $table->string('product_name', 64); $table->integer('category_id')->unsigned(); $table->integer('price')->unsigned(); $table->string('description', 256); $table->integer('sale_status_id')->unsigned(); $table->integer('product_status_id')->unsigned(); $table->timestamp('resist_date'); $table->integer('user_id')->unsigned(); $table->char('delete_flag', 1); $table->foreign('sale_status_id')->references('id')->on('m_sales_statuses')->onDelete('cascade'); $table->foreign('product_status_id')->references('id')->on('m_products_statuses')->onDelete('cascade'); }); }データ型について
上記のファイル内の記載のうち、string integer timestamp などがデータ型にあたる。
そのデータはどういう形式のデータなのか?文字なのか?数字なのか?その時の時間なのか?
を指定することができる。詳しくはGoogle先生に。php artisan migrate の実行
このコマンドを実行すると、作成したマイグレーションファイルがテーブルとして作成される。
エラーになる場合は、他のエラーに関するメモを参照(上記記載)。migrationエラーについて
多かったエラーは
①データ型があっていない場合
②migrationする順番が違い、外部キー制約がつかないために起こるエラーシーディングとは
ザックリい言うと、テストデータを一気に作成することができる機能で、ファイルを作成してシーディングを行うことテーブル内にデータが挿入される。
テストデータの決定
シーディングを行うテーブルに適したデータを考える。
例えば、商品(肉とか魚)のテストデータを考える時は、それぞれのカラムに適応した具体的なデータ(商品名や値段)を考える。
何個でも一気に登録できるが、まぁ、テストなので5~10個程度あれば十分。シーディングファイルの作成
php artisan make:seeder ファイル名
上記コマンドでシーディングファイルが作成される。中身には前項で決定したテストデータを記載していく。
実際の内容としてはこんな感じ
public function run() { DB::table('m_products')->insert([ 'id' => 1, 'product_name' => '黒毛和牛サーロイン', 'category_id' => 1, 'price' => 8000, 'description' => 'なめらかでとろける食感と、甘くコクがある上品な香りが特徴です' , 'sale_status_id' => 1, 'product_status_id' => 1, 'resist_date' => date('Y-m-d H:i:s'), 'user_id' => 1, 'delete_flag' => '' ]); DB::table('m_products')->insert([ 'id' => 2, 'product_name' => 'A5ランク松坂牛', 'category_id' => 1, 'price' => 12000, 'description' => '松坂牛は濃厚で上品な甘みが絶品!' , 'sale_status_id' => 1, 'product_status_id' => 1, 'resist_date' => date('Y-m-d H:i:s'), 'user_id' => 1, 'delete_flag' => '' ]);例として2つだけここに書いたが、実際は何個でも良い。
php artisan db seed の実行
このコマンドを実行することで、作成したシーディングファイル(テストデータ込み)がシーディングされて、当該テーブルにデータが挿入される。
このコマンドの実行時にエラーとしてよく起こるのは
①子テーブルと親テーブルの関係
②外部キー関連
が多いが、詳しくは別のメモにまとめてあるものを参照(上記記載)。
- 投稿日:2021-01-24T17:15:20+09:00
Docker + Laravel + Vue の環境構築 - Docker編
はじめに
Docker
がWindows10 Home
にも対応したということでDockerでの環境構築を始めてみました。Docker
とVue
は初めて触ります。Laravel
のみ少し経験あり。- Xserverにデプロイするつもりで構築。
- ドキュメントルートはプロジェクト直下の
public_html
- 本来はWebサーバーは
Apache
だけど、慣れたいのでnginx使ってます。環境
- Windows 10 Home(20H2)
Dockerのインストールについて
- インストール
- Docker Desktop for Windows
- インストールの詳細については割愛します。
- 発生したトラブル
Win10
にすんなりインストールして使えるとはいかず、バージョンアップをしました。- Windowsアップデートがまだの場合、下記公式からダウンロード可能です。
- 生成されたバージョン
- Docker: 20.10.2
- Docker Compose: 1.27.4
Docker
- Docker単体でも使えるが
Docker Compose
を使うのが便利なようです。- docker-composeは
yml
ファイルに複数のコンテナの定義を記述し、立ち上げができます。- WEBサーバーやDB等の1つのファイルで管理でき、コンテナ間の連携もできる大変便利なツールです。
- 今回使う
Docker Desktop
のインストール内容にDocker Compose
も含まれています。Docker Composeの準備
- 下記の
yml
を実行し、以下の環境が作られました。
- php : 7.4.14
- nginx : 1.19.6
- MySql : 5.7.32
- PhpMyAdmin : 5.0.4
- npm : 6.12.1
- node : 12.13.1
docker-compose.ymlversion: '3' services: php: build: ./docker/php volumes: - ./src:/var/www nginx: image: nginx ports: - 80:80 volumes: - ./src:/var/www - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - php tty: true command: [nginx-debug, '-g', 'daemon off;'] db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: sample_project MYSQL_USER: docker MYSQL_PASSWORD: docker TZ: 'Asia/Tokyo' command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - ./docker/db/data:/var/lib/mysql - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf - ./docker/db/sql:/docker-entrypoint-initdb.d ports: - 3306:3306 phpmyadmin: image: phpmyadmin/phpmyadmin environment: - PMA_ARBITRARY=1 - PMA_HOST=db - PMA_USER=docker - PMA_PASSWORD=docker links: - db ports: - 4000:80 volumes: - ./docker/phpmyadmin/sessions:/sessions node: image: node:12.13-alpine tty: true volumes: - ./src:/var/www working_dir: /var/wwwphp -> Dockefileの準備
Dockerfile
に各コンテナの詳細情報を定義します。
これはphp
用のDockerfileで、今回個別に用意するのはこれだけです。FROM php:7.4-fpm COPY php.ini /usr/local/etc/php/ # 1. 必要なツールをインストール RUN apt-get update \ && apt-get install -y zlib1g-dev mariadb-client vim libzip-dev \ && docker-php-ext-install zip pdo_mysql \ && git vim curl cron unzip # 2. Composerインストール RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" RUN php composer-setup.php RUN php -r "unlink('composer-setup.php');" RUN mv composer.phar /usr/local/bin/composerd ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME /composer ENV PATH $PATH:/composer/vendor/bin WORKDIR /var/www # 3. laravelインストール RUN composer global require "laravel/installer"php -> php.iniの準備
php.ini[Date] date.timezone = "Asia/Tokyo" [mbstring] mbstring.internal_encoding = "UTF-8" mbstring.language = "Japanese"nginx -> default.conf
server { listen 80; index index.php index.html; root /var/www/public_html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }ここまでのディレクトリ構成
適当な場所にプロジェクトフォルダを作り、下記のように配置してください。
※[]
で囲ってる箇所はディレクトリです。[myLaravel] ├── [docker] │ ├── [nginx] │ │ └── default.conf │ └── [php] │ ├── Dockerfile │ └── php.ini └── [src]Docker Composeの実行
- コマンドプロンプト、または
Git Bash
等を使ってプロジェクトフォルダへ移動してください。- 下記コマンドを実行すると
Docker Compose
の内容からコンテナが作成され、下記のように動作を確認できます。~/myLaravel$ docker-compose up -d Starting mylaravel_db_1 ... done Starting mylaravel_node_1 ... done Starting mylaravel_php_1 ... done Starting mylaravel_phpmyadmin_1 ... done Starting mylaravel_nginx_1 ... done
Docker Desktop
を確認すると下記のように指定したプロジェクトと、コンテナが作成されていることが確認できます。
これで環境が整いました。
Docker Desktopからの操作
各コンテナにカーソルを合わせると、いくつかアイコンが表示されます。
左から
- ブラウザを開く
- WebサーバーやPhpMyAdmin等ブラウザ上で確認できるものにだけ、アイコンが表示されます。
- コンソール画面を開く
- コンソール上での操作を行います。
- 他の記事だとコマンド
docker-compose exec php bash
を使ってるものが多いです。- なぜか僕はこのコマンドでエラーになるので、デスクトップアプリ経由で使ってます。
docker-compose.yml
の各コンテナの設定にtty:true
があればできるはずなんですが解決できなかったので、設定から外しています。- PHPコマンドやnpmを使う時はそれぞれのコンソール上からしか実行できないので、やりたいことに合わせたコンソールを開く必要があります。ちょっとめんどくさい。
- コンテナの停止
- コンテナの再起動
- コンテナの削除
最終的にできた構成
db
,phpmyadmin
ディレクトリが作られました。中身は特に気にしなくていいので省略してます。[myLaravel] ├── [docker] │ ├── [db] │ │ └── ... │ ├── [nginx] │ │ └── default.conf │ ├── [php] │ │ ├── Dockerfile │ │ └── php.ini │ └── [phpmyadmin] │ └── [sessions] └── [src]次回
次回はLaravelとVueの環境構築を進めます。
参考にさせていただいた記事
https://qiita.com/phper_sugiyama/items/654f7a9171ae5ccf3e83
https://qiita.com/rockinruuula1227/items/83f3f1406f339083ef3f
- 投稿日:2021-01-24T16:37:43+09:00
【PHP】初中級者が解くべき過去問精選 100 問を解いてみた【4問目/100】
アルゴリズムのアウトプット
ということで、
レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編:目指せ水色コーダー!】@e869120さんAtCoder で水色コーダー、つまりレーティング 1200 を少ない問題数で達成するために、茶色コーダー・緑コーダーにとって適切な教育的良問を 100 問集めました。
こちらの記事の初中級者が解くべき過去問精選 100 問
をPHPで解いていきます。<?php $input_line = trim(fgets(STDIN)); $input_line = str_replace(array("\r\n","\r","\n"), '', $input_line); $input_line = explode(" ", $input_line); $arr = []; for ($i = 0; $i < $input_line[0]; $i++) { $s = trim(fgets(STDIN)); $s = str_replace(array("\r\n","\r","\n"), '', $s); $s = explode(" ", $s); $arr[] = $s; } $sumArr = []; for ($k = 0; $k < $input_line[1]; $k++) { for ($l = 0; $l < $input_line[1]; $l++) { if ($k <= $l) {continue;} $sum = 0; for ($j = 0; $j < $input_line[0]; $j++) { $sum = $sum + max($arr[$j][$k], $arr[$j][$l]); } $sumArr[] = $sum; } } echo max($sumArr) . "\n"; }配列でデータを持って条件に合わせて参照する問題。
- 投稿日:2021-01-24T16:16:02+09:00
【PHP】住所を都道府県/市区町村/それ以降に分ける
参考
この記事を作るにあたり、以下のサイトを大いに参考にしました。
なるべく短い正規表現で住所を「都道府県/市区町村/それ以降」に分けるエクストリームスポーツ
PHP: preg_match - Manual
[PHP] preg_match の正規表現の中で日本語(マルチバイト文字)を使う « Codaholicコード
separate_address.php<?php /** * @param string $address * @return array */ function separate_address(string $address) { if (preg_match('@^(.{2,3}?[都道府県])(.+?郡.+?[町村]|.+?市.+?区|.+?[市区町村])(.+)@u', $address, $matches) !== 1) { return [ 'state' => null, 'city' => null, 'other' => null ]; } return [ 'state' => $matches[1], 'city' => $matches[2], 'other' => $matches[3], ]; } var_dump(separate_address('京都府京都市東山区清水1丁目294')); var_dump(separate_address('東京都府中市宮西町2丁目24番地')); var_dump(separate_address('不正な住所')); // 市より先がない var_dump(separate_address('東京都府中市')); // 市名に村が入ってるのでうまく分けられていない。今回は非対応 var_dump(separate_address('東京都東村山市本町1丁目2番地3'));$ php separate_address.php array(3) { ["state"]=> string(9) "京都府" ["city"]=> string(18) "京都市東山区" ["other"]=> string(16) "清水1丁目294" } array(3) { ["state"]=> string(9) "東京都" ["city"]=> string(9) "府中市" ["other"]=> string(24) "宮西町2丁目24番地" } array(3) { ["state"]=> NULL ["city"]=> NULL ["other"]=> NULL } array(3) { ["state"]=> NULL ["city"]=> NULL ["other"]=> NULL } array(3) { ["state"]=> string(9) "東京都" ["city"]=> string(6) "東村" ["other"]=> string(27) "山市本町1丁目2番地3" }
- 投稿日:2021-01-24T16:11:33+09:00
phpMyAdmin 4.6.6 のWarning対処
同じような環境を何度も構築しては、phpMyAdminから警告がでるので、いい加減まとめる。
最新をソースからinstallすればいいんだけど、aptに慣れた体にはマジ無理・・。環境
- Ubuntu 18.04.5 LTS (Bionic Beaver)
- Apache 2.4.29
- MySQL 5.7.32-0ubuntu0.18.04.1 - (Ubuntu)
- PHP 7.2.24-0ubuntu0.18.04.7
- phpMyAdmin 4.6.6deb5ubuntu0.5
インポート/エクスポート回り2箇所でWarningがでるので対処。
Warning in ./libraries/plugin_interface.lib.php#551
Warning in ./libraries/plugin_interface.lib.php#551 count(): Parameter must be an array or an object that implements Countablephp7.2から、count(null)に対して0ではなく、warningを返すようになったため。
/usr/hsare/phpmyadmin/libraries/plugin_interface.lib.php の551行目あたり/usr/share/phpmyadmin/libraries/plugin_interface.lib.phpif ($options != null && count($options) > 0) {を、
/usr/share/phpmyadmin/libraries/plugin_interface.lib.phpif ($options != null && count((array)$options) > 0) {に修正。もう一箇所は、、
Warning in ./libraries/sql.lib.php#613
Warning in ./libraries/sql.lib.php#613 count(): Parameter must be an array or an object that implements Countable/usr/share/phpmyadmin/libraries/sql.lib.phpの、613行目あたり。
/usr/share/phpmyadmin/libraries/sql.lib.php|| (count($analyzed_sql_results['select_expr'] == 1)を、
/usr/share/phpmyadmin/libraries/sql.lib.php|| ((count($analyzed_sql_results['select_expr']) == 1)参考(ありがとう)
- 投稿日:2021-01-24T15:35:35+09:00
共同開発講座を受講中にコツコツ書いた「詰まったメモ」をジャンル別に全て公開します【Laravel編】
はじめに
タイトルの通り、共同開発講座を受講中に起きたトラブルや詰まりポイントをまとめたメモ(約50記事)をジャンル別に全て公開します。
ジャンルは以下の通りなので、気になるものがあればぜひご覧ください。【ジャンル一覧】
・GitHub関連
・関連
・php関連
・データベース(migration/seeding)関連
・環境関連
・総まとめ集下記の点を、ご了承ください。
ジャンルで統一しているため、内容に関しては統一性はありません。
なるべく有用性の高いメモの使用を心がけておりますが、あくまで初学者向けの内容となっております。
自分用のメモを転用しておりますので、表現が稚拙な部分があるかと思います。・MVCの考え方(言葉で説明)
ユーザ登録機能を題材にMVCの実際の動きを確認します
ルーティング(Web.php)の
Route::get('signup', 'Auth\RegisterController@showRegistrationForm')->name('signup');この意味は
signupと検索されればRegisterControllerにいって、showRegistrationFormアクションを発動させる
↓
RegisterControllerに行くとshowRegistrationFormアクションはトレイトで表記されている。ちなみに
トレイトの内容はreturn view(‘auth.register’)となっていて
「Authフォルダにある、register.blade.phpというviewファイルを表示しなさい」という意味
つまり
Authフォルダを作って、その中にregister.blade.phpを作成してそれが呼び出されるようにする・LaravelCollective導入時のエラー
Laravel Collectiveとは
Laravelには便利なライブラリがたくさんある。
Larval collective はその中の一つ
Laravel のビューでフォームを記述するには直接HTMLを記述する方法とヘルパー関数(HTML/Formヘルパー)を使う方法がある。
ヘルパー関数を使う場合はこのパッケージをcomposerでインストールする必要がある。
なお、LaravelCollective/htmlはLaravel4では標準で組み込まれていたが、Laravel5からは別パッケージになった。導入時のエラーの詳細
Webコンテナに入る
[vagrant@local-docker lara-d]$ docker-compose exec web bash紹介されたコマンド実行
↓
以下のようなエラーが起こる[root@1b08bc3fd4bf html]# composer require "laravelcollective/html":"5.5.*" ./composer.json has been updated Running composer update laravelcollective/html Loading composer repositories with package information Updating dependencies Your requirements could not be resolved to an installable set of packages. Problem 1 - laravelcollective/html[v5.5, ..., 5.5.x-dev] require illuminate/http 5.5.* -> found illuminate/http[v5.5.0, ..., 5.5.x-dev] but it conflicts with another require. - laravelcollective/html v5.5.2 requires illuminate/http 5.6.* -> found illuminate/http[v5.6.0, ..., 5.6.x-dev] but it conflicts with another require. - Root composer.json requires laravelcollective/html 5.5.* -> satisfiable by laravelcollective/html[v5.5, ..., 5.5.x-dev]. Installation failed, reverting ./composer.json and ./composer.lock to their original content.導入時のエラーの原因
原因①
PHPのバージョンとLaravelのバージョンが一致していなかったのが原因。
適応するバージョンにアップデートしたら無事導入できた。原因②
インストール実行コマンドの仕様が違っていた。
紹介されていたコマンド
composer require "laravelcollective/html":"5.5.*"調べてインストール成功したコマンド
composer require "laravelcollective/html":"^5.5"※ちなみにLaravelCollectiveはプロジェクト毎にインストールしないといけないので注意
・セッションの使用方法
セッションの使用方法は大きく3つある
①Requestインスタンスを用いる方法
②グローバルSessionへルパ関数を利用する方法
(③ファサードを利用する方法)今回は①のRequestインスタンスを利用する方法で実装する
セッションへのデータ保存(Requestインスタンス経由)
$request -> session () -> put ( ‘ key ’ , ’ value ’ ) ;ここのkeyは勝手に名前つけて良いの?→良い!
Valueは何を入れたら良いの?→保存したい値!セッションデータの取得(Requestインスタンス経由)
$request->session () -> get( ‘ key ’ );データの保存先
Laravelの
strage > framework > sessions に格納されていく!・フォームリクエストの作成方法
コントローラ作成する時みたいに
php artisan make:request CreateProductRequest
でリクエストを作成する作成したファイルにバリデーションを記載していく
この時、authorize()はとりあえずtureにしておく(細かい設定もある)CreateProductRequest<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; //クラス名は作成時に指定したものになる class CreateProductRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; //細かい設定もあるようだけど、とりあえずtureにしとく } /** * Get the validation rules that apply to the request. * * @return array */ //ここにバリデーションを書いていく public function rules() { return [ 'product_name' => 'required|string|max:20', 'category_id' => 'required|numeric|exists:m_categories,id', 'price' => 'required|numeric', 'sale_status_id' => 'required|numeric|exists:m_sales_statuses,id', 'product_status_id' => 'required|numeric|exists:m_products_statuses,id', 'description' => 'required|string|max:191', ]; } }コントローラのupdateアクションで、さっき作成したフォームリクエスト(バリデーション)を用いて、リクエスト情報を更新する。
Controllerのupdateアクションここに public function update(CreateProductRequest $request, $id) { $product = MProduct::with(['category', 'sale_status', 'product_status'])->find($id); // dd($request); $product->product_name = $request->product_name; $product->category_id = $request->category_id; $product->price = $request->price; $product->sale_status_id = $request->sale_status_id; $product->product_status_id = $request->product_status_id; $product->description = $request->description; $product->save(); return redirect('seller/items'); }フォームリクエストを使用することで、更新時には、まずCreateProductRequestに記載したバリデーションを実行してくれて、それがtureであれば( authorize()の話 )コントローラの内容が実行されるという流れ。
もしバリデーションに引っかかった場合はエラー情報を持たせて、直前のページにリダイレクトしてくれる。・リレーション先のデータを取得する
モデルにリレーションを貼って、リレーション先のデータを取得できるようにします
例えば...
Product テーブル
→商品に関するテーブルで登録された商品がたくさん入っているCategories テーブル
→Productテーブルの親テーブルで、商品をカテゴリー別に分類するためのカテゴリーデータが入っているこの二つのテーブルにリレーションを貼ります
リレーションの貼り方
Product モデル
class Product extends Model { ・・・ public function category() { return $this->belongsTo(Category::class); } ・・・ }category メソッドを作成して
「このクラスはCategoryモデルに属するんだよ」
と記述してあげる。
→Productモデルの親はCategoryモデルであり、Productモデルの中身の一つである’カテゴリー’カラムのデータは、Categoryテーブルから持ってくる。
→ProductモデルはCategoryモデルに属する!!Category モデル
class Category extends Model { ・・・ public function Products() { return $this->hasMany(Product::class); } }Products メソッドを作成して
「このクラスはProductモデルをたくさん保有しているよ」
と記述してあげる。
→Categoryモデルの子はProductモデルであり、Categoryモデルの中身の一つである’カテゴリー’カラムのデータを持つProductモデルはたくさんある。
→CategoryモデルはたくさんのProductモデルを保有する!!上記二つのテーブル(モデル)間のリレーションを貼りたい場合は、モデル内に上記のような親子関係を考慮した記述を双方に対して記載してあげることでリレーションを張ることができる。
コントローラで取得の方法を確認していく↓
コントローラの記述
public function show($id)//Product $product ? { //Productモデルから$idの商品データを取得 $pd_info = Product::find($id); //上記で定義した商品データからcategory_idを取得できるようになる $pd_category = Category::find($pd_info -> category_id); return view('iteminfo', [ 'pd_info' => $pd_info, 'pd_category' => $pd_category, ]); }Productモデルから$idの商品データを取得し、その商品データからcategory_idを取得できるようになる。
つまり、
Categoryモデルからデータを取得している!ということ・ルーティング prefix の使い方
Prefixとは
直訳すると「接頭語」という意味
ルーティングする上での意味はprefixで指定した文字を最初に設置するっという感じの意味合いになる(url のアクセスに関する話)使用例
Route::group(["prefix"=> 'iteminfo'], function() { Route::get('/{id}', 'ProductController@show'); Route::post('/add', 'ProductController@addCart')->name('addcart'); });解説)
Route::group(["prefix"=> 'iteminfo']Prefix => ‘iteminfo’ とすることで、urlのアクセス部分を統一することができる。
この場合iteminfoというurlにアクセスされるルーティングを一まとめ(グループ)にすることができる。上記のグループの中身である
Route::get('/{id}', 'ProductController@show'); Route::post('/add', 'ProductController@addCart')->name('addcart');この部分は iteminfo 以降のurl部分を記述していて、
一つ目は iteminfo/id にアクセスされた場合のルーティングとなる。・新規プロジェクトの立ち上げ方法(バルスした時に新しいプロジェクトを立ち上げて再開する)
環境にvagrant-dockerを使用しています
最新のリモートをクローンしてくる
[vagrant@local-docker docker-laravel]$ git clone https://github.com・・・・/・・・・.gitクローンが終わればファイルがあるか確認(必要ならmvコマンドで名前を変更)
※ここではlara-dというファイル名で進めます[vagrant@local-docker docker-laravel]$ ls README.md docker-compose.yml lara-d apache-php index.phplara-d に移動
[vagrant@local-docker docker-laravel]$ cd lara-d今どのブランチにいるかを確認
[vagrant@local-docker lara-d]$ git branch * masterここで、最新のリモートdevelop_alphaブランチをpullしてくる(ここではdevelop_alphaというリモートのメインブランチ)
[vagrant@local-docker lara-d]$ git pull origin develop_alpha ・・・・・ ・・・・ ・・ //pullが完了Lara-dでdockerを再起動する
[vagrant@local-docker lara-d]$ docker-compose restart Restarting apache-php ... done Restarting phpmyamin-la ... done Restarting mysql5.7 ... donewebコンテナ内に入る
[vagrant@local-docker lara-d]$ docker-compose exec web bashComposerが入っていないので新しくインストールする
これがおそらく新しくプロジェクトを始める際のに必要な手順?[root@1b08bc3fd4bf html]# composer install ・・・・・ ・・・・ ・・ //composerのインストール完了Git logを確認
→みんなのlogが確認できれば正しくpullできているということ(?)[vagrant@local-docker lara-d]$ git log ・・・・・ ・・・・ ・・ //logが存在していれば成功ブランチを確認→なぜかdevelop_alphaブランチがない
[vagrant@local-docker lara-d]$ git branch * masterdevelop_alphaブランチに移動してみる
[vagrant@local-docker lara-d]$ git checkout develop_alpha D .env.example Branch develop_alpha set up to track remote branch develop_alpha from origin. Switched to a new branch 'develop_alpha'あった!!
[vagrant@local-docker lara-d]$ git branch * develop_alpha master--ここから続きの開発を始めることができる--
- 投稿日:2021-01-24T14:56:27+09:00
谷藤賢一『いきなりはじめるPHPワクワク・ドキドキの入門教室』でPHPを勉強するのをやめた話
チャプター3まで終え、チャプター4『データベース』に進もうとしたら、mampの設定で挫折した。
以前【PHP】超優良入門書『いきなりはじめるPHP』をMAMPで完走するために知っておくべき5つのこと【Mac】
に「xamppではなくmampでも勉強できる」と記載したが、調べてみるとmampはmacbook向けのデータベースでwindowsには向かないと判明した。
【PHP初心者向け】MAMPでMySQLの文字コードを設定する方法(文字化け対策)【Mac】を参考に文字化け対策を行おうにも、コマンドプロンプトでエラーが出て進めない。対策方法はあるらしいが、初学者の私にはどうすればいいか見当もつかない。
というわけで、この本でphpの学習を続けるのは断念した。
- 投稿日:2021-01-24T12:43:41+09:00
DockerでPHP環境を作る(mac)
はじめに
勤め先でもPHPを使っており自宅でPHPを勉強するために、ローカルでPHP開発環境を整えることにしました。
MAMP(マンプ)でも良いかなと思いましたが、せっかくなのでDockerで作ってみます。
(開発中に色々詰まってしまったところがあるので、備忘録がわりのメモです。)手順
- Dockerによる環境構築
- ファイル・ディレクトリの準備
- 各ファイルの作成
- コンテナを起動
- サイトにアクセス
1. Dockerによる環境構築
Dockerを使うには、「Docker for Mac」のインストールが必要です。
Qitaに素敵な記事がたくさんあるので、ここでの説明は省略します。今回はDockerで以下のコンテナを使います。
- nginx
- PHP
- MySQL
- PHPMyAdmin
使用するコンテナが複数あるので、今回は「Docker Compose」を使って環境を作っていきます。
2. ディレクトリ・ファイルの準備
Dockerを起動する場所を作成しましょう。
まずはフォルダを1つ用意し、次のようなファイル構造となるようにしてください。
用意するフォルダは何でも良いのですが、今回は「php-test」という名前で作成します。php-test ├── docker-compose.yml ├── mysql │ └── data ├── nginx │ └── nginx.conf ├── php │ ├── Dockerfile │ └── php.ini └── www └── html └── index.php3. 各ファイルの作成
用意したファイルの中身を作成していきます。
中身を作成するファイルは、docker-compose.yml
、nginx.conf
、Dockerfile
、php.ini
、index.php
の5つです。docker-compose.yml
version: '3' services: nginx: image: nginx:latest ports: - 8080:80 volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf - ./www/html:/var/www/html depends_on: - php php: build: ./php volumes: - ./www/html:/var/www/html depends_on: - db db: image: mysql:5.7 ports: - 13306:3306 volumes: - ./mysql/data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret phpmyadmin: image: phpmyadmin/phpmyadmin:latest ports: - 8888:80 depends_on: - dbnginx.conf
server { listen 80; server_name _; root /var/www/html; index index.php index.html; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }Dockerfile
FROM php:7.2-fpm COPY php.ini /usr/local/etc/php/ RUN docker-php-ext-install pdo_mysqlphp.ini
date.timezone = "Asia/Tokyo"index.php
設定情報を確認するために
phpinfo();
としていますが、なんでもいいです。<?php phpinfo(); ?>4. コンテナを起動
いよいよコンテナ起動です。
ターミナルを開き、docker-compose.yml
があるフォルダ(今回はphp-test)に移動します。下記コマンドで、php-testフォルダに移動。
cd php-test下記コマンドで、コンテナを起動。
docker-compose up -d以下のような記述がターミナル内に表示されたら、起動は成功です。
Creating php_01_db_1 ... done Creating php_01_phpmyadmin_1 ... done Creating php_01_php_1 ... done Creating php_01_nginx_1 ... doneなお下記コマンドで、コンテナを停止できます。
docker-compose stop5. サイトにアクセス
最後にサイトにアクセスします。
それぞれ下記画像のような画面が表示されたら、成功です。
お疲れ様でした。Webサイト:http://localhost:8080/
ユーザー名:root
パスワード:secret以上です。
最後までお読みいただき、ありがとうございました。
お世話になったサイト
- [PHP]DockerでPHP, MySQL(MariaDB), nginxを使ったローカル開発環境を構築する
- Docker Composeでphpでmysqlにアクセスする
- docker-composeでPHPとMySQLを連携させてみる
- Docker ドキュメント
【補足】Qitaに投稿されているDockerインストール記事
下記の中から自分に合いそうなものを1つ選んで、進めてみると良いと思います。
- 投稿日:2021-01-24T12:29:33+09:00
エンジニア未経験がWordPressでWEBアプリを制作する際につまずいたこと
まず初めにどのようなWEBアプリを作ったのか
「AboutMyself」という、プロフィール専門SNSを製作しました。
※内容については、こちらの記事を参照。「AboutMyself」を製作する上でつまずいたこと
SNSを製作する上でのプラグインの選択について困った
→日本語の説明ブログなどもかなり投稿されていますので、これに関しては「BuddyPress」一択で大丈夫だと思います。ログイン・登録画面で自分のサイトのUIではなく、WordPressのログイン画面に遷移してしまう。
→これもプラグインがおすすめです。「Theme My Login」を入れることで、自分のサイトのUIにあったログイン・登録画面に遷移されます。ログアウト後の画面にログインをしないと見れないメニューが表示される
→以下のスクショのようにログアウト後の画面に、ログインをしなければ見れない画面が出てきてしまいました。(本来「グループ作成」メニューはログアウト後には必要ない)
こちらもプラグインを導入しました。「If Menu」というログイン後とログアウト後のメニュー画面の表示を分けられる優れものです!今回WordPressを使ってわかったこと
WordPressを使用することで、プログラミング未経験者でも簡単にWEBアプリが作成できます!プラグインというのは本当に便利な機能ですよね。適宜、欲しい機能にあったプラグインを調べて導入することである程度自由なサイトを構築できます!
最後に「AboutMyself」のご利用もお願いいたします!
- 投稿日:2021-01-24T11:31:43+09:00
【Laravel】テーブル名が長い時に、Laravel7から導入された外部キー制約をつけるマイグレーションエイリアスを使う方法
久しぶりのQiitaへの投稿です。
未経験からエンジニアに転職をして、2年目に突入したバックエンドエンジニアです。
DBに外部キー制約を追加をしようと思い、Laravel7から使えるエイリアスでmigrationファイルを作成していました。
ただ、テーブル名が長い時にハマってしまい、できる人には当たり前すぎる内容かもしれませんが、振り返りの意味も込めて投稿します。開発環境
- 言語:PHP7.4.8
- フレームワーク:Laravel7.28.3
- DB:MySQL8.0.22
テーブル名が短い時
目標のテーブル構造
公式ガイドでもよく使われるような下記のようなテーブルを作り、postsテーブルのuser_idに外部キー制約をかけることを目指します。
Laravel7より前の時の記法
Laravel7より前のバージョンで外部キー制約をつけるためには、下記のようにmigrationファイルを作成をしていました。
一度user_id
のカラムを作成してから別の行で外部キー制約をつけています。Schema::create('posts', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('user_id'); $table->foreign('user_id')->references('id')->on('users'); });そんなに難しくもないですが、少しだけ面倒です。
Laravel7以降で使えるエイリアスを使用
そこでLaravel7以降では下記のようなエイリアスができ、
foreignId
とconstrained()
を使えば一行でも外部キー制約をかけることができるようになりました。
短くて楽ですね。Schema::create('posts', function (Blueprint $table) { $table->id(); $table->foreignId('user_id')->constrained(); $table->timestamps(); });テーブル名が長い時
目標のテーブル構造
問題のパターンです。下記のようなテーブルを想定して試してみます。
名前は適当に僕が好きなスポーツからとってきましたが、とりあえず2つのテーブル名が長く文字数の合計が一定数を超えると同じ現象になります。Laravel7以降で使えるエイリアスを使用
せっかく新しい記法があるということなので、
foreignId
を使った新しいエイリアスを使ってやってみます。Schema::create('national_basketball_association_players', function (Blueprint $table) { $table->id(); $table->string('name'); $table->foreignId('national_basketball_association_team_id')->constrained(); $table->timestamps(); });キー名が長すぎるようで下記のようなエラーが出てしまいました。
SQLSTATE[42000]: Syntax error or access violation: 1059 Identifier name 'national_basketball_association_players_national_basketball_association_team_id_foreign' is too long (SQL: alter table `national_basketball_association_players` add constraint `national_basketball_association_players_national_basketball_association_team_id_foreign` foreign key (`national_basketball_association_team_id`) references `national_basketball_association_teams` (`id`))通常であれば、Laravelのスキームビルダの制約命名規則に従い、自動的に外部キー制約の名前は変換されるため、外部キー制約名は下記のようになります。
(接続元テーブル名)_(外部キー名)_foreign
しかし、今回この命名規則に当てはめようとすると、
national_basketball_association_players_national_basketball_association_team_id_foreign
という名前になりますが、これは文字数が長すぎるということでエラーになってしまいました。Laravel7以降で使えるエイリアスを使用(nameでキー名変更)
同じようなことが他の制約を作る時でも起こっていたのを思い出します。
name
メソッドを使えば直せたような気がするのでname
メソッドを使って試してみました。
外部キー制約名は省略した、basketball_players_team_id_foreign
を設定します。Schema::create('national_basketball_association_players', function (Blueprint $table) { $table->id(); $table->string('name'); $table->foreignId('national_basketball_association_team_id')->constrained()->name('basketball_players_team_id_foreign'); $table->timestamps(); });先程と違い、今度はエラーも起こらず、migrationファイルが無事に通りました。
念のためにdatabaseを確認してみます。外部キー制約がついていません。。。
多分routeを作成する時に使うname
メソッドと勘違いしていたのですが、ここで結構ハマってしまいました。migration関連でnameメソッドは用意されていなさそうでした。
エイリアスメソッドのコードを確認
改めて今回のエイリアスの
foreignId
メソッドを確認してみます。public function foreignId($column) { $this->columns[] = $column = new ForeignIdColumnDefinition($this, [ 'type' => 'bigInteger', 'name' => $column, 'autoIncrement' => false, 'unsigned' => true, ]); return $column; }引数がカラム名のみで1つしか受け付けていないので、キー名を短くして渡そうとしても無理そうです。
また、
foreignId
の後に使っているconstrainedも確認してみます。public function constrained($table = null, $column = 'id') { return $this->references($column)->on($table ?? Str::plural(Str::beforeLast($this->name, '_'.$column))); }こちらも外部キー制約名を渡す引数がなく、無理そうです。
結果:Laravel7以降で使えるエイリアスを使用(indexでキー名変更)
下記のように
index
メソッドを使って、外部キー名を指定するとうまくいきました。Schema::create('national_basketball_association_players', function (Blueprint $table) { $table->id(); $table->string('name'); $table->foreignId('national_basketball_association_team_id')->constrained()->index('basketball_players_team_id_foreign'); $table->timestamps(); });公式ガイドを見てみると
index
メソッドは「基本的なインデックス追加」とだけ書いてありましたが、外部キー制約の名前を作成をする際にも使えるようです。
uniqueキー作るときは、第2引数にインデックスキー名指定できるのに対して、外部キー制約の場合はindex
メソッドを使わないといけなさそうなので書き方が結構違いますね。https://readouble.com/laravel/7.x/ja/migrations.html
※何か誤解していたり、他にいい方法があれば教えていただけると助かります!!!
Laravel7より前の時の記法でやる方法
もちろん元々使っていた記法を使って、
foreign
メソッドの中の第2引数に外部キー制約名を指定してもうまくいきます。
このやり方は元々やったことあったのですが、ハマるくらいなら最初からこっち使っておけばよかったなと思いました、、、Schema::create('national_basketball_association_players', function (Blueprint $table) { $table->id(); $table->string('name'); $table->unsignedBigInteger('national_basketball_association_team_id'); $table->foreign('national_basketball_association_team_id', 'basketball_players_team_id_foreign')->references('id')->on('national_basketball_association_teams'); $table->timestamps(); });感想
チュートリアルで使うようなusersとかpostsとかのテーブルと違い、実務ではテーブル名が長くなるケースは命名規則によりけりだと思いますが、結構発生しそうなイメージなので意外と困ることもあるかなと思います。
また、今回少し深く調べてみて、フレームワークのコードをより深くみるようにしたのはよかったなと思いました。
それにしても
name
メソッドを使ったときに何故かmigrationファイル通るのに外部キー制約がついていないのは結構たちが悪かったです。。。
- 投稿日:2021-01-24T01:47:11+09:00
PHP ログイン認証の作成手順⑤ 〜ログイン機能作成②とセッションハイジャック〜
今回は
・emailと一致するユーザ検索
・passwordが一致するか検証
・ユーザ情報をセッションに格納してログイン
を実装するパスワード照会の方法
ユーザ入力とDBの値を照会
しかし、パスワードはハッシュ化されている→照会できる関数がある
password_verify(パス、ハッシュ)
パスワードがハッシュにマッチするかを判定する
マッチしたらtrue、しなかったらfalseを返すセッションハイジャック対策
セッションIDを盗まれて、なりすましをされること
対策:セッションIDを再作成する手順
ログインロジック作成
前回までに作成したUserLogicクラスの中にログイン専用のメソッドを作成していく。
login
メソッドとする。
top.phpがログインフォーム後のページだから、ここでログインの処理を記述する。top.php<?php require_once('../classes/UserLogic.php'); session_start(); // エラーメッセージ $err = []; // バリデーション if(!$email = filter_input(INPUT_POST, 'email')){ $err['email'] = 'メールアドレスを記入してください'; } if(!$password = filter_input(INPUT_POST, 'password')){ $err['password'] = 'パスワードを記入してください'; } if(count($err) > 0){ // エラーがあった場合は戻す $_SESSION = $err; header('Location: login.php'); return; } // ログイン成功時の処理 $result = UserLogic::login($email, $password); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ユーザ登録完了画面</title> </head> <body> <?php if (count($err) > 0) : ?> <!-- エラーがある場合にforeachで該当エラーを表示させる --> <?php foreach($err as $e) : ?> <p><?php echo $e ?></p> <?php endforeach; ?> <!-- $err配列に何もない=エラーがない から完了画面を表示させる --> <?php else: ?> <p>ユーザー登録が完了しました。</p> <?php endif ; ?> <a href="login.php">戻る</a> </body> </html>
$result = UserLogic::login($email, $password);
の部分。そして、その
login
メソッドを以下の通りに記述する。UserLogic.php/** * ログイン処理 * @param string $email * @param string $password * @return bool $result */ public static function login($email, $password) { // 結果 $result = false; // ユーザをemailから検索して取得 $user = self::getUserByEmail($email); }emailからユーザ取得ロジック作成
loginメソッドとは別に、emailの照会のためのメソッドを作成する。
UserLogic.php/** * ログイン処理 * @param string $email * @param string $password * @return bool $result */ public static function login($email, $password) { // 結果 $result = false; // ユーザをemailから検索して取得 $user = self::getUserByEmail($email); return $user; } /** * emailからユーザを取得 * @param string $email * @return array|bool $user|false */ public static function getUserByEmail($email) { // SQLの準備 // SQLの実行 // SQLの結果を返す $sql = 'SELECT * FROM users WHERE email = ?'; // ユーザデータを配列に入れる $arr = []; $arr[] = $email; try{ $stmt = connect()->prepare($sql); $stmt->execute($arr); //SQLの結果を返す $user = $stmt->fetch(); return $user; }catch(\Exception $e){ return false; } }パスワード照会とセッションハイジャック対策
- 投稿日:2021-01-24T01:07:41+09:00
PHP ログイン認証の作成手順④ 〜ログイン機能作成①とセッションとキャッシュ〜
ログイン機能の作成の流れ
①emailとpasswordを受け取る
②emailと一致するユーザ検索
③passwordが一致するか検証
④ユーザ情報をセッションに格納してログインsessionとは
開始から終了までの期間のこと。
1ユーザのログインからログアウトまでの行動は1セッション。
1セッションはセッションIDで管理する。通信(HTTP)はユーザを識別することができない。
そのため、識別するためにセッションが必要になる。
セッションIDを管理するのはCookie。CookieはセッションIDをブラウザに保存する。
ユーザがログインすると、サーバ側からセッションIDが生成されてブラウザに送られ、Cookieに保存する。
そして、ログイン中は常にセッションIDを送って、サーバ側でユーザを識別してもらう。sessionの使い方
関数
session_start()
→Cookie(ブラウザ)にセッションIDを入れる
→セッションファイルが生成される
→セッションファイルに自由に値を保存可能(現場ではセッションファイルを管理する用のデータベースを作ることが多い)
session_destroy()
→セッションファイルを削除するグローバル変数
$_SESSION
→セッションへデータを連想配列で保存ログインフォーム作成
login.php<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ログイン画面</title> </head> <body> <h2>ログインフォーム</h2> <form action="top.php" method="POST"> <p> <label for="email">メールアドレス:</label> <input type="email" name="email"> </p> <p> <label for="password">パスワード:</label> <input type="password" name="password"> </p> <p> <input type="submit" value="ログイン"> </p> </form> <a href="signup_form.php">新規登録はこちら</a> </body> </html>バリデーションの作成
login.phpのsubmitでtop.phpに移動するのだが、移動した時のバリデーションを作成する
top.php<?php require_once('../classes/UserLogic.php'); // エラーメッセージ $err = []; // バリデーション if(!$email = filter_input(INPUT_POST, 'email')){ $err[] = 'メールアドレスを記入してください'; } if(!$password = filter_input(INPUT_POST, 'password')){ $err[] = 'パスワードを記入してください'; } if(count($err) === 0){ // ログインする処理 echo 'ログインしました!'; } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ユーザ登録完了画面</title> </head> <body> <?php if (count($err) > 0) : ?> <!-- エラーがある場合にforeachで該当エラーを表示させる --> <?php foreach($err as $e) : ?> <p><?php echo $e ?></p> <?php endforeach; ?> <!-- $err配列に何もない=エラーがない から完了画面を表示させる --> <?php else: ?> <p>ユーザー登録が完了しました。</p> <?php endif ; ?> <a href="login.php">戻る</a> </body> </html>sessionでバリデーションを出す
上記のやり方だと、top.php上でのエラー表示になる。
本来はlogin.phpでエラー表示をさせる。
そのためには、
①logion.php → ログインフォームに入力して、ログインボタンを押す
②top.phpに移動して送られたデータのバリデーション行う
③header関数で強制的にlogin.phpへ戻して、sessionのデータを下にエラーを表示させる
という流れを作成する保存されたsessionのデータはブラウザからも確認できるし、MAMP/tmp/phpフォルダの中にsessionファイルが作られており、その中にsessionの値が記述されている。
$_SESSION変数には
連想配列
として値が格納されることになる。top.php<?php require_once('../classes/UserLogic.php'); session_start(); // エラーメッセージ $err = []; // バリデーション if(!$email = filter_input(INPUT_POST, 'email')){ $err['email'] = 'メールアドレスを記入してください'; } if(!$password = filter_input(INPUT_POST, 'password')){ $err['password'] = 'パスワードを記入してください'; } if(count($err) > 0){ // エラーがあった場合は戻す $_SESSION = $err; header('Location: login.php'); return; } // ログイン成功時の処理 echo 'ログインしました!'; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ユーザ登録完了画面</title> </head> <body> <?php if (count($err) > 0) : ?> <!-- エラーがある場合にforeachで該当エラーを表示させる --> <?php foreach($err as $e) : ?> <p><?php echo $e ?></p> <?php endforeach; ?> <!-- $err配列に何もない=エラーがない から完了画面を表示させる --> <?php else: ?> <p>ユーザー登録が完了しました。</p> <?php endif ; ?> <a href="login.php">戻る</a> </body> </html>login.php<?php session_start(); $err = $_SESSION; // セッションを消す $_SESSION = array(); session_destroy(); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ログイン画面</title> </head> <body> <h2>ログインフォーム</h2> <form action="top.php" method="POST"> <p> <label for="email">メールアドレス:</label> <input type="email" name="email"> <?php if(isset($err['email'])) : ?> <p><?php echo $err['email']; ?></p> <?php endif; ?> </p> <p> <label for="password">パスワード:</label> <input type="password" name="password"> <?php if(isset($err['password'])) : ?> <p><?php echo $err['password']; ?></p> <?php endif; ?> </p> <p> <input type="submit" value="ログイン"> </p> </form> <a href="signup_form.php">新規登録はこちら</a> </body> </html>
- 投稿日:2021-01-24T00:08:16+09:00
エンジニア未経験がWordPressを使ってWEBアプリを作ってみた
今回製作したWEBアプリについて
今回作成したWEBアプリは「AboutMyself」。プロフィールを質問形式で記載していくSNSのようなものです。15年程前に流行った「前略プロフ」をイメージしていただければ良いかと思います。
1. 開発経緯
インターンのテレワークをするなかで、新しく入ってきた人のこと(趣味や経歴)についてわからずなかなかコミュニケーションが取りづらいと思った。また、気難しいと思っていた上司の趣味がわかった途端、急に親近感が沸いた。これらのことから、ある程度事前に相手のことをわかっていればコミュニケーションが円滑になるのではないかと考え、「AboutMyself」を作ることになった。
2. 「AboutMyself」の想定利用ケース
人と深く関わりたい人の場合
* 人と会う機会が減ったなかで、ユニークなプロフィールを通して親交を深めたい。
* プロフィールを通して相手のことを知りたい。
* プロフィールを通して初対面の人と仲良くなるきっかけを作りたい。そんなに深く関わりたくない人の場合
* プライベートで利用しているLINEやFacebookなどを教え合う仲ではないけど連絡は取りたい。
* グループも作成できるので、何かについてざっくばらんに議論や質問などをしたい。3. 開発工程
- お名前.comからドメインを取得し、同時にレンタルサーバーも申し込み。
- レンタルサーバーのコントロールパネルからWordPressをインストール
- SNS作成にはもってこいのプラグイン「BuddyPress」を使用。テーマは「GeneratePress」を使用。
- その他ログイン、ログアウトに関するプラグインを使用。
- ある程度機能が備わったらデザインの微調整をし、自分でパソコン3台、スマホ2台を使いテスト。
- テストに問題がなければ、友人に使用してもらいフィードバックをもらう
- フィードバックを元に完成段階まで完了。 ここまで5日ほど。
4. 今後の「AboutMyself」について
今後は、多くの人に利用してもらうようマーケティングに重きを置き、フィードバックを元に改善していく予定。この記事をみた方もぜひ、アクセス、ユーザー登録していただきたいです!お願いします!
5. 最後に
今はユーザー0ですが、何か進捗があればGoogle Analyticsの画像と共に報告できればなと思います。
初めての執筆なので、めちゃくちゃな文章でしたが最後までご覧いただきありがとうございました!
- 投稿日:2021-01-24T00:08:16+09:00
開発未経験がWordPressを使ってWEBアプリを作ってみた
今回製作したWEBアプリについて
今回作成したWEBアプリは「AboutMyself」。プロフィールを質問形式で記載していくSNSのようなものです。15年程前に流行った「前略プロフ」をイメージしていただければ良いかと思います。
1. 開発経緯
インターンのテレワークをするなかで、新しく入ってきた人のこと(趣味や経歴)についてわからずなかなかコミュニケーションが取りづらいと思った。また、気難しいと思っていた上司の趣味がわかった途端、急に親近感が沸いた。これらのことから、ある程度事前に相手のことをわかっていればコミュニケーションが円滑になるのではないかと考え、「AboutMyself」を作ることになった。
2. 「AboutMyself」の想定利用ケース
人と深く関わりたい人の場合
* 人と会う機会が減ったなかで、ユニークなプロフィールを通して親交を深めたい。
* プロフィールを通して相手のことを知りたい。
* プロフィールを通して初対面の人と仲良くなるきっかけを作りたい。そんなに深く関わりたくない人の場合
* プライベートで利用しているLINEやFacebookなどを教え合う仲ではないけど連絡は取りたい。
* グループも作成できるので、何かについてざっくばらんに議論や質問などをしたい。3. 開発工程
- お名前.comからドメインを取得し、同時にレンタルサーバーも申し込み。
- レンタルサーバーのコントロールパネルからWordPressをインストール
- SNS作成にはもってこいのプラグイン「BuddyPress」を使用。テーマは「GeneratePress」を使用。
- その他ログイン、ログアウトに関するプラグインを使用。
- ある程度機能が備わったらデザインの微調整をし、自分でパソコン3台、スマホ2台を使いテスト。
- テストに問題がなければ、友人に使用してもらいフィードバックをもらう
- フィードバックを元に完成段階まで完了。 ここまで5日ほど。
4. 今後の「AboutMyself」について
今後は、多くの人に利用してもらうようマーケティングに重きを置き、フィードバックを元に改善していく予定。この記事をみた方もぜひ、アクセス、ユーザー登録していただきたいです!お願いします!
5. 最後に
今はユーザー0ですが、何か進捗があればGoogle Analyticsの画像と共に報告できればなと思います。
初めての執筆なので、めちゃくちゃな文章でしたが最後までご覧いただきありがとうございました!