作成日:2021/04/12 更新日:2022/01/27

#1 PHPとjsで簡単なアプリを作ってみよう

今回はこのようなアプリを作ってみたいと思います。
自分で登録した名前をdiv要素化して、その要素をJavaScriptドラッグして配置場所を保存しておくというアプリです。 ドラッグされた要素は、PHPでxy座標をデータベースに保存させます。

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 {
  border2px dashed #ccc;
  margin:15px;
  border-radius6px;
  height600px;
}

/*drag*/
#drag-area {
  position: relative;
  height500px;
  width:980px;
  margin5px auto;
  border1px solid #333;
  border-radius6px;
}
.drag {
  position: absolute;
  padding1em;
  color#666;
  border-radius5px;
  background#efefef;
  border3px solid #ccc;
}
.name {
  font-size:12px;
}
簡単なhtml文書とcssですね。(めんどうのでresetの重要なものだけ上部に入れました)cssは1枚でいきます。 どのセレクタがどんな役割を持っているのか、文章を見ただけで把握しましょう。
ディレクトリはこんな感じです。
アドレス(localhost:8001)を入力するとブラウザではこんな表示になると思います。

#2 PHPのエラーをブラウザに表示させる

PHPでは間違った記述をしているときに、エラーを表示してくれる機能がありますので、表示させる内容を明示しておきます。 内容を確認し、修正できるようにしましょう。
<?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 . '<br>';
?>
</body>
</html>
エラーが表示されます。どこが間違っているのか、表示される内容を読み解き、解決してみましょう。
 Notice: Undefined variableアン ディファインド バリアブル: = 注意: 未定義の変数です
 Parse error: syntax errorシンタックス エラー, = 解析エラー: 構文エラーです
 Fatal error: Call to undefined functionコール トゥー アンディファインド ファンクション = 致命的なエラー: 未定義の関数を呼び出してます
 Warning: Missing argumentミッシング アーギュメント = 警告: 引数がありません
英語で表示されますが、翻訳ソフトなどを利用し積極的に読み解いていくようにしましょう。
ブラウザクリックで翻訳できるアドオン(Chrome版 Firefox版もあります) S3.Translator

▼解説
表示する/非表示にする

#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の初期設定値です。

データベースに接続する前にデータベースの情報を入れておきます。 接続先名やユーザーIDやパスワードは基本的には変わらないのでdefine()関数で定義してあげます。 例えるなら、FTPを設定する時にアプリの画面でホスト名やユーザID、パスワードを登録したのと同じようなことです
define()関数は、定数(変わらないもの)を定義(決める)する関数です。
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;
}
?>
データベースに接続するときにはtry catch構文で、PDOクラスをnewする(PDOインスタンスを生成)というこの構文を思い出しましょう。※PDOは「PHP Data Objects」の略。
dbhはデータベースハンドルの略で、ハンドルは車のハンドルをイメージしてください。データベースを運転できる人という感じです。

▼解説
解説は一度目を通し、仕組みをなんとなく把握できたら忘れても構いません。
表示する/非表示にする

データベースのデータ内容をブラウザで確認する

<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>
<div id="drag-area">内に、データベースに接続して取ってきたデータを出力しましょう。 結果はこうなります。
Array
(
  [id] => 1
  [name] => 新垣結衣
  [left_x] => 810
  [top_y] => 56
)
きちんと、データが取れていることが確認できます。
▼解説
表示する/非表示にする

データベースのデータを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>
PHP_EOL(End Of Line)は、ソース上で改行されるPHPの定義済み定数です。ドットで繋いで文末に入れて使用します。 上記は、<div id="drag-area">内に、データベース内の情報を、↓このように埋め込みたい場合のやり方になります。
<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>
ここでの「1」「新垣結衣」「810」「56」の部分が、データベースのレコードに格納されているデータになります。 たくさんレコード(行)があれば、その行が終わるまで、テンプレートに沿って データだけが違う、たくさんの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出力
id1$result['id']
name新垣結衣$result['name']
left_x810$result['left_x']
top_y56$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>