作成日:2021/04/12 更新日:2022/01/27
#1 PHPとjsで簡単なアプリを作ってみよう
今回はこのようなアプリを作ってみたいと思います。

今回は理解度を優先させるために、機能を全てindex.phpに記述します。
簡単なhtml文書とcssですね。(めんどうのでresetの重要なものだけ上部に入れました)cssは1枚でいきます。
どのセレクタがどんな役割を持っているのか、文章を見ただけで把握しましょう。



PHPの準備
phpファイルはhtmlファイルと同じだと考えて大丈夫です。 拡張子をindex.htmlではなくindex.phpにしてマークアップします。 イメージとしてはhtml文書を作って、その中にphpの機能を追記していく感じになります。 サイトの機能が複雑になると「MVC(Model View Controller)」という考え方になり、 機能(PHP)と見栄え(html+css)を分けて書く事になります。今回は理解度を優先させるために、機能を全てindex.phpに記述します。
構造体を作る
まずは以下の文章をコピーして、index.phpとcssを作ってください。
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>sortable</title>
  <link href="css/style.css" rel="stylesheet">
</head>
<body>
<div id="wrapper">
<div id="drag-area">
drag area
</div>
</div>
</body>
</html>
/*reset*/
body,div,p{margin:0;}
.clearfix:after {
    content:"";
    display:block;
    clear:both;
}
/*frame*/
body {
  height:100%;
  color:#ccc;
  font-size:10px;
}
#wrapper {
  border: 2px dashed #ccc;
  margin:15px;
  border-radius: 6px;
  height: 600px;
}
/*drag*/
#drag-area {
  position: relative;
  height: 500px;
  width:980px;
  margin: 5px auto;
  border: 1px solid #333;
  border-radius: 6px;
}
.drag {
  position: absolute;
  padding: 1em;
  color: #666;
  border-radius: 5px;
  background: #efefef;
  border: 3px solid #ccc;
}
.name {
  font-size:12px;
}


#2 PHPのエラーをブラウザに表示させる
PHPでは間違った記述をしているときに、エラーを表示してくれる機能がありますので、表示させる内容を明示しておきます。
内容を確認し、修正できるようにしましょう。
Notice: Undefined variable: = 注意: 未定義の変数です
Parse error: syntax error, = 解析エラー: 構文エラーです
Fatal error: Call to undefined function = 致命的なエラー: 未定義の関数を呼び出してます
Warning: Missing argument = 警告: 引数がありません
英語で表示されますが、翻訳ソフトなどを利用し積極的に読み解いていくようにしましょう。
ブラウザクリックで翻訳できるアドオン(Chrome版 Firefox版もあります) S3.Translator
▼解説

アプリケーション > MAMP > bin > php > [MAMPで指定したphpバージョン] > conf > php.ini
date.timezoneで検索(910行目あたり)の
指定の場所にエラーログが出力されるので便利です。
<?php
ini_set('display_errors', 1);  /* MAMPの設定次第では記述が必要 1は表示、0は非表示*/
error_reporting(-1);  /* 0は表示させない、-1はすべて表示 */
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
</head>
<body>
<?php
$name = '大橋太郎';
$measage = 'こんにちは!';
echo $names . 'さん' . $measages . '
';
?>
</body>
</html>
Notice: Undefined variable: = 注意: 未定義の変数です
Parse error: syntax error, = 解析エラー: 構文エラーです
Fatal error: Call to undefined function = 致命的なエラー: 未定義の関数を呼び出してます
Warning: Missing argument = 警告: 引数がありません
英語で表示されますが、翻訳ソフトなどを利用し積極的に読み解いていくようにしましょう。
ブラウザクリックで翻訳できるアドオン(Chrome版 Firefox版もあります) S3.Translator
▼解説
PHPのエラーを画面に表示するように設定
MAMPのphp.iniの「display_errors = 」がOFFの場合、以下の記述でPHP書類上で上書きします。 引数「1」は表示、 「0」は表示させない
ini_set('display_errors', 1);
出力するエラーの内容設定
error_reporting(引数); 引数→ 0=オフ、E_ALL=全て表示、E_ERROR=重大なエラー、E_DEPRECATED=非推奨コード など
error_reporting(E_ALL);
error_reporting(E_ALL & ~ E_DEPRECATED & ~ E_USER_DEPRECATED & ~ E_NOTICE);
文字化け対策
PDOの使い方は後ほど
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND=>"SET CHARACTER SET 'utf8'");
エラーログの確認
MAMP内にphp_error.logがあるので、stgフォルダにエイリアスを作っておくと、 エラーlogから確認することもできます。
アプリケーション > MAMP > bin > php > [MAMPで指定したphpバージョン] > conf > php.ini
date.timezoneで検索(910行目あたり)の
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
;date.timezone = "Europe/Berlin" /*Asia/Tokyoになっている場合はコメントアウトを外すのみ*/
↓
date.timezone = "Asia/Tokyo"
エラーログの書き出し
Webサーバやローカル開発環境で、エラーログファイルを書き出して確認する方法です。
if($_SERVER["HTTP_HOST"] === 'creativeresourceinstitute.com'){  /*ドメイン名*/
  ini_set('error_log', $_SERVER['DOCUMENT_ROOT'].'/../../error.log');  /*サーバ上のファイルを書き出してほしい場所*/
}else{
  ini_set('error_log', $_SERVER['DOCUMENT_ROOT'].'/../error.log');  /*ローカルのファイル場所が違う場合*/
}
指定の場所にエラーログが出力されるので便利です。
#3 データベースに接続する
データベースに接続するための前準備
接続設定の定例文を書いてみましょう。
<?php
error_reporting(-1);
/* データベース設定 */
define('DB_DNS', 'mysql:host=localhost; dbname=cri_sortable; charset=utf8');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');
?>
使い方は、define('定数名', '定数に入れる値');
 define('DB_DSN', '接続先種別:host=ローカルホスト; dbname=データベースの名前; charset=文字コード');
