【初心者向け】PHP データベースに接続して操作する方法を解説

データベース

データベースとは?

PHPでWEBアプリケーションを作る場合、ほぼ確実にデータベースの知識が必要とされます。

データベースとは、database(DB)=データの基地という言葉の通り、決まった形式で整理されたデータの集まりのことです。データを整理しておくことで、追加・編集・削除・検索といった処理が行いやすくなる、というメリットがあります。

イメージしやすくなるように身近な例を挙げます。

例えば、携帯電話やスマートフォンに入っている電話帳・アドレス帳です。

名前や電話番号、メールアドレスなどが決まった形式でデータ登録されていると思います。

必要に応じて、新規で名前や電話番号を登録したり、編集削除を行えますね。

多くの場合、名前が「あいうえお順」で並んでいたり、グループ分け、検索といった便利な機能もあるはずです。

これらの機能のおかげで、必要なデータを見つけやすくなっています。

IT用語でデータベースというときは、商用的に使われていたり、ある程度規模の大きなものを指すことが一般的です。

名前電話番号メールアドレス
青木xxx-xxxx-xxxxaoki@xxx.xxx
佐々木xxx-xxxx-xxxxsasaki@xxx.xxx
高橋xxx-xxxx-xxxxtakahashi@xxx.xxx

具体的には、図書館の蔵書データベースやネットショップの会員情報データベースですね。

データベース管理システムとは?

データベース管理システム(DBMS:DataBase Management System)とは、データベースの管理・運用を行うシステムのことです。

DBMSの必要性について簡単に説明します。

通常、ある程度規模が大きい商用のデータベースとなると、複数のユーザーから同時にアクセスされることになります。

このため、データの読み書きの速度が早いことが求められます。

また、ユーザーAとユーザーBが同時にデータを編集したときに、更新内容を混在させたくない場合もあります。

こういった場合には、ユーザーAの編集内容を保存後にユーザーBの編集内容を保存するという直列処理にしたり、そもそもユーザーAが編集しているときはユーザーBに編集させないといった対応が必要です。

そこで用いられるのが、データベース管理するソフトウェアで、これをデータベース管理システムと呼びます。

MySQLやPostgreSQL、Oracle Database、Microsoft SQL Serverなど色々な種類がありますが、この記事では無料でかつ扱いやすいMySQLを使うことにします。

SQLとは?

コンピュータに「こういった処理をしてください」と指示を出すときに、PHPのようなプログラミング言語が必要になりますよね。

一方でSQLはデータベース管理システムにデータ更新の指示を出す時に必要になります。

基本的な処理は「生成=Create」「読み取り=Read」「更新=Update」「削除=Delete」の4つで、頭文字をとってCRUD(クラッド)と呼ばれます。これは覚えておいて損はないです。

ここまでの説明を図示すると次のようになる。

リレーショナルデータベース

この記事で扱うMySQLはリレーショナルデータベース(RDB:Relational Database)という種類のデータベースです。

リレーショナルデータベースは、複数の「表」で構成されます。

この「表」はテーブル(Table)と呼ばれ、列をカラム(Column)、行をレコード(Record)とそれぞれ呼びます。

プログラミング言語の変数に型があるように、データベースにもカラムごとに型を設定します。

Excelのファイルと各シートの構成をイメージすると理解しやすいと思います。

掲示板の開発の事前準備

掲示板の機能

この記事ではデータベースを使用したプログラムを作成してみましょう。

まずは実装する機能を検討します。

ユーザーが掲示板に書き込む項目は、「名前」「タイトル」「本文」の3つとします。

必要な情報を入力して送信すると、これらの情報をデータベースに保存します。

また、書き込まれた情報が新しい順に表示されるようにします。書き込み日時も表示するようにすると、より見やすくなりますね。

フォームで登録した情報を一覧表示するというシンプルな掲示板です。

データベースの設計

実際のコーディングに入る前に、実装したい機能を考慮して、データベースの設計をしていきます。

具体的には、どのようなデータをどのような型(形式)で保存するかを決めます。

