魁小野の塾

魁!小野の塾 PHPで簡単なプログラムを作ってみようの巻 第1話


PHPで簡単なプログラムを作ってみよう 第1話

初心者向け、PHPプログラム構築講座です。
初心者といっても、PHPの勉強を少し行い、LAMP環境が自分で構築できるレベルを対象とします。
まったくの初心者の場合は、わからない部分が出てくると思います。
できるだけ細かく説明は入れていきますが、説明がわからない場合は、PHPやMySQLの初心者講座をご覧ください。

対象のスキルレベル

  • LAMP環境の構築
  • PHP言語が読める
  • HTML, CSS, Javascriptが少しわかる
  • Bootstrapのドキュメントをみて、HTMLが書ける
  • CDNを理解している

構築環境

  • Windows10
  • XAMPP(PHP7.3.2, MariaDB 10.1.38)

今回は、CRUD(クラッド:create, read, update, delete)のupdateを除いた、登録、読込、削除を対象に、掲示板を作成する流れを説明致します。
最初に、PHP、CSS、Javascript、DDLなど結果を表示し、それに至る過程を説明していきます。

完成イメージ

完成ソース

index.php
<?php
	// db resource
	$db	= new mysqli('localhost', 'root', '', 'pjin');
	$db->set_charset("utf8");

	// $_POST -> $request
	$request	= [
		'author'	=> $_POST['author'] ?? '',
		'content'	=> $_POST['content'] ?? '',
		'action'	=> $_POST['action'] ?? ''
	];

	// create or delete
	$errors	= [];
	switch($request['action']){
	case 'create':
		// error check
		if(empty($request['author'])){
			$errors['author'][]	= '名前を入力して下さい。';
		}
		if(mb_strlen($request['author']) > 128){
			$errors['author'][]	= '名前は128文字以内で入力して下さい。';
		}
		if(empty($request['content'])){
			$errors['content'][]	= '内容を入力して下さい。';
		}
		if(mb_strlen($request['content']) > 65535){
			$errors['content'][]	= '名前は65,535文字以内で入力して下さい。';
		}

		if(count($errors) > 0){
			// エラーがあれば終了
			break;
		}

		// 登録処理
		$sql	= "insert into board(author, content) values (?, ?)";
		if($stmt = $db->prepare($sql)){
			$stmt->bind_param("ss", $request['author'], $request['content']);
			$stmt->execute();
			$stmt->close();
			// 登録後に空にします。
			$request	= [
				'author'	=> '',
				'content'	=> ''
			];
		}
		break;

	case 'delete';
		// 削除処理
		$sql	= "delete from board where id = ?";
		if($stmt = $db->prepare($sql)){
			$stmt->bind_param("i", $_POST['id']);
			$stmt->execute();
			$stmt->close();
		}
		break;
	}

	// 検索処理
	$rs	= [];
	$sql	= "select * from board order by id desc";
	if($stmt = $db->prepare($sql)){
		$stmt->execute();
		$stmt->bind_result($id, $createdAt, $author, $content);
		while($stmt->fetch()){
			$rs[]	= [
				'id'		=> $id,
				'createdAt'	=> $createdAt,
				'author'	=> $author,
				'content'	=> $content
			];
		}
		$stmt->close();
	}

	// db resource close
	$db->close();
