WEBアプリ開発を少しやってみたかったので独学で
持ち得る知識をフル活用してみた。
MacBook Air(M1)にて環境構築〜ログイン機能が完成するまでの作業メモ
<?php
echo "Hello, World!";
?>
version: '3.8'
services:
php:
image: arm64v8/php:8.2-apache
ports:
- "8888:80"
volumes:
- ./src:/var/www/html
networks:
- app-network
mysql:
image: mysql:5.7
platform: linux/amd64
container_name: mysql-container
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: testdb
MYSQL_USER: user
MYSQL_PASSWORD: password
ports:
- "3306:3306"
networks:
- app-network
networks:
app-network:
driver: bridge
Error response from daemon: Conflict. The container name "/mysql-container" is already in use by container "ab40002890513d6c82e122a8bb052a1de9875a82eff662fdac7c9743980bce56". You have to remove (or rename) that container to be able to reuse that name.
このエラーは、すでに同じ名前のコンテナが存在しているため、新しいコンテナを作成できないことが原因です。この問題を解決するためには、既存のコンテナを削除するか、コンテナの名前を変更する必要があります。
container_name: php-mysql-container
irochi@irochi-macbook src % docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb871d6f5c1f php:8.2-apache "docker-php-entrypoi…" 33 seconds ago Up 31 seconds 0.0.0.0:8888->80/tcp php-docker-php-1
8b3b6d7fcd16 mysql:5.7 "docker-entrypoint.s…" 33 seconds ago Up 31 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp php-mysql-container
irochi@irochi-macbook src %
<?php
$servername = "php-mysql-container";
$username = "user";
$password = "password";
$dbname = "testdb";
// MySQL データベースへの接続
$conn = new mysqli($servername, $username, $password, $dbname);
// 接続をチェック
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
echo "Connected successfully";
// 簡単なクエリの実行
$sql = "SELECT 1";
$result = $conn->query($sql);
if ($result) {
echo "Query successful.";
} else {
echo "Error: " . $conn->error;
}
// 接続を閉じる
$conn->close();
?>
/Users/irochi/php-docker
├── docker-compose.yml
├── Dockerfile
├── mysql-init/
│ └── init.sql
└── src/
├── index.php
└── db_test.php
CREATE DATABASE IF NOT EXISTS todoapp;
USE todoapp;
CREATE TABLE IF NOT EXISTS tasks (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO tasks (title, description) VALUES
('Sample Task 1', 'This is the first sample task'),
('Sample Task 2', 'This is the second sample task')
version: '3.8'
services:
php:
build: .
ports:
- "8888:80"
volumes:
- ./src:/var/www/html
networks:
- app-network
mysql:
image: mysql:5.7
platform: linux/amd64
container_name: php-mysql-container
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: testdb
MYSQL_USER: user
MYSQL_PASSWORD: password
ports:
- "3306:3306"
volumes:
- ./mysql-init:/docker-entrypoint-initdb.d // New!
networks:
- app-network
networks:
app-network:
driver: bridge
docker exec -it php-mysql-container mysql -u user -p
irochi@irochi-macbook src % docker exec -it php-mysql-container mysql -u user -p
Enter password: ←passwordと入力
ERROR 1044 (42000): Access denied for user 'user'@'%' to database 'todoapp'
init.sql
GRANT ALL PRIVILEGES ON todoapp.* TO 'user'@'%'; -- 権限付与
<?php
// データベース接続情報
$servername = "php-mysql-container"; // MySQLコンテナのホスト名
$username = "user"; // MySQLのユーザー名
$password = "password"; // MySQLのパスワード
$dbname = "todoapp"; // 使用するデータベース名
// MySQL データベースへの接続
$conn = new mysqli($servername, $username, $password, $dbname);
// 接続をチェック
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error); // 接続エラーの場合、エラーメッセージを表示してスクリプトを終了
}
// SQLクエリを準備
$sql = "SELECT id, title, description, created_at FROM tasks";
// クエリを実行
$result = $conn->query($sql);
// 結果を確認
if ($result->num_rows > 0) {
// データが存在する場合、各行を出力
echo "<h1>ToDo List</h1>";
echo "<table border='1'>";
echo "<tr><th>ID</th><th>Title</th><th>Description</th><th>Created At</th></tr>";
while($row = $result->fetch_assoc()) {
echo "<tr>";
echo "<td>" . $row["id"] . "</td>";
echo "<td>" . $row["title"] . "</td>";
echo "<td>" . $row["description"] . "</td>";
echo "<td>" . $row["created_at"] . "</td>";
echo "</tr>";
}
echo "</table>";
} else {
// データが存在しない場合、メッセージを表示
echo "No tasks found";
}
// 接続を閉じる
$conn->close();
?>
データベースから値の取得を完了
ログイン機能を作ってみる
CREATE DATABASE IF NOT EXISTS todoapp;
GRANT ALL PRIVILEGES ON todoapp.* TO 'user'@'%';
USE todoapp;
CREATE TABLE IF NOT EXISTS tasks (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO tasks (title, description) VALUES
('Sample Task 1', 'This is the first sample task'),
('Sample Task 2', 'This is the second sample task');
CREATE TABLE IF NOT EXISTS User (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
mail_address VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL
);
INSERT INTO User (name, mail_address, password) VALUES
('佐藤 一郎', 'sato@example.com', MD5('password123')),
('木下 たかし', 'kinoshita@example.com', MD5('password456'));
ログイン画面
<!DOCTYPE html>
<html>
<head>
<title>Todoログイン</title>
</head>
<body>
<h2>ログイン</h2>
<form method="post" action="authenticate.php">
<label for="mail_address">メールアドレス:</label>
<input type="email" name="mail_address" required><br><br>
<label for="password">パスワード:</label>
<input type="password" name="password" required><br><br>
<input type="submit" value="Login">
</form>
</body>
</html>
ログイン認証
<?php
session_start();
// データベース接続情報
$servername = "php-mysql-container";
$username = "user";
$password = "password";
$dbname = "todoapp";
// MySQL データベースへの接続
$conn = new mysqli($servername, $username, $password, $dbname);
// 接続をチェック
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// POSTデータの取得
$mail_address = $_POST['mail_address'];
$password = md5($_POST['password']); // パスワードをMD5でハッシュ化
// SQLクエリを準備
$sql = "SELECT * FROM User WHERE mail_address = '$mail_address' AND password = '$password'";
$result = $conn->query($sql);
// 結果を確認
if ($result->num_rows > 0) {
// ユーザーが存在する場合
$row = $result->fetch_assoc();
$_SESSION['username'] = $row['name'];
header("Location: welcome.php");
} else {
// ユーザーが存在しない場合
echo "メールアドレスまたはパスワードが違います。";
}
// 接続を閉じる
$conn->close();
?>
<?php
session_start();
// セッションにユーザー名が設定されているか確認
if (!isset($_SESSION['username'])) {
header("Location: login.php");
exit();
}
$username = $_SESSION['username'];
?>
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h2>ようこそ、<?php echo htmlspecialchars($username); ?>さん</h2>
</body>
</html>
login.php
<!DOCTYPE html>
<html>
<head>
<title>Todoログイン</title>
<style>
.error { color: red; }
</style>
</head>
<body>
<h2>ログイン</h2>
<?php if (isset($_GET['error'])): ?>
<p class="error">メールアドレスまたはパスワードが違います。</p>
<?php endif; ?>
<form method="post" action="authenticate.php" onsubmit="return validateForm()">
<label for="mail_address">メールアドレス:</label>
<input type="email" name="mail_address" id="mail_address" required><br><br>
<label for="password">パスワード:</label>
<input type="password" name="password" id="password" required><br><br>
<input type="submit" value="Login">
</form>
<script>
function validateForm() {
var mail_address = document.getElementById("mail_address").value;
var password = document.getElementById("password").value;
if (mail_address === "" || password === "") {
alert("メールアドレスとパスワードを入力してください。");
return false;
}
return true;
}
</script>
</body>
</html>
authenticate.php
<?php
session_start();
// データベース接続情報
$servername = "php-mysql-container";
$username = "user";
$password = "password";
$dbname = "todoapp";
// MySQL データベースへの接続
$conn = new mysqli($servername, $username, $password, $dbname);
// 接続をチェック
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// POSTデータの取得
$mail_address = $_POST['mail_address'];
$password = md5($_POST['password']); // パスワードをMD5でハッシュ化
// SQLクエリを準備
$sql = "SELECT * FROM User WHERE mail_address = '$mail_address' AND password = '$password'";
$result = $conn->query($sql);
// 結果を確認
if ($result->num_rows > 0) {
// ユーザーが存在する場合
$row = $result->fetch_assoc();
$_SESSION['username'] = $row['name'];
header("Location: welcome.php");
} else {
// ユーザーが存在しない場合
header("Location: login.php?error=1");
exit();
}
// 接続を閉じる
$conn->close();
?>
welcome.php
<?php
session_start();
// セッションにユーザー名が設定されているか確認
$username = isset($_SESSION['username']) ? $_SESSION['username'] : null;
?>
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<?php if ($username): ?>
<h2>ようこそ、<?php echo htmlspecialchars($username); ?>さん</h2>
<form method="post" action="logout.php">
<input type="submit" value="ログアウト">
</form>
<?php else: ?>
<h2>ログインしてください。</h2>
<form method="post" action="login.php">
<input type="submit" value="ログイン画面に戻る">
</form>
<?php endif; ?>
</body>
</html>
logout.php
<?php
session_start();
session_destroy();
header("Location: login.php");
exit();
?>
機能面は終了
BootStrapの適用(CDN)