今回の掲示板では、下記の情報が必要になりそうですね。

  • 名前
  • タイトル
  • 本文
  • 書き込み日時
  • 通し番号

書き込みに対して通し番号をつけておくと、データを管理するのが楽になるので追加しています。

MySQLのデータ型データ型

DBMSによって使用できるデータ型が多少異なります。

MySQLのデータ型には、大きく分けて「数値型」「日付・時刻型」「文字列型」があります。

さらに、どういったデータをデータを保存するかによって、この中からより細かく型を選んでいきます。

ここでは、MySQLで使用できる代表的なデータ型を紹介しますね。

名称
INT整数型連番、個数など
DOUBLE倍精度浮動小数点型身長など小数点を含むもの
数値型
名称
DATE日付型日付
DATETIME日付・時刻型日付と時刻
日付・時刻型
型の名称
CHAR固定長文字列型郵便番号など長さが決まっているもの
※文字列長を指定する
VARCHAR可変長文字列型名前、住所など
※最大長を指定する
TEXT文字列型本文などの長い文章
文字列型

データベースの具体的な設計

まずはデータベース名をきめておきましょう。今回は掲示板を作成するので「bbs」とします。

ちなみに、三省堂国語辞典(第八版)で「BBS」という言葉が削除されるらしいですね。ちょっと時代を感じます。

次にデータを保存するテーブルを設計していきましょう。テーブル名は「messages」にしておきます。

messagesテーブルには、「通し番号」「名前」「タイトル」「本文」「書き込み日時」を保存する必要があります。

カラム名カラム型NOT NULL 制約説明
idINT通し番号
主キー、自動採番
nameVARCHAR(255)名前
長さは最大255文字
titleVARCHAR(255)タイトル
長さは最大255文字
bodyTEXT本文
dateDATETIME書き込みされた日時
messagesテーブル

ここで「主キー」「NOT NULL 制約」という2つの新しい用語が出てきました。それぞれについて説明します。

主キー

主キーとは、テーブル内でレコードを一意に識別するための項目(カラム)です。

messagesテーブルでidを主キーとしているので、idの数字はユニーク(重複しない)ということになります。

身近な例で言えばクラス名簿の出席番号ですね。

氏名は主キーになりません。

同姓同名の人がいる可能性もあるので、必ず特定の誰かを示すとは限らないからです。

あいうえお順などで順番に振られた出席番号であれば、クラス内では他人と重複しないので、主キーになります。

messagesテーブルのidについても同様の考え方で、書き込みの通し番号のため重複せず、主キーとして設定することが可能です。

NOT NULL 制約

NOT NULL 制約とは、名前の通り「対象のカラムに必ずデータを入れる」という制約です。

messagesテーブルで言えば、title以外の項目には何らかのデータを入れる必要があるということです。

title未指定で書き込まれる可能性がありますので、その時の処理も考える必要があります。

この記事では、表示側プログラムで「無題」と表示させることにしましょう。

データベースの準備

ここまで設計ができたところで、MySQLのデータベースの準備を進めていきます。

開発している環境によっても手順が変わってきますので、ここで紹介するのはあくまでも一例です。

MySQL自体のセットアップは完了している前提で話を進めます。

まず、次のコマンドでmysqlに接続します。必要に応じて、-uや-pオプションでユーザーやパスワードを指定しましょう。

mysql

接続が無事にできたら、データベースの作成コマンドを実行します。

CREATE DATABASE bbs;

エラーが出ていなければ問題ないと思いますが、念の為データベースが作成されていることを確認しましょう。

SHOW DATABASES;

コマンドを実行すると、データベースの一覧が表示されるはずです。一覧の中に「bbs」があればOKです。

bbsデータベースを利用したいので、次のコマンドでデータベースを選択します。

USE bbs;

データベースを選択したので、次にテーブルを作成しましょう。

CREATE TABLE messages (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
title VARCHAR(255),
body TEXT NOT NULL,
date DATETIME NOT NULL
) DEFAULT CHARACTER SET=utf8;

()の中はカラムの設定で、カラム名、型、制約、属性の順に指定します。