define('DB_USER', 'ユーザー名');
define('DB_PASSWORD', 'パスワード');
※ID, PWの「root」はMAMPに入っているMySQLの初期設定値です。define('DB_USER', 'ユーザー名');
define('DB_PASSWORD', 'パスワード');
データベースに接続する前にデータベースの情報を入れておきます。 接続先名やユーザーIDやパスワードは基本的には変わらないのでdefine()関数で定義してあげます。 例えるなら、FTPを設定する時にアプリの画面でホスト名やユーザID、パスワードを登録したのと同じようなことです

defineで作られた定数はグローバル定数となります。
グローバル定数とは、変わらないもの、上書きできないもの。プログラムのどこからでも呼び出せるもの、になります。
※DNS は Data Source Name の略。
#4 データベースのデータをhtmlで表示させる
まずデータベースに接続する

<?php
/* データベース設定 */
define('DB_DNS', 'mysql:host=localhost; dbname=cri_sortable; charset=utf8');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');
/* データベースへ接続 */
try {
  $dbh = new PDO(DB_DNS, DB_USER, DB_PASSWORD);
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e){
    echo $e->getMessage();
    exit;
}
?>
dbhはデータベースハンドルの略で、ハンドルは車のハンドルをイメージしてください。データベースを運転できる人という感じです。
▼解説
解説は一度目を通し、仕組みをなんとなく把握できたら忘れても構いません。
try catch構文(例外処理)
ある処理と、エラー時の処理を実行できる構文
try {
    /*例外が発生するおそれがあるコード*/
} catch(例外クラス名 例外を受け取る変数名){
    /*例外発生時の処理*/
}
データベース接続処理
①まずデータベースにログインする情報をPDOオブジェクトとして変数 $dbh に格納。new演算子:クラス(型)からインスタンス(実体)を生成
つまり、PHPで準備されているDB接続クラスである「PDO」を使って、今回の接続する情報を$dbhに代入している。
$dbh = new PDO(DB_DNS, DB_USER, DB_PASSWORD);
/*アロー演算子(->)を使って変数雨や関数を呼び出します。*/
$インスタンスを代入した変数 -> 呼び出したいインスタンスの、プロパティ(変数)またはメソッド(関数)名
/*属性をセットする*/
setAttribute( );
/* デフォルトのエラー発生時の処理 Exception の形で例外を投げる */
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/* パフォーマンス向上のためプリペアドステートメント機能を使う設定。*/
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
またオプションについては下の書き方Bのように、
new PDO(DB_DNS, DB_USER, DB_PASSWORD, $option);として、連想配列で値を渡すこともできます。
/*書き方A*/
$dbh = new PDO(DB_DNS, DB_USER, DB_PASSWORD);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
/*書き方B*/
$dbh = new PDO(DB_DNS, DB_USER, DB_PASSWORD, $option);
$option = [
  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  PDO::ATTR_EMULATE_PREPARES => false
]
メッセージを出力
echoで結果(エラー内容)をhtmlに出力します
echo $e->getMessage();
終了
メッセージを出力し、現在のスクリプトを終了する
exit;