?>
<!DOCTYPE html>
<html lang="ja">
	<head>
		<!-- Required meta tags -->
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

		<!-- Bootstrap CSS -->
		<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
			integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
		<!-- Font Awesome CSS -->
		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css"
			integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
		<!-- Animate.css CSS -->
		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
		<!-- Sawarabi Gothic -->
		<link href="https://fonts.googleapis.com/css?family=Sawarabi+Gothic" rel="stylesheet">

		<link rel="stylesheet" href="assets/css/style.css" />

		<title>掲示板 | tech.pjin.jp</title>
	</head>
	<body>
		<header>
			<nav class="navbar navbar-expand-lg navbar-dark bg-info fixed-top">
				<section class="container">
					<a class="navbar-brand" href="<?php echo $_SERVER['SCRIPT_NAME'] ?>">
						<h1 class="animate__animated animate__backInRight"><i class="far fa-clipboard"></i> 掲示板</h1>
					</a>
					<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
						<span class="navbar-toggler-icon"></span>
					</button>
					<div class="collapse navbar-collapse" id="navbarText">
						<span class="navbar-text animate__animated animate__bounce animate__delay-3s">
							<i class="fas fa-heart"></i> 好きなこと書いて生きよう!
						</span>
					</div>
				</section>
			</nav>
		</header>

		<main class="container">

		<?php if(count($errors) > 0){ ?>
			<div class="alert alert-danger" role="alert">
				<h4 class="alert-heading"><i class="fas fa-exclamation-triangle"></i> エラー</h4>
				<ul>
			<?php foreach($errors as $err){ ?>
				<?php foreach($err as $e){ ?>
					<li><?php echo htmlentities($e) ?></li>
				<?php } ?>
			<?php } ?>
				</ul>
			</div>
		<?php } ?>

			<form action="<?php echo $_SERVER['SCRIPT_NAME'] ?>" method="POST">
				<input type="hidden" name="action" value="create">
				<div class="form-group row">
					<label for="author" class="col-sm-2 col-form-label">名前</label>
					<div class="col-sm-10">
						<input type="text" name="author" id="author"
							value="<?php echo $request['author'] ?>"
							class="form-control<?php if(isset($errors['author'])){ echo ' is-invalid';} ?>"
							placeholder="名前" autofocus>
					</div>
				</div>
				<div class="form-group row">
					<label for="content" class="col-sm-2 col-form-label">内容</label>
					<div class="col-sm-10">
						<textarea name="content" id="content"
							class="form-control<?php if(isset($errors['content'])){ echo ' is-invalid';} ?>"
							rows="10" placeholder="内容を入力してください"><?php echo $request['content'] ?></textarea>
					</div>
				</div>
				<div class="form-group row">
					<div class="offset-sm-2 col-sm-10">
						<button type="submit" class="btn btn-primary"><i class="fas fa-paper-plane"></i> 送信</button>
					</div>
				</div>
			</form>

			<hr>

		<?php foreach($rs as $row){ ?>
			<div class="card">
				<div class="card-header">
					<div class="row">
						<div class="col-sm-6">
							<strong><?php echo htmlentities($row['author']) ?></strong>
						</div>
						<div class="col-sm-6 text-right">
							<small><?php echo date('Y-m-d H:i:s ', strtotime($row['createdAt'])) ?></small>
						</div>
					</div>
				</div>
				<div class="card-body">
					<form action="<?php echo $_SERVER['SCRIPT_NAME'] ?>" method="POST">
						<p class="float-right">
							<input type="hidden" name="action" value="delete">
							<input type="hidden" name="id" value="<?php echo htmlentities($row['id']) ?>">
							<button type="submit" class="btn btn-outline-danger btn-sm">
								<i class="far fa-trash-alt"></i> 削除
							</button>
						</p>
					</form>
					<p class="card-text">
						<?php echo nl2br(htmlentities($row['content'])) ?>
					</p>
				</div>
			</div>

			<div class="mt-3"></div>
		<?php } ?>

			<div class="mt-5"></div>
		</main>

		<!-- Optional JavaScript -->
		<!-- jQuery first, then Popper.js, then Bootstrap JS -->
		<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
			integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
		<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
			integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
		<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"
			integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
	</body>
</html>

PHPのコードを新人に見せたら、「ながっ!!」って言われました。ゴメンナサイ。
PHPとHTMLを分ければ良かったと、ちょっと後悔しております。
80行のPHPコードと120行くらいのHTMLです。合わせるとちょっと長い感があるかもしれませんが、慣れですかね。
見慣れると短いくらいです。多分。

assets/css/style.css
@charset "utf-8";
*{
	font-family: "Sawarabi Gothic";
}
body{
	margin-top: 120px;
}

CSSはassetsフォルダーに入れています。元々、Bootstrapでは、リソース(Javascript, CSS, imagesなど)はassetsフォルダーに入れていて、わりと名残でそれを使っているサイトをよく見ます。
まあ、サンプルは、おじさんが作っているということでご容赦頂けると幸いです。
このシリーズでは、リソースはassetsフォルダーを積極的に使っていきますので、あまり冷ややかな目で見ないように、お願い申し上げます。
今回は、Javascriptは利用していないですし、画像もありません。

DDL
CREATE TABLE `board` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `author` varchar(128) DEFAULT NULL,
  `content` text DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `board`
  ADD PRIMARY KEY (`id`);

データベースは「pjin」で、テーブル名は「board」です。
XAMPPで特に設定を入れない場合は、ユーザは「root」で、パスワードはなしでログインできます。

XAMPPのコントローラでMySQL部分の「Admin」ボタンを押下すると、phpMyAdminが開きます。

phpMyAdminにログインしたら、「データベース」タブを押下し、データベース名を入力(今回はpjin)、照合順序(utf8mb4_general_ci)を選択し、「作成」ボタンを押下します。
照合順序はデフォルトが最新では変わっていますが、以前は「latin1_swedish_ci」になっています。(スウェーデン語/フィンランド語)

※参考 MySQL での文字セットと照合順序

後から変更も可能なのですがここは間違えないように、「utf8mb4_general_ci」を選択しましょう。(半角英字の大文字・小文字を区別しませんよー)
※参考 MySQLの文字コードとCollation

あと、DDLという用語ですが、SQLは「DDL」「DCL」「DML」「トランザクション制御」に分かれております。

  • DDL:Data Definition Language データベースやテーブルの作成や破棄 ※DLLではないですので注意。ちなみにDLLはDynamic Link Libraryの略
  • DCL:Data Control Language 権限の付与と剥奪
  • DML:Data Manipulation Language 検索、登録、更新、削除

魁!小野の塾 PHPで簡単なプログラムを作ってみようの巻

  • このエントリーをはてなブックマークに追加

PAGE TOP