例えば、idの型はINT、制約はNOT NULL、属性はAUTO_INCREMENT, PRIMARY KEYとなります。

AUTO_INCREMENTは自動採番を表していますので、idはレコードが挿入されるたびに、自動で数字が付与されていくことになります。PRIMARY KEYは主キーを表しています。

その他のカラムも同様に、カラム名と型を指定しています。制約や属性はオプション項目なので省略可能です。

最後にこのテーブルで標準的に使う文字コードにUTF-8を指定しています。

次のコマンドで各カラムの設定を確認することができます。

SHOW COLUMNS FROM messages;

これでデータベースの準備ができました。


場合によっては、このデータベースを操作できるユーザーを新規に作成・設定しますが、この記事では省略します。

登録機能の開発

入力フォームの作成

ここまで来て、ようやくPHPのプログラムの開発に入っていきます。

まずは入力フォームを作成していきますが、フォームと送信処理は前回の記事を参考にすぐに実装できると思います。

ここまでは簡単ですね。

データベースへの書き込み処理

次に送信データを受け取って、データベースへの保存をするwrite.phpを示します。

前回までのプログラムとは違い、データベースが絡んでくると処理が複雑に見えるかもしれません。

順を追って説明します。

必須項目の入力チェック

2~4行目はフォームから送信されたデータの受け取りです。フォームからPOSTメソッドで送られてくるので、$_POSTで取得しています。

6~9行目が必須項目の入力チェックを行なっています。名前か本文が入力されているか確認して、いずれかが未入力だった場合、フォームの画面へ戻すという処理をしています。

headerはHTTPヘッダを送信するための関数です。header関数でLocationを指定すると、指定したURLにジャンプさせることができます。

header(‘Location: 戻り先のURL’);

サーバとデータベースの接続情報

11~13行目で、データベースに接続するのに必要なDSNとユーザー名、パスワードを指定しています。

ここは自分の環境に合わせて書き換えてください。

DSN(Data Source Name)とは、どのサーバにあるどのデータベースを使うのか指定する文字列です。

mysql:host=ホスト名;dbname=データベース名;charset=文字コード

PDOとは

16行目でPDOインスタンスの作成を行なっています。ここでPDOとは何かを説明しておきます。

DBMSにはさまざまな種類がありますが、どれを使うかによってプログラムの書き方が異なります。

もし、DBMSに依存したプログラムの書き方をしてしまうと、DBMSを変更したときに、PHPのプログラムを大幅に変更する必要が出てきます。

このような手間を防ぐため、PHPとDBMSの間に抽象化レイヤを挟んでDBMSの違いをレイヤで吸収させるようにします。

こうすることで、データベースの細かい扱いはPDOに任せて、その他のプログラムの開発に集中できるようになります。

PDOはこのデータアクセスの抽象化レイヤを提供します。次のようなイメージですね。

プリペアドステートメント

19~36行目で、プリペアドステートメントを作成しています。

プリペアドステートメントとは、実行するクエリのテンプレートのようなものです。

プログラム内に「:name」「:title」「:body」といった記述がありますが、この部分のことをプレースホルダと呼び、後から変数を埋め込むようにします。

38~40行目で、bindParamメソッドを使ってプレースホルダに変数を埋め込んでいます。

レコードを追加するINSERT 文

21~34行目が実行するクエリになります。

INSERT文はテーブルに新しいレコードを追加するSQLの構文になります。

INSERT INTO テーブル名 (カラム1, カラム2, カラム3, …) VALUES (値1, 値2, 値3, …)

実際にのプログラムでは改行を入れているため分かりづらいかもしれませんが、よく比較してみましょう。

テーブル名にはレコードを追加したいテーブルの名前を指定します。ここではmessagesテーブルですね。

次の()内にはデータを入れたいカラムを列挙します。各カラムに対応する値はVALUESの後の()内で指定します。

dateは書き込み日時を指定するカラムですが、now()を入れておくことで、レコード追加時に自動で日時を展開してくれます。

このnow()はMySQLが持つ現在日時を取得する関数です。便利なので覚えておきましょう。

