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など結果を表示し、それに至る過程を説明していきます。
完成イメージ
完成ソース
<?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です。合わせるとちょっと長い感があるかもしれませんが、慣れですかね。
見慣れると短いくらいです。多分。
@charset "utf-8"; *{ font-family: "Sawarabi Gothic"; } body{ margin-top: 120px; }
CSSはassetsフォルダーに入れています。元々、Bootstrapでは、リソース(Javascript, CSS, imagesなど)はassetsフォルダーに入れていて、わりと名残でそれを使っているサイトをよく見ます。
まあ、サンプルは、おじさんが作っているということでご容赦頂けると幸いです。
このシリーズでは、リソースはassetsフォルダーを積極的に使っていきますので、あまり冷ややかな目で見ないように、お願い申し上げます。
今回は、Javascriptは利用していないですし、画像もありません。
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 検索、登録、更新、削除