PHP/データベースとの連動
PHPのプログラム側から、データベースのMySQL(mariaDBでも可)にアクセスできる。
手法編集
XAMPP や phpmyadmin などのツールがなくても、標準状態の Linux での Apache, mySQL(mariaDB) とPHP だけでも 、下記のようにPHPをデータベースと連動できます。(2020年4月25日に Fedora 32 などで確認。)
Linux の場合編集
mysqli_connect の場合編集
まず、mysqli_connect
という組み込み関数を使うが、しかし、初期設定では mysqli_connect
がインストールされていないので、
sudo dnf install php-mysqlnd
でインストールする(Fedora の場合)。
さて、 まず、PHP の先の起動よりも先に、 MySQL と Apache(httpd) をそれぞれ起動しておく必要がある。
$ systemctl start mariadb
$ systemctl start httpd
もし先にPHPを起動していたら、MySQLおよびApacheの起動後に、PHPをいったん終了してから、再度にPHPを起動しなおす(でないと、のちの mysqli_connect 関数による MySQL 接続時にエラーになる)。
なお、MySQLとApacheの詳しい操作の解説についてはwikibooks『CGI』および『MySQL』を参照のこと。
PHPには、コマンドラインから使える対話型シェルというのがあるので、まずこの対話型シェルでデータベース接続を試すのがラクである。
Linux側のコマンド端末で、
$ php -a
で、対話型シェルを起動できる。(なおWindows版も同様のコマンドで対話型シェルを起動できる。以降の説明ではLinuxの場合について説明する。なぜならWindowsで滅多にデータベースまで使わないので。)
起動後の表示は、
[ユーザー名@localhost ~]$ php -a Interactive shell php >
のように「Interactive shell」と出る。
シェルを終了するには quit
または exit
で終了できる。(Windows版もLinux版も同様のコマンド。)
起動できる事が分かったら、いったん exit などでログアウトして sudo コマンドを使ってrootユーザーとしてPHPを起動しなおす。(でないと、あとで、mySQL側からアクセス拒否されるのが通常なので。なお、そのエラーの場合、おそらく PHP Warning: Uncaught Error: Call to undefined function mysqli_connect() in php shell code:1
というエラーメッセージが出ることになるだろう。)
$ sudo php -a
のように、単にsudoを先につければ、rootユーザーとしてPHPを起動できるので、それを実行しよう。
さて、sudo で起動できたら、次に
php > mysqli_connect('localhost',"root","","既存のデータベース名" );
の書式で、MySQLにPHP側からアクセスできる。(プログラマーで手で入力するのは PHP > 以降の部分。)
なお、第3引数はパスワードだが、MySQLの初期設定では通常、パスワードが無いので、その場合は空白で良い。
- ※ むかし、mysql「i」の 「i」がついてない関数があったが、これは古い関数で、2020年現在の mysqli_ 系(iつき)の関数とは互換性が無いのでエラーになる。(そもそも、もはやi無しの関数はPHPに未登録。)
なお、もし sudo のrootユーザーとしてPHPを起動していないと、上記の mysqli_connect
をしてもアクセス権が無いという理由で MySQL から接続拒否されるので
PHP Warning: mysqli_connect(): (HY000/1698): Access denied for user 'root'@'localhost' in php shell code on line 1
のようにエラーメッセージが出る。
さて、接続できることが分かったら、次のように、なんらかの変数($conの部分)を定義して、接続しなおす。今後の関数で、mysqli系の関数では、この変数を利用する必要があるので。(関数の利用する際、どの接続に対する関数であるかを、mysqliなどiつき関数では引数で指定する仕組みになっているので。)
$con = mysqli_connect('localhost',"root","","testmysql" );
クエリ(データベースへの命令送信)は、次のように送る。
mysqli_query($con, 'select * from testTable');
mysqli_query
では第1引数で、どの接続かを指定する必要がある。第2引数は、送信したいクエリ内容で、引用符で くくる必要がある。(なお、iなしの古いバージョンの関数では、引数の順序が違っているので、混同しないように。)
PHPファイルで実行する場合編集
MySQLにアクセスするPHPファイルの場所は、ホームフォルダで良い。(わざわざドキュメントルート /var/www/html にコピーしなくてもいい)
- コード例
<?php
$con = mysqli_connect('localhost',"root","","testmysql" );
$res = mysqli_query($con, 'select * from testTable');
$data = mysqli_fetch_array($res);
echo "番号:" . $data["gensobangou"] ."\n" ;
echo "元素名:" . $data["gensomei"] ."\n" ;
echo "記号:" . $data["gensokigou"] ."\n" ;
?>
- 実行方法
先に、MySQL側で作っておく。本コード例のデータベースは wikibooks『MySQL』で作成したものを流用した。
起動方法では、コマンド端末で sudo ユーザーで起動することで実行する必要がある(root以外だとアクセス拒否されるので)。たとえばファイル名が「conPhp.php」なら
sudo php conPhp.php
のようにコマンド実行する必要がある。
もし sudo 以外で起動しても、アクセス拒否されてしまう。( PHP Warning: mysqli_connect(): (HY000/1698): Access denied for user 'root'@'localhost' in /home/sujiniku/conPhp.php on line 2
)
- 実行例
番号:1 元素名:Hydrogen 記号:H
2列目以降のデータを読みとりたいなら、
<?php
$con = mysqli_connect('localhost',"root","","testmysql" );
$res = mysqli_query($con, 'select * from testTable');
$data = mysqli_fetch_array($res);
echo "番号:" . $data["gensobangou"] ."\n" ;
echo "元素名:" . $data["gensomei"] ."\n" ;
echo "記号:" . $data["gensokigou"] ."\n" ;
$data = mysqli_fetch_array($res);
echo "番号:" . $data["gensobangou"] ."\n" ;
echo "元素名:" . $data["gensomei"] ."\n" ;
echo "記号:" . $data["gensokigou"] ."\n" ;
?>
のように、
$data = mysqli_fetch_array($res);
を繰り返す。
なお echo だけを繰り返しても、前と同じ列を読み取ってしまう(つまり、上述の周期表データの例では、水素Hだけ)。
- 実行結果
番号:1 元素名:Hydrogen 記号:H 番号:2 元素名:Helium 記号:
PDOの場合編集
データベースはMySQL以外のものもあるので、PHPでは、特定のデータベースに依存しない形式のPDOという接続方式もある。
- コード例
<?php
$con = new PDO('mysql:host=localhost;dbname=testmysql;charset=utf8',"root","" );
$res = $con->query('select * from testTable');
$data = $res->fetch(PDO::FETCH_ASSOC);
echo "番号:" . $data["gensobangou"] ."\n" ;
echo "元素名:" . $data["gensomei"] ."\n" ;
echo "記号:" . $data["gensokigou"] ."\n" ;
$data = $res->fetch(PDO::FETCH_ASSOC);
echo "番号:" . $data["gensobangou"] ."\n" ;
echo "元素名:" . $data["gensomei"] ."\n" ;
echo "記号:" . $data["gensokigou"] ."\n" ;
?>
- 実行結果
番号:1 元素名:Hydrogen 記号:H 番号:2 元素名:Helium 記号:
- 解説
最初にPDOを宣言する際、演算子 new を忘れないようにしよう。この new 演算子が無いと、代入命令との区別ができないためか、エラーになる。
なお、このPDO の new 宣言では、メモリの確保を行っている[1]。そのためか、このnew宣言を先に行ってからでないと、コード中で後述のpdo関連の様々な関数命令を用いる事ができない。
- なお、このPDOのnew宣言のように、(おおむねC++登場時および以降の)近代的な命令群や機能など用いるために、new演算子などを用いてメモリ確保する事や、その結果のメモリ確保された領域のことなどを「インスタンス」といいます。
PDO::FETCH_ASSOC
のコロン2つの部分(::)はコマンド名の一部なので、変更してはならない。(アロー演算子 -> などに変更しても、認識しない。)
おおまかには fetch(PDO::FETCH_ASSOC) の PDO::FETCH_ASSOC が配列形式の指定。 fetch が変換の命令。
fetch() 命令は、一行ずつ、レコード(データベースの中身の部分)を取得する。
webブラウザからデータベースの読み書き編集
webブラウザはどうやっても、root権限にはなれない。しかし、mySQLの初期状態では、ユーザーがrootしか登録されていない。
なので、まずMySQLにユーザーの追加が必要なので、Linuxのログインユーザー名で、MySQLにユーザーを追加する。MySQL起動後に、MySQL端末内で(Gnome端末ではないので注意)
CREATE USER 'ユーザー名'@'localhost';
でMySQLにユーザー登録できる。
まだユーザーを作っただけでは、この新規ユーザーには権限がまったく無い。なので、権限の追加のため grant
という命令で(指定ユーザーに権限を)追加する。
GRANT ALL ON *.* TO ユーザー名@localhost;
なお、この例では、すべての権限を与えている。(実務ではセキュリティなどのため、権限は限定的に与えることになる。 例では、今後の操作の簡略化のため、権限をすべて与えることにした。)
- コード例
<html>
<head>
<title>サンプル</title>
</head>
<body>
<?php
$con = mysqli_connect('localhost',"ユーザー名","","testmysql" );
$res = mysqli_query($con, 'select * from testTable');
$data = mysqli_fetch_array($res);
print "番号:" . $data["gensobangou"] ."<br />" ;
echo "元素名:" . $data["gensomei"] ."<br />" ;
echo "記号:" . $data["gensokigou"] ."<br />" ;
$data = mysqli_fetch_array($res);
echo "番号:" . $data["gensobangou"] ."<br />" ;
echo "元素名:" . $data["gensomei"] ."<br />" ;
echo "記号:" . $data["gensokigou"] ."<br />" ;
?>
</body>
</html>
この上記のコードを、/var/www/html に入れておく。拡張子は .php であることに注意。(コード中に html タグがあるので、ついつい拡張子を html にしてしまいがち)
ブラウザ接続時にwebブラウザの見れる形式に変換するため、あらかじめ Apache(httpd) を起動しておく。
systemctl start httpd
で起動できる。
MySQLサーバーも当然、起動する必要があるので、
systemctl start mariadb
でMySQLサーバーを起動。
そして、webブラウザで
http://localhost/上記コードのファイル名.php
にアクセスすればいい。
- 実行結果
番号:1 元素名:Hydrogen 記号:H 番号:2 元素名:Helium 記号:
- (動作環境など: FireFox75 で2020年4月25日に動作を確認。OS はFedora 32 で同日。)
XAMPPの場合編集
主にWindows版の場合について、XAMPPでのMySQL連動について述べる。
まず、連動先のMySQLについては、XAMPPのフォルダ内にあるMySQLにあるデータベースであるという必要がある。
ともかく、何らかの方法で事前に XAMPP 内 MySQL にて、目的のデータベースを保管しておく必要がある(その方法については、mySQl側の説明を待て。ただし現時点(2020年4月26日)ではwikibooksでは未完成)。
さて、とにかくXAMPP内MySQLに目的のデータを保管できたら、あとは単に、上記のコードのphpファイルを、XAMPPのドキュメントルートのフォルダ (初期設定では C:\xampp\htdocs である)に(そのphpファイル)入れれば良い。
念のため、どのphpファイルを入れるのかというと、
<?php
$con = mysqli_connect('localhost',"ユーザー名","","testmysql" );
$res = mysqli_query($con, 'select * from testTable');
$data = mysqli_fetch_array($res);
print "番号:" . $data["gensobangou"] ."<br />" ;
echo "元素名:" . $data["gensomei"] ."<br />" ;
echo "記号:" . $data["gensokigou"] ."<br />" ;
$data = mysqli_fetch_array($res);
echo "番号:" . $data["gensobangou"] ."<br />" ;
echo "元素名:" . $data["gensomei"] ."<br />" ;
echo "記号:" . $data["gensokigou"] ."<br />" ;
?>
</body>
</html>
のようなphpファイルであり、このファイルを C:\xampp\htdocs に入れるだけである。
そして、webブラウザで
http://localhost/上記コードのファイル名.php
にアクセスすれば、同様の結果になり、ブラウザを介してアクセスできる。(XAMPP経由の場合、わざわざ新規にデータベース側にアカウント登録の必要が無い)
SQLiteを使う場合編集
PHP5.4以降には、標準でSQLite(エスキューライト)という簡易データベースがPHPに付属している。
SQLiteの特徴としては、
- サーバーではない。 ※ 一方、MySQLはサーバーなので、ネットワーク設定をすればインターネット越しにMySQLにアクセスする事も可能。
- デーモンなどが常駐しない。 ※ どちらかというと、マイクロソフト Office の Access などに近い。
- MySQLにはデータ型があった。しかしSQLiteにはデータ型が無い。
などの違いがある。
このため、MySQLにあったデータ型を調べる desc コマンドも、SQLiteには無い。
- 起動方法
コマンド端末で
$ sqlite3 データベース名
と入力する。
「3」の数字が必要である。(数字を外すと、「bash: sqlite: コマンドが見つかりませんでした...」「コマンド sqlite' を提供するためにパッケージ 'sqlite2' をインストールしますか? [N/y] n」と出てきてしまい、過去バージョンのインストールになってしまう。いまさら過去バージョンは不要。)
たとえば
$ sqlite3 sample.db
など(SQLite公式サイトがこういうデータベース名)のように入力すればいい。
SQLite3が2020年現在の最新バージョンである。もし「3」の代わりに「4」とか「5」とか入れても、コマンドとして認識しない。
とにかく、
[ユーザー名@localhost ~]$ sqlite3 sample.db SQLite version 3.31.1 2020-01-27 19:55:54 Enter ".help" for usage hints. sqlite>
のように表示されるので、
sqlite>
のあとにコマンドを入れる仕組みである。
- 終了方法
.exit
というコマンドでSQLiteが終了する。ドット記号(.)が冒頭につくのに注意。ドットが無いと終了コマンドとして認識しない。
例
sqlite> .exit
使い方
sqlite>
のように表示されれば、あとはSQLコマンドを認識するので、SQLコマンドをいれればいい。
しかし、SQLiteにはデータ型が存在しないなど、MySQLとは若干の違いがあるので、入力するコマンドが若干、異なる。
たとえば
sqlite> create table testTable( gensobangou int,gensomei text,gensokigou text );
のように、入力時にデータ型(int や text など)を書いてもエラーにならないが、しかし、SQLite内部ではデータ型はまったく保存されていない。
よっ、上記コマンドでは、単にテーブルのキー名をそれぞれ入力しているだけである。
sqlite> insert into testTable (gensobangou,gensomei,gensokigou) values(1, "Hydrogen", "H" );
MySQLと同様のコマンドで、キーに値を入力できる。
テーブルの内容を表示するのも、MySQLと同様のコマンドである。つまり、
sqlite> select * from testTable;
と入力すると
1|Hydrogen|H
のように表示する。(※ 2020年5月6日にFedora32で確認。)
なお MySQLと違って、上記コマンドではSQLiteではキー名(gensobangou,gensomei,gensokigou の部分 )を表示しない。
- ^ 松浦健一郎『確かな力が身につく PHP「超」入門』、SBクリエイティブ、、、2016年10月3日初版 第1刷 発行、194ページ