web系エンジニアを目指し、PHPを学習している初学者です。
就職活動の武器とすべく着手した、webアプリ(ポートフォリオ)作成。
MENTAを利用し、本格的に学習開始してから4ヶ月で、デプロイに漕ぎ着けました!
派手さもモダンな感じもないですが、バリデーションや不正アクセス防止など、地味な部分を丁寧にコーディングしました。
採用担当の方、同じエンジニアを目指す初学者の方、エンジニアを目指そうか迷っている方の目に留まれば幸いです。
#記事の目的
- 面接に備えた補助資料として
- 同じ境遇の方の参考(になれば幸い)
作成した【内定者懇親サイト】について、
- カタログ
- 仕様書
- 気を付けた点
- 後悔している点
- (追記)公開後、改善した点
をまとめました。
#1.カタログ
作成したサイトの紹介。
##〜内定者懇親サイト〜
内定承諾してから、入社するまでの期間。
「他の内定者は何人位?年齢は?どんな人?」
「内定式で会う前に知って欲しい・知っておきたい、話のネタを仕込んでおきたい。」
そんな願いを叶える、簡易的な懇親サイト。
###概要
####ユーザー種類
- 管理者
- メンバー
####機能
- 管理者|メンバー全員の編集、削除。他の管理者の新規登録、編集、削除
- メンバー|自身の登録、編集、削除。他のメンバー 一覧、詳細の閲覧
####開発環境
MAMPでローカル環境構築。
VScodeでコーディング→Githubでコード管理→herokuでデプロイ
- PHP 7.3.11
- HTML/CSS、Bootstrap4
- MySQL 5.7.26
#2.仕様書
サイトの設計図です。
##機能一覧
- メンバーのCRUD機能(新規登録、プロフィール編集、削除)
- 管理者のCRUD機能
- 管理者権限付与(メンバーの編集、削除)
- メンバー 一覧表示機能
- メンバー 詳細表示機能
- レスポンシブ対応(Bootstrap)
##DB
クリエイト文
- jinjies
CREATE TABLE `jinjies` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(100) NOT NULL,
`password` varchar(255) NOT NULL,
`last_name` varchar(100) NOT NULL,
`first_name` varchar(100) NOT NULL,
`created` datetime NOT NULL,
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4
- members
CREATE TABLE `members` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(100) NOT NULL,
`password` varchar(255) NOT NULL,
`created` datetime NOT NULL,
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4
- members_info
CREATE TABLE `members_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_id` int(10) NOT NULL,
`last_name` varchar(100) NOT NULL,
`first_name` varchar(100) NOT NULL,
`nick_name` varchar(100) NOT NULL,
`school` char(10) NOT NULL,
`prefectures_id` int(10) NOT NULL,
`message` varchar(240) NOT NULL,
`icon` varchar(120) DEFAULT NULL,
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4
- prefectures
CREATE TABLE `prefectures` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pre_name` char(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8mb4
- members_interesting
CREATE TABLE `members_interesting` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_id` int(11) NOT NULL,
`interesting1_id` int(11) NOT NULL,
`interesting2_id` int(11) NOT NULL,
`interesting3_id` int(11) NOT NULL,
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4
- interesting
CREATE TABLE `interesting` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`intere_name` char(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4
##ER図
データベースの設計図。リレーションは慎重に決める。
##ステートチャート図
##画面遷移図
これらは無料で使えるLucidchartを利用し、作成しました。
#3.気を付けた点
##基本スキルを示す
- フレームワークを使わない、スクラッチ開発(フロント部分はBootstrap使用)
- CRUD
- 一通りの入力形式(テキストボックス、チェックボックス、ラジオボタン、ファイルのアップロード)実装
- 各項目に対するバリデーションを丁寧に
- パスワードのハッシュ化 (
PASSWORD_DEFAULT
使用) - 不正アクセス防止
##ログイン
- メンバーログインと新規登録、管理者ログインを1つのログイン画面にまとめ、
login_check.php
にて、移行画面を変更した - バリデーションはメソッドを呼び出し、返り値はboolean型とした
class Login
{
public function __construct()
{
2.validation
$email_validation = new emailValidation();
$is_email = $email_validation->isEmail($this->clean['email']);
//パスワードも同様に
//validationエラーなら、エラーメッセージを取得し、ログイン画面へ戻る
}
public function main()
{
1.DB接続し、メンバーテーブル・管理者テーブルの情報と、入力された情報を照合
メール 一致なし =>新規登録画面へ
メール、パスワード
メンバーと一致 =>メンバーログイン
管理者と一致 =>管理者ログイン
メール 一致、パスワード 一致なし =>エラーメッセージを取得し、ログイン画面へ戻る
}
}
$login = new Login();
$login->main();
-
入力値を
htmlspecialchars
処理する為に、hsc.php
にデータを渡すが、配列(3つ選択させるチェックボックス)も同様の処理が出来るようにした
class Hsc
{
public static function clean($posts)
{
foreach ($posts as $post => $value) {
3.配列の場合
if(is_array($value)) {
foreach($value as $key => $val) {
$clean[$post][$key] = htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
}
} else {
$clean[$post] = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
}
return $clean;
}
}
##アラート表示
$status
で、前画面での処理内容を表示した
<?php
if(!empty($status)):
?>
<div class="alert alert-success" role="alert">
<?php
switch ($status) {
case 'login':
echo 'ログイン成功しました。';
break;
case 'new':
echo '新規登録が完了しました。';
break;
case 'edit':
echo '編集が完了しました。';
break;
case 'delete':
echo '削除が完了しました。';
break;
}
?>
</div>
<?php endif; ?>
#4.後悔していること
- 開発履歴を、Githubのブランチやissuesを使用して残せば良かった(ずっとmasterにpushし、コメントも「third commit」など無意味なものばかり^^;)
- 自身の困りごとを元に、実用性の高いものにすれば良かった
- クラスをあまり活用出来なかった
- Twitter的な交流(コメント、イイね!)がない
- ソートがない
- 変数の付け方、仕様書を定めずに着手してしまった
- 後から「アラート付けよう!」など追加していったので、無駄な修正作業や、抜け・漏れで新たなエラーを生み出してしまった
以上です。
Twitter的な機能やソートについては、追加実装するかもしれませんが、ひとまずはこれでデプロイ。
コーディングして画面が出来上がってからは、夢中で作成することが出来ました。
ぜひ、サイトにアクセスしてみてください!
https://github.com/kunitani920/BullentinBoard
#5.(追記)公開後、改善した点
メンターさんを中心に改善案を頂き、一部アップデートしました。
その際、自身で感じた「後悔していること」も一部リカバリー出来たので紹介します。
##PDOのトランザクション
DBへの新規登録、編集、削除時にトランザクションを追加。
<?php
try {
//DB接続
$db = new Db();
$dbh = $db->dbconnect();
// トランザクション開始
$dbh->beginTransaction();
新規登録、編集、削除処理
// コミット
$dbh->commit();
} catch(PDOException $e) {
// ロールバック
$dbh->rollBack();
// エラーメッセージ出力
echo $e->getMessage();
die();
}
$dbh = null;
}
期待できる効果
- DB同時アクセスによるデータの行き違い防止
- 処理速度の向上
##コンフィグ
コンフィグディレクトリとdatabase.phpファイルを作成し、DB接続情報を移動した。
<?php
$db = parse_url($_SERVER['CLEARDB_DATABASE_URL']);
$db['dbname'] = ltrim($db['path'], '/');
return [
'dsn' => "mysql:host={$db['host']};dbname={$db['dbname']};charset=utf8",
'user' => $db['user'],
'password' => $db['pass'],
'options' => array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY =>true,
)
];
?>
<?php
class Db
{
public function dbconnect() {
try {
$db = include(__DIR__ . '/config/database.php');
$dbh = new PDO($db['dsn'], $db['user'], $db['password'], $db['options']);
} catch(PDOException $e) {
echo 'DB接続エラー:' . $e->getMessage();
}
return $dbh;
}
}
期待できる効果
- 管理者の負担軽減
- 人的ミスの削減
##DB定義とクリエイト文
DB定義を、GithubのREADMEに追加。
DBクリエイト文を、この記事の2.仕様書
に追加。
##issues、ブランチ活用(4.後悔していることより)
改善項目をissuesに設定。
Millestonesで期限設定も体験し、機能を少し把握できた。
修正で間違えても戻れるよう、新しいブランチを切って修正作業。
ブランチ名がわかりづらく反省。しかし、コミットメッセージはマシになったと思う。
##DB再設計
「1対1関係なのに、なぜテーブルを分けるのか?」
複数の方にご指摘いただいた。
作成当時、
「ID(メール、パスワード)とプロフィール(メッセージなど)を分けて管理したいな」
「3つ選択の趣味、それぞれにIDふるのは変かな?いや、でもそうしないと実現できない」
など考えがまとまらない中
「とりあえず、作ろう!」
と走ってしまった結果です。