はじめに
先に述べておきますが今回は長い記事となりますのでご了承ください。
- PHP
- MySQL
- Docker
上の3つに関してのある程度の知識は有るものとして解説していきます。と言っても簡単なので初見さんでもコピペで構築が出来るようになっています。
フォルダ構成
$ tree .
.
|-- docker
| `-- db
| |-- data
| |-- my.cnf
| `-- sql
| |-- 001-create-tables.sql
| `-- init-database.sh
|-- docker-compose.yml
|-- php
| |-- article.php
| |-- css
| | `-- style.css
| |-- Dockerfile
| `-- index.php
`-- README.md
- db系
- dataディレクトリ
- 設定ファイルが勝手に入るディレクトリ
- my.cnf
- 文字コードなどdbの初期設定
- 001-create-tables.sql
- データベース/テーブル作成クエリ
- init-database.sh
- 001-create-tables.sqlを実行するスクリプト
- dataディレクトリ
- docker-compose.yml
- dockerのプレイブック
- php系
- article.php
- 記事用ページ
- style.css
- スタイルシート
- Dockerfile
- phpインストールのプレイブック
- index.php
- トップ用ページ
- article.php
この辺が編集していくファイルになります。
プレイブック
$ vi docker-compose.yml
version: '2'
services:
# php:apache
app:
build:
context: ./php
dockerfile: Dockerfile
container_name: php_apa
volumes:
- ./php:/var/www/html:z
ports:
- 80:80
depends_on:
- db
links:
- db:mysql
# MySQL
db:
image: mysql:5.7
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: test_db
MYSQL_USER: root
MYSQL_PASSWORD: password
TZ: 'Asiz/Tokyo'
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./docker/db/data:/var/lib/mysql:z
- ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf:z
- ./docker/db/sql:/docker-entrypoint-initdb.d:z
ports:
- 3306:3306
ApacheとMySQLでコンテナを二つ用意します。今回は構築が目的で運用は考慮していないのでアカパスは適当なものにしています。
$ vi php/Dockerfile
FROM php:7.2-apache
RUN docker-php-ext-install pdo_mysql
このままPHPファイルを解説するよりもDBを先に見ておいた方が分かりやすいと思うので、MySQLの初期クエリから見ていきたいと思います。
MySQL
$vi docker/db/sql/001-create-tables.sql
---- Create TitleTable ----
CREATE DATABASE IF NOT EXISTS keijiban_db;
USE keijiban_db;
DROP TABLE IF EXISTS title_table;
create table title_table
(
id INT(4) AUTO_INCREMENT NOT NULL PRIMARY KEY,
title_id VARCHAR(15),
title VARCHAR(200),
last_com DATETIME,
total_com INT(4)
) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
---- Create CommentTable1 ----
CREATE DATABASE IF NOT EXISTS keijiban_db;
DROP TABLE IF EXISTS 2019_0923_1357;
create table 2019_0923_1357
(
id INT(4) AUTO_INCREMENT NOT NULL PRIMARY KEY,
user VARCHAR(100),
comment TEXT,
date_com DATETIME
) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
---- insert ----
START TRANSACTION;
insert into title_table (title_id, title, last_com, total_com) value ('2019_0923_1357', 'テスト用ダミースレ', '2019-09-23 13:57', 1);
insert into 2019_0923_1357 (user, comment, date_com) value ('通行人A', 'おわた!', '2019-09-23 13:57');
COMMIT;
$ vi docker/db/sql/init-database.sh
#!/usr/bin/env bash
mysql -u root -ppassword < "/docker-entrypoint-initdb.d/001-create-tables.sql"
このスクリプトはMySQLコンテナで実行します。
title_tableテーブル
タイトル名とタイトルIDを管理するテーブルになります。
概要 | カラム名 | 値 | 型 |
ID | id | 1 | INT(4) |
スレタイID | title_id | YYYY_MMDD_hhmmss | VARCHAR(15) |
スレタイ | title | テスト用ダミースレ | VARCHAR(200) |
最終書込日時 | last_com | YYYY-MM-DD hh:mm:ss | DATETIME |
書込総数 | total_com | 999 | INT(4) |
YYYY_MMDD_hhmmテーブル
コメントなどを管理するテーブルです。
概要 | カラム名 | 値 | 型 |
ID | id | 1 | INT(4) |
書込者 | user | 通行人A | VARCHAR(100) |
書込 | comment | おわた! | TEXT |
書込日時 | date_com | YYYY-MM-DD hh:mm:ss | DATETIME |
DBはこんな感じです。意外とシンプルです。
PHP
先に完成予想図を見ておきます。
まずは今回のPHPの動作を確認します。
- POST要求チェック
- フォームにデータが入力されて送信されているかどうか
- DB挿入/抽出
- POSTデータが正しく入力されていればDB挿入
- DBから現状のデータを抽出
- レンダリング
- 抽出したデータを元にレンダリングHTMLを作成
トップページ
トップページから作成しましょう。
$ vi php/index.php
<?php
date_default_timezone_set('Asia/Tokyo');
/**********************************/
/* DB諸情報 */
/*コンテナから見えるホスト名を設定*/
/* ホスト名にはmysqlコンテナid */
/* GlobalIPを記入 */
/* $_SERVER['QUERY_STRING']はparm */
/**********************************/
define('DB_DATABASE', 'keijiban_db');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', 'password');
define('PDO_DSN', 'mysql:host=【MySQLコンテナID】;dbname=' . DB_DATABASE);
$gip = '【WEBサーバIP】';
/******************************************/
/* スレ作成エリア */
/* (1) */
/*Insert title_table & Create CommentTable*/
/******************************************/
if ( !empty($_POST['make_sled_input_sleti']) ) {
$input_sleti = $_POST['make_sled_input_sleti'];
$sle_timestamp = date("Y_md_Hi");
$dummy_first_comment_timestamp = date("Y-m-d H:i:s");
if ( strcmp($input_sleti, "スレッド名") == 0 ) {
echo "あのねあのねスレッド名が空なの";
} else if ( strcmp($input_sleti, "") == 0 ) {
//リロード時の初期値NULLなので何もしない
} else {
$sql3 = "CREATE TABLE $sle_timestamp (
id INT(4) AUTO_INCREMENT NOT NULL PRIMARY KEY,
user VARCHAR(100),
comment TEXT,
date_com DATETIME
) DEFAULT CHARSET=utf8 COLLATE=utf8_bin";
$sql4 = "INSERT INTO title_table (title_id, title, last_com, total_com) value ('{$sle_timestamp}', '{$input_sleti}', '{$dummy_first_comment_timestamp}', 1)";
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql3, PDO::FETCH_ASSOC);
$arr2 = $db->query($sql4, PDO::FETCH_ASSOC);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
}
$redirect_url = "{$_SERVER['PHP_SELF']}".'?'."{$title_id}";
header("Location: $redirect_url");
exit;
}
?>
<html>
<head>
<meta charset="utf-8">
<?php
echo "<title>トップページ</title>"
?>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1 style="text-align:center;">掲示板 on Docker</h1>
<?php
/**********************************/
/* スレタイエリア */
/* レンダリング */
/**********************************/
echo "<div style=\"border: 1px solid#3399FF;\" class=\"sleti_area\">";
/**************************************/
/* (1) */
/* Title Table からスレタイ総数抽出 */
/*最終行のidを取得するためにはこれしか*/
/* なかったんです...... */
/* $title_num */
/**************************************/
$sql = 'SELECT id FROM title_table ORDER BY id desc limit 1';
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql, PDO::FETCH_ASSOC);
foreach($arr as $que_res) {
if ($que_res === reset($arr)) {
echo "これは何の条件分岐";
}
$title_num = $que_res['id'];
if ($que_res === end($arr)) {
echo "これは何の条件分岐";
}
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
/**************************************/
/* (2) */
/* title_tableから更新日時など抽出 */
/**************************************/
$sql = 'SELECT * FROM title_table ORDER BY id DESC';
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql, PDO::FETCH_ASSOC);
foreach($arr as $que_res) {
if ($que_res === reset($arr)) {
echo "";
}
echo "<p class=\"slti\"><a href=\"http://", $gip, "/article.php", "?", $que_res['title_id'], "\" target=\"_blank\">【", $que_res['last_com'], "】 ", $que_res['title'], "</a></p>";
if ($que_res === end($arr)) {
echo "";
}
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
echo "</div>";
/**********************************/
/* コメントエリア */
/* (1) */
/* INSERT処理後にレンダリングする */
/**********************************/
echo "<div style=\"border: 1px solid #3399FF;\" class=\"comment_area\">";
echo "<p style=\"margin-top:0; margin-bottom:20px; font-size:15px; text-align:left;\">直近のコメへ移動</p>";
echo "<div class=\"input_com_block\">";
echo "<form method=\"post\" action=\"\" enctype=\"multipart/form-data\">";
echo "<input type=\"text\" name=\"input_name\" value=\"名前\" class=\"input_name\" onfocus=\"if(this.value==this.defaultValue){this.value='';this.style.color='black';}\" onblur=\"if(this.value==''){this.value=this.defaultValue;this.style.color='#999999'}\"/><br>";
echo "<input type=\"file\" name=\"input_fname\"><br>";
echo "<textarea name=\"input_comment\" class=\"input_comment\" onfocus=\"if(this.value==this.defaultValue){this.value='';this.style.color='black';}\" onblur=\"if(this.value==''){this.value=this.defaultValue;this.style.color='#999999'}\" >コメント</textarea><br>";
echo "<input type=\"submit\" name=\"send\" value=\"書き込む\" class=\"input_com_button\" />";
echo "</form>";
echo "</div>";
echo "</div>";
/**********************************/
/* スレ作成エリア */
/* (2) */
/* レンダリング */
/**********************************/
echo "<div style=\"border: 1px solid #3399FF;\" class=\"make_sled_area\">";
echo "<div class=\"explain_block\">";
echo "<h2 style=\"margin:0;\">ルール</h2>";
echo "<ul class=\"explain_list\"><li>書き込めるのは現状テキストのみ</li><li>荒らしたら負け</li></ul>";
echo "</div>";
echo "<div class=\"make_sled_block\">";
echo "<form method=\"post\" action=\"\">";
echo "<input type=\"text\" name=\"make_sled_input_sleti\" value=\"スレッド名\" class=\"make_sled_input_sleti\" onfocus=\"if(this.value==this.defaultValue){this.value='';this.style.color='black';}\" onblur=\"if(this.value==''){this.value=this.defaultValue;this.style.color='#999999'}\"/><br>";
echo "<input type=\"submit\" name=\"send_sle\" value=\"スレッドを立てる\" class=\"button_sle\" />";
echo "</form>";
echo "</div>";
echo "</div>";
echo "<div class=\"backtop\">";
echo "<a href=\"#\">ページ上部へ移動</a>";
echo "</div>";
?>
</body>
</html>
- 23~54行:スレ作成用のPOSTデータがあればテーブル作成とtitle_tableへのINSERT処理を実行する
- 52~53行:POSTデータをクリアする
- 57行以降:レンダリング処理
- index.phpはコメント入力処理はありません
記事ページ
次は記事ページを作成します。基本的にはトップページと中身は同じです。
$ vi php/article.php
<?php
date_default_timezone_set('Asia/Tokyo');
/**********************************/
/* DB諸情報 */
/*コンテナから見えるホスト名を設定*/
/* ホスト名にはmysqlコンテナid */
/* GlobalIPを記入 */
/* $_SERVER['QUERY_STRING']はparm */
/**********************************/
define('DB_DATABASE', 'keijiban_db');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', 'password');
define('PDO_DSN', 'mysql:host=【MySQLコンテナID】;dbname=' . DB_DATABASE);
$gip = '【WEBサーバIP】';
$title_id = $_SERVER['QUERY_STRING'];
$first_sql = "SELECT title FROM title_table WHERE title_id='{$title_id}'";
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$title_name_arr = $db->query($first_sql, PDO::FETCH_ASSOC);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
foreach($title_name_arr as $que_res) {
$title_name = $que_res['title'];
}
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
/*********************************************************/
/* コメントエリア */
/* (1) */
/* レンダリング前にINSERT処理を実施 */
/* POSTが来たらPOSTクリアするためにheader()でGETリクエスト */
/* header()はレンダリングの前 */
/*********************************************************/
if ( !empty($_POST['input_comment']) ) {
$input_name = $_POST['input_name'];
$input_comment = $_POST['input_comment'];
$input_comment_time = date("Y-m-d H:i:s");
//リロードの度にINSERTしないようにクエリ変数初期化
//commentブロックのレンダリング前だから$input_commentがNULLの場合も弾く必要がある
//リロード時のPOSTクリア
if ( strcmp($input_comment, "コメント") == 0 ) {
echo "あのねあのねコメントが空なの";
} else if ( strcmp($input_comment, "") == 0 ) {
//リロード時の初期値NULLなので何もしない
} else {
$sql = "INSERT INTO {$title_id} (user, comment, date_com) value ('{$input_name}', '{$input_comment}', '{$input_comment_time}')";
$sql2 = "UPDATE title_table SET last_com='{$input_comment_time}' WHERE title_id='{$title_id}'";
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql, PDO::FETCH_ASSOC);
$arr2 = $db->query($sql2, PDO::FETCH_ASSOC);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
}
$redirect_url = "{$_SERVER['PHP_SELF']}".'?'."{$title_id}";
header("Location: $redirect_url");
exit;
}
/******************************************/
/* スレ作成エリア */
/* (1) */
/*Insert title_table & Create CommentTable*/
/******************************************/
if ( !empty($_POST['make_sled_input_sleti']) ) {
$input_sleti = $_POST['make_sled_input_sleti'];
$sle_timestamp = date("Y_md_Hi");
$dummy_first_comment_timestamp = date("Y-m-d H:i:s");
if ( strcmp($input_sleti, "スレッド名") == 0 ) {
echo "あのねあのねスレッド名が空なの";
} else if ( strcmp($input_sleti, "") == 0 ) {
//リロード時の初期値NULLなので何もしない
} else {
$sql3 = "CREATE TABLE $sle_timestamp (
id INT(4) AUTO_INCREMENT NOT NULL PRIMARY KEY,
user VARCHAR(100),
comment TEXT,
date_com DATETIME
) DEFAULT CHARSET=utf8 COLLATE=utf8_bin";
$sql4 = "INSERT INTO title_table (title_id, title, last_com, total_com) value ('{$sle_timestamp}', '{$input_sleti}', '{$dummy_first_comment_timestamp}', 1)";
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql3, PDO::FETCH_ASSOC);
$arr2 = $db->query($sql4, PDO::FETCH_ASSOC);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
}
$redirect_url = "{$_SERVER['PHP_SELF']}".'?'."{$title_id}";
header("Location: $redirect_url");
exit;
}
?>
<html>
<head>
<meta charset="utf-8">
<?php
echo "<title>{$title_name}</title>";
?>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1 style="text-align:center;">掲示板 on Docker</h1>
<?php
/**********************************/
/* スレタイエリア */
/* レンダリング */
/**********************************/
echo "<div style=\"border: 1px solid#3399FF;\" class=\"sleti_area\">";
/**************************************/
/* (1) */
/* Title Table からスレタイ総数抽出 */
/*最終行のidを取得するためにはこれしか*/
/* なかったんです...... */
/* $title_num */
/**************************************/
$sql = 'SELECT id FROM title_table ORDER BY id desc limit 1';
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql, PDO::FETCH_ASSOC);
foreach($arr as $que_res) {
if ($que_res === reset($arr)) {
echo "これは何の条件分岐";
}
$title_num = $que_res['id'];
if ($que_res === end($arr)) {
echo "これは何の条件分岐";
}
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
/**************************************/
/* (2) */
/* title_tableから更新日時など抽出 */
/**************************************/
$sql = 'SELECT * FROM title_table ORDER BY id DESC';
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql, PDO::FETCH_ASSOC);
foreach($arr as $que_res) {
if ($que_res === reset($arr)) {
echo "これは何の条件分岐";
}
echo "<p class=\"slti\"><a href=\"http://", $gip, "/article.php", "?", $que_res['title_id'], "\" target=\"_blank\">【", $que_res['last_com'], "】 ", $que_res['title'], "</a></p>";
if ($que_res === end($arr)) {
echo "これは何の条件分岐";
}
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
echo "</div>";
/**********************************/
/* コメントエリア */
/* (2) */
/* INSERT処理後にレンダリングする */
/**********************************/
echo "<div style=\"border: 1px solid #3399FF;\" class=\"comment_area\">";
echo "<p style=\"margin-top:0; margin-bottom:20px; font-size:15px;\"><a href=\"#lastcom\">直近のコメへ移動</a></p>";
$sql2 = 'SELECT * from '.$title_id;
try {
$db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
$arr = $db->query($sql2, PDO::FETCH_ASSOC);
foreach($arr as $que_res) {
if ($que_res === reset($arr)) {
echo "これは何の条件分岐";
}
echo "<p class=\"comment_header\">", $que_res['id'], ":", $que_res['user'], ":", $que_res['date_com'], "</p>";
echo "<p class=\"comment\">", $que_res['comment'];
if ($que_res === end($arr)) {
echo "これは何の条件分岐";
}
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
echo "<div class=\"input_com_block\">";
echo "<form method=\"post\" action=\"\" enctype=\"multipart/form-data\">";
echo "<input type=\"text\" name=\"input_name\" value=\"名前\" class=\"input_name\" onfocus=\"if(this.value==this.defaultValue){this.value='';this.style.color='black';}\" onblur=\"if(this.value==''){this.value=this.defaultValue;this.style.color='#999999'}\"/><br>";
echo "<input type=\"file\" name=\"input_fname\"><br>";
echo "<textarea name=\"input_comment\" class=\"input_comment\" onfocus=\"if(this.value==this.defaultValue){this.value='';this.style.color='black';}\" onblur=\"if(this.value==''){this.value=this.defaultValue;this.style.color='#999999'}\" >コメント</textarea><br>";
echo "<input type=\"submit\" name=\"send\" value=\"書き込む\" class=\"input_com_button\" id=\"lastcom\" />";
echo "</form>";
echo "</div>";
echo "</div>";
/**********************************/
/* スレ作成エリア */
/* (2) */
/* レンダリング */
/**********************************/
echo "<div style=\"border: 1px solid #3399FF;\" class=\"make_sled_area\">";
echo "<div class=\"explain_block\">";
echo "<h2 style=\"margin:0;\">ルール</h2>";
echo "<ul class=\"explain_list\"><li>書き込めるのは現状テキストのみ</li><li>荒らしたら負け</li></ul>";
echo "</div>";
echo "<div class=\"make_sled_block\">";
echo "<form method=\"post\" action=\"\">";
echo "<input type=\"text\" name=\"make_sled_input_sleti\" value=\"スレッド名\" class=\"make_sled_input_sleti\" onfocus=\"if(this.value==this.defaultValue){this.value='';this.style.color='black';}\" onblur=\"if(this.value==''){this.value=this.defaultValue;this.style.color='#999999'}\"/><br>";
echo "<input type=\"submit\" name=\"send_sle\" value=\"スレッドを立てる\" class=\"button_sle\" />";
echo "</form>";
echo "</div>";
echo "</div>";
echo "<div class=\"backtop\">";
echo "<a href=\"#\">ページ上部へ移動</a>";
echo "</div>";
?>
</body>
</html>
- 18~29行:タイトル取得
- 108~114行:ページタイトルレンダリング
- 38~66行:コメント入力用POSTデータをチェックしあれば作成済みのコメントテーブルに行を追加し、title_tableテーブルの該当する最終コメント日時を更新する。
2つのファイルの機能差分はそんなにありません。
スタイルシート
自分は動けばいいやの精神なので、この辺は好みでお願いします。
$ vi php/css/style.css
/************************/
/*スレタイ・コメント部分*/
/************************/
body {
font-size:22px;
}
.sleti_area {
margin-left:15%;
margin-right:15%;
margin-bottom:50px;
margin-top:50px;
padding:20px;
white-space: nowrap;
overflow:scroll;
height:350px;
}
.slti {
margin:0;
}
.comment_area {
margin-left:15%;
margin-right:15%;
margin-bottom:50px;
padding:20px;
font-size:20px;
}
.comment_header {
margin:0;
font-size:15px;
}
.comment {
margin-top:0;
margin-bottom:30px;
}
/************************/
/*スレタイ・コメント部分*/
/************************/
.explain_block {
text-align:center;
margin-bottom:30px;
margin-bottom:30px;
}
.explain_list {
text-align:left;
}
/************************************************************************/
/* POST部分 */
/*input系は要素定義が特殊でuser-agent stylesheetを呼ぶので個別に指定する*/
/************************************************************************/
.input_com_block {
text-align:center;
}
.input_name {
margin-bottom:20px;
font-size:20px;
padding:5px;
}
.input_fname {
margin-bottom:20px;
font-size:20px;
}
.input_comment {
margin-bottom:20px;
font-size:20px;
padding:5px;
width:70%;
height:300px;
}
.input_com_button {
margin-bottom:20px;
font-size:20px;
width:70%;
}
.make_sled_area {
margin-left:15%;
margin-right:15%;
margin-bottom:50px;
padding:20px;
}
.make_sled_block {
text-align:center;
}
.make_sled_input_sleti {
margin-bottom:20px;
font-size:20px;
padding:5px;
width:70%;
}
.button_sle {
margin-bottom:20px;
font-size:20px;
width:70%;
}
.backtop {
text-align:center;
}
コンテナ起動
以上で開発は完了です。あとはdocker環境を用意して実行してください。
1. docker-compose.ymlファイルのあるディレクトリに移動する。
# docker-compose up -d
2. mysqlコンテナ上でinit-database.shを実行する。
あとはfirewallやポート開放などを行ってください。
- 80/tcp
- 3306/tcp
最後に
勉強不足なもので至らない点が多かったかと思います。それでも最後までお読みいただきありがとうございました。
本当は証明書取得やテキスト以外の書込み機能、改行対応、絵文字、XSS対策などやらないといけないことは山ほどあります。ですが掲示板という機能のみを考えれば実装することは出来ます。今回の記事を少しでも面白いと思って頂ければ幸いです。
また今挙げたものもそれほど難しいものではないので是非対応してみてはいかがでしょうか。証明書などは普段意識していない分、意外と勉強になります。