PHP MySQLからデータを引いて、ページング

<?php

define('DB_HOST', 'localhost');
define('DB_USER', 'dbuser');
define('DB_PASSWORD', 'xxxx');
define('DB_NAME', 'testdb');
define('COMMENTS_PER_PAGE', 5);

if (preg_match('/^&#91;1-9&#93;&#91;0-9&#93;*$/', $_GET&#91;'page'&#93;)){
$page = (int)$_GET&#91;'page'&#93;;
} else {
  $page = 1;
}

error_reporting(E_ALL & ~E_NOTICE);

try {
  $dbh = new PDO
('mysql:host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASSWORD);
} catch (PDOException $e){
  echo $e->getMessage();
  exit;
}

// select * from comments limit OFFSET,Count
// page offset Count
// 1 0 5
// 2 5 5
// 3 10 5

$offset = COMMENTS_PER_PAGE * ($page -1);
$sql = "select * from comments limit ".$offset.",".COMMENTS_PER_PAGE;
$comments = array();
foreach ($dbh->query($sql) as $row){
 array_push($comments, $row);
}
$total = $dbh->query("select count(*) from comments")->fetchColumn();
$totalPages = ceil($total / COMMENTS_PER_PAGE);

$from = $offset + 1;
$to = ($offset + COMMENTS_PER_PAGE) <  $total ? ($offset + COMMENTS_PER_PAGE): $total;

?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>コメント一覧</title>
</head>
<body>
    <h1>コメント一覧</h1>
    <p>全<?php echo $total; ?>件中、<?php echo $from; ?>件~<?php echo $to; ?>件を表示しています</p>
    <ul>
    <?php foreach ($comments as $comment) : ?>
      <li><?php echo htmlspecialchars($comment&#91;'comment'&#93;,ENT_QUOTES,'UTF-8'); ?></li>
    <?php endforeach; ?>
  </ul>
  <?php if($page > 1) : ?>
  <a href="?page=<?php echo $page-1; ?>">前へ</a>
<?php endif; ?>
  <?php for ($i = 1; $i <= $totalPages; $i++): ?>
    <?php if ($page == $i) : ?>
  <strong><a href="?page=<?php echo $i; ?>"><?php echo $i; ?></a></strong>
<?php else: ?>
    <a href="?page=<?php echo $i; ?>"><?php echo $i; ?></a>
<?php endif; ?>
  <?php endfor; ?>
  <?php if ($page < $totalPages): ?>
  <a href="?page=<?php echo $page+1; ?>">次へ</a>
<?php endif; ?>
</body>
</html>

SQLでデータを作ります。

create database testdb;
grant all on testdb.* to dbuser@localhost identified by 'xxxx';
use dotinstall_paging_php

create table comments (
 id int not null auto_increment primary key,
 comment text,
 created datetime,
 modified datetime
);

insert into comments (comment, created, modified) values
('コメント1', now(), now()),
('コメント2', now(), now()),
('コメント3', now(), now()),
('コメント4', now(), now()),
('コメント5', now(), now()),
('コメント6', now(), now()),
('コメント7', now(), now()),
('コメント8', now(), now()),
('コメント9', now(), now()),
('コメント10', now(), now()),
('コメント11', now(), now()),
('コメント12', now(), now()),
('コメント13', now(), now()),
('コメント14', now(), now()),
('コメント15', now(), now()),
('コメント16', now(), now()),
('コメント17', now(), now()),
('コメント18', now(), now());

%e7%84%a1%e9%a1%8c

PDOで条件付き検索

<?php

define('DB_DATABASE', 'name_db');
define('DB_USERNAME', 'dbuser');
define('DB_PASSWORD', 'xxxx');
define('PDO_DSN', 'mysql:dbhost=localhost;dbname=' . DB_DATABASE);

try {
  $db = new PDO(PDO_DSN, DB_USERNAME, DB_PASSWORD);
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  // $stmt = $db->prepare("select score from users where score > ?");
  // $stmt->execute([60]);

  //$stmt = $db->prepare("select name from users where name like ?");
  //$stmt->execute(['%t%']);

  $stmt = $db->prepare("select score from users order by score desc limit ?");
  $stmt->bindValue(1, 1, PDO::PARAM_INT);
  $stmt->execute();

  $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
  foreach($users as $user){
    var_dump($user);
  }
  echo $stmt->rowCount() . "records found.";

  /*
  (1) exec(): 結果を返さない、安全なsql
  (2) query(): 結果を返す、安全、何回も実行されない
  (3) prepare(): 結果を返す、安全対策が必要、複数回実行
  */

  // $stmt = $db->prepare("insert into users(name, score) values(?, ?)");
  // $stmt->execute(['tagu', 44]);
  // $stmt = $db->prepare("insert into users(name, score) values(:name, :score)");
  // $stmt->execute(['name'=>'nishikawa', ':score'=>76]);
  // echo "inserted: " . $db->lastInsertId();

  // bindValue 値をbind
  // bindParam 変数への参照をbindValue

  // $stmt = $db->prepare("insert into users(name, score) values(?, ?)");

  // $name = 'tagu';
  // $stmt->bindValue(1, $name, PDO::PARAM_STR);
  // $score= 23;
  // $stmt->bindValue(2, $score, PDO::PARAM_INT);
  // $stmt->execute();
  // $score= 44;
  // $stmt->bindValue(2, $score, PDO::PARAM_INT);
  // $stmt->execute();
  //$stmt->bindParam(2, $score, PDO::PARAM_INT);
  // $score = 52;
  // $stmt->execute();
  // $score = 44;
  // $stmt->execute();
  // $score = 2;
  // $stmt->execute();

} catch (PDOException $e){
  echo $e->getMessage();
  exit;
}

phpでPOD接続

PODとはphp data obujectの略で、データベース接続クラスのことです。 PHPは標準でMySQLやPostgreSQLやSQLiteなど、色々なデータベースに接続するための命令が用意されています。PDOを使うことで、どのデータベースを利用する場合でも同じ関数を使うことができますので、もし将来データベースを変更することがあっても、PDOオブジェクトを作成する時に指定したパラメータだけを変更するばいいことになります。

index.php

<?php

define('DB_DATABASE', 'name_db');
define('DB_USERNAME', 'dbuser');
define('DB_PASSWORD', 'xxxx');
define('PDO_DSN', 'mysql:dbhost=localhost;dbname=' . DB_DATABASE);

try {
  $db = new PDO(PDO_DSN, DB_USERNAME, DB_PASSWORD);
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  // insert
  $db->exec("insert into users (name, score) values('yamada', 55)");
  echo "user added!";

  // disconnect
  $db = null;

} catch (PDOException $e){
  echo $e->getMessage();
  exit;
}

%e7%84%a1%e9%a1%8c

prepared

<?php

define('DB_DATABASE', 'name_db');
define('DB_USERNAME', 'dbuser');
define('DB_PASSWORD', 'xxxx');
define('PDO_DSN', 'mysql:dbhost=localhost;dbname=' . DB_DATABASE);

try {
  $db = new PDO(PDO_DSN, DB_USERNAME, DB_PASSWORD);
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  /*
  (1) exec(): 結果を返さない、安全なsql
  (2) query(): 結果を返す、安全、何回も実行されない
  (3) prepare(): 結果を返す、安全対策が必要、複数回実行
  */

  $stmt = $db->prepare("insert into users(name, score) values(?, ?)");
  $stmt->execute(['name', 44]);
  echo "inserted: " . $db->lastInsertId();

} catch (PDOException $e){
  echo $e->getMessage();
  exit;
}

php簡易掲示板

投稿内容はdatファイルに格納します。

<?php

$dataFile = 'bbs.dat';

// csrf
session_start();

function setToken(){
  $token = sha1(uniqid(mt_rand(), true));
  $_SESSION&#91;'token'&#93; = $token;
}
function checkToken(){
  if (empty($_SESSION&#91;'token'&#93;) || ($_SESSION&#91;'token'&#93; !=$_POST&#91;'token'&#93;)){
    echo "不正なpostが行われました!";
    exit;
  }
}

function h($s){
  return htmlspecialchars($s, ENT_QUOTES, 'utf-8');
}

if($_SERVER&#91;'REQUEST_METHOD'&#93; == 'POST' &&
  isset($_POST&#91;'message'&#93;) &&
  isset($_POST&#91;'user'&#93;)){
    checkToken();

  $message =trim($_POST&#91;'message'&#93;);
  $user = trim($_POST&#91;'user'&#93;);

 if($message !== ''){

   $user = ($user === '') ? 'ななしさん' : $user;

   $message = str_replace("\t", '', $message);
   $user = str_replace("\t", '', $user);
   $postedAt = date('Y-m-d H:i:s');

  $newData = $message . "\t" . $user . "\t" . $postedAt. "\n";

  $fp = fopen($dataFile, 'a');
  fwrite($fp, $newData);
  fclose($fp);
   }
} else {
  setToken();
}

$posts = file($dataFile, FILE_IGNORE_NEW_LINES);

$posts = array_reverse($posts);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>簡易掲示板</title>
</head>
<body>
  <h1>簡易掲示板</h1>
  <form action="" method="post">
    message: <input type="text" name="message">
    user: <input type="text" name="user">
    <input type="submit" value="投稿">
    <input type="hidden" name="token" value="<?php echo h($_SESSION&#91;'token'&#93;); ?>">
  </form>
  <h2>投稿一覧(<?php echo count($posts); ?>件)</h2>
  <ul>
    <?php if (count($posts)) : ?>
      <?php foreach ($posts as $post) : ?>
        <?php list($message, $user, $postedAt) =  explode("\t", $post); ?>
        <li><?php echo h($message); ?>(<?php echo h($user); ?>)-<?php echo h($postedAt); ?></li>
      <?php endforeach; ?>
       <li></li>
    <?php else : ?>
    <li>まだ投稿はありません。</li>
  <?php endif; ?>
  </ul>
</body>
</html>

%e7%84%a1%e9%a1%8c