42行目のexecuteメソッドで、クエリを実行します。

このように、プリペアドステートメントでクエリを組み立てて、executeで実行するというのが基本的な流れになります。

一覧表示機能の開発

index.phpの修正

index.phpでmessagesテーブルのデータを読み込み、一覧表示させるようにプログラムを修正します。

まず修正したプログラムを示して、順を追って説明していきます。

1~40行目に追加したコードで、データベースへの接続とデータの取得を行なっています。

53~86行目に追加したコードは、取得したデータの表示処理になります。

データの取得

まず、データの取得部分について説明します。

一度にたくさんの投稿メッセージを表示してしまうと見づらいので、5件ずつ表示することにしました。件数は2行目で指定するようになっています。

4~5行目はデータベースの接続情報をしているので、環境に合わせて書き換えてください。

クエリパラメータでページ数を指定することにします。

例えば、index.php?page=2でアクセスすれば2ページ目のデータを表示、index.php?page=5でアクセスした場合には5ページ目のデータを表示するということです。

クエリパラメータの取得は9~11行目で行なっています。

レコードを取得するSELECT文

17~29行目のプリペアドステートメントでは、レコードを取得するSELECTというクエリを作成しています。

ここで指定しているクエリは次のような構造になっています。

SELECT カラム1, カラム2, … FROM テーブル名
ORDER BY ソートするカラム DESC
LIMIT 開始位置, 件数

SELECT文では、SELECTの後ろに取得するカラムを指定します。全てのカラムを取得する場合には、今回のように「*」を指定しましょう。

ORDER BY以降はオプション項目なので、必要なければ省略可能です。

今回の例では、書き込み日時の新しい順に取得したいので、ORDER BYを入れています。

BYの後ろに何のカラムでソートするかを指定します。次のDESCは「降順」に並べ替えることを意味しています。

つまり、「書き込み日時の降順、日時の新しい順」にデータを取得するということになります。

逆に昇順に並び替えてデータを取得したい時には、ASCとします。日時の昇順=日時の古い順ということになりますね。

最後にLIMITで「何件目から何件分のレコードを取得するか」を指定します。

1ページ目なら1件目〜10件取得、2ページ目なら11件目から10件取得、というようにずらしていく必要があります。

この開始位置と件数の制御をLIMITで行なっているということです。

レコードの取得と整形

実際のプロジェクトでは、データベースから取得したデータの形式を変換してから表示する、という場面が多々あります。

今回の例で言えば、53~52行目が変換と表示の部分になります。

54行目のwhile文で1レコードずつ取り出して、その後に形式の変換と表示を行なっています。

ここでfetchメソッドを使っています。このメソッドを使うと、カラム名をキーにした連想配列として、レコードを1件ずつ取得することができます。

55行目では、タイトル入ってない場合に、「(無題)」と表示するように文字列をセットしています。

タイトルが入っていればそのまま、入っていなければ「(無題)」にするという条件分岐が必要になりますが、三項演算子というもので実現しています。

条件式 ? 式1 : 式2

三項演算子は、条件式の結果がTRUEであれば式1を、FALSEであれば式2を返します。

ページング処理

64行目以降はページング処理になります。

65~72行目のプリペアドステートメントでも、SELECT文を使っています。

COUNTはMySQLが持っている関数の1つで、レコード数(ここでは投稿の数)を取得することができます。

79行目で投稿の件数を取得して、80行目で1ページあたりの件数で割ることで、総ページ数を求めています。

その後、82行目のfor分で必要な分だけページリンクを生成しているということです。

まとめ

今回はPHPからデータベースに接続して操作する方法を扱いました!

データベースを扱うとなった瞬間にこれだけ情報が多くなって、記事を書いている途中で驚いたぐらいです。

データベースを扱えるようになると、本当にアプリケーションらしいものが作れるようになってきます。

覚えることは多いですが、是非マスターしましょう!

ココナラでプログラミング初学者向けのサービスを出品しています。

初学者のプログラミング学習をサポートします 現役のエンジニアが丁寧にサポートします!

コメントを残す

メールアドレスが公開されることはありません。