接続のときの基本的な記述内容になるので、別のアプリを作ったときも同じ構文になります。
データベースのデータ内容をブラウザで確認する
<div id="drag-area">
<?php
$sql = 'SELECT * FROM sortable';
$stmt = $dbh->query($sql);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
print_r ($result);  /* print_rはechoのようなもので、配列の中身を出力できる*/
?>
</div>
Array
(
  [id] => 1
  [name] => 新垣結衣
  [left_x] => 810
  [top_y] => 56
)
▼解説
  ■MySQLで使えるSQL文(SQLステートメント)の SELECT * FROM sortable> という文字列を、変数$sqlに格納

stmt (ステートメント:文章 の略語)
PDO::FETCH_ASSOC (カラム名で添字を付けた配列を返す)
$sql = 'select * from sortable';
$stmt = $dbh->query( $sql );
$stmt = $dbh->query( 'select * from sortable' );  /*このように書いても同様*/
/* 1行ずつ取得 = 配列(whileでループ)*/
$result = $stmt->fetch(PDO::FETCH_ASSOC);
/* 全データを配列に変換 = 多次元配列(foreachでループ)*/
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
↓
/* 配列なので、foreachを使おう */
foreach ($stmt as $result){
  echo $result['添字']
}
print_r($result);
print_r ($result);       /* 配列が出力される */

stmt (ステートメント:文章 の略語)
PDO::FETCH_ASSOC (カラム名で添字を付けた配列を返す)
データベースのデータをhtml構文でレイアウト
<div id="drag-area">
<?php
$sql = 'SELECT * FROM sortable';
$stmt = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
/* while ($result = $stmt->fetch(PDO::FETCH_ASSOC)){ while文だとこのような書き方*/
/* 配列なので、foreach文を使ってみよう */
foreach ($stmt as $result){
  echo '  <div class="drag" data-num="'.$result['id'].'" style="left:'.$result['left_x'].'px; top:'.$result['top_y'].'px;">'.PHP_EOL;
  echo '    <p><span class="name">'.$result['id'].' '.$result['name'].'</span></p>'.PHP_EOL;
  echo '  </div>'.PHP_EOL;
}
?>
</div>
<div id="drag-area">
  <div class="drag" data-num="1" style="left:810px; top:56px;">
    <p><span class="name">1 新垣結衣</span></p>
  </div>
  <div class="drag" data-num="2" style="left:631px; top:302px;">
    <p><span class="name">2 北川景子</span></p>
  </div>
  <div class="drag" data-num="3" style="left:788px; top:326px;">
    <p><span class="name">3 佐々木希</span></p>
  </div>
  ︙
</div>
以下のdivの中でデータが変わる箇所【 】に変数を入れます。
<div class="drag" data-num="【ID】" style="left:【x座標】px; top:【y座標】px;">
<p><span class="name">【ID】 【名前】</span></p>
<div>
'data-num="1"'
↓
'data-num="' .$result['id']. '"'
| DBカラム名 | 中のデータ | PDO出力 | 
| id | 1 | $result['id'] | 
| name | 新垣結衣 | $result['name'] | 
| left_x | 810 | $result['left_x'] | 
| top_y | 56 | $result['top_y'] | 
そうするとこのような表示になると思います。

ここまでのindex.php
<?php
error_reporting(-1);
/* データベース設定 */
define('DB_DNS', 'mysql:host=localhost; dbname=cri_sortable; charset=utf8');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');
/* データベースへ接続 */
try {
  $dbh = new PDO(DB_DNS, DB_USER, DB_PASSWORD);
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e){
    echo $e->getMessage();
    exit;
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>8001-cri-sortable</title>
  <link href="css/style.css" rel="stylesheet">
</head>
<body>
<div id="wrapper">
<div id="drag-area">
<?php
$sql = 'SELECT * FROM sortable';
$stmt = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
foreach ($stmt as $result){
  echo '  <div class="drag" data-num="'.$result['id'].'" style="left:'.$result['left_x'].'px; top:'.$result['top_y'].'px;">'.PHP_EOL;
  echo '    <p><span class="name">'.$result['id'].' '.$result['name'].'</span></p>'.PHP_EOL;
  echo '  </div>'.PHP_EOL;
}
?>
</div>
</div>
</body>
</html>
 入門
入門 基礎
基礎 応用
応用 実践フロントエンド
実践フロントエンド 実践バックエンド
実践バックエンド デザイン
デザイン キッズ
キッズ