問い合わせ管理システム

index.php

<?php

require_once('config.php');
require_once('functions.php');

session_start();
if ($_SERVER&#91;'REQUEST_METHOD'&#93; != "POST"){
  setToken();
} else {
  checkToken();

  $name = $_POST&#91;'name'&#93;;
  $email = $_POST&#91;'email'&#93;;
  $memo = $_POST&#91;'memo'&#93;;

  $error = array();

  if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
    $error&#91;'email'&#93; = 'メールアドレスの形式が正しくありません';
  }
  if($email == ''){
    $error&#91;'email'&#93; = 'メールアドレスを入力してください';
  }
  if($memo == ''){
    $error&#91;'memo'&#93; = '内容を入力してください';
  }
  if(empty($error)){
    $dbh = connectDb();

    $sql = "insert into entries
            (name, email, memo, created, modified)
            values
            (:name, :email, :memo, now(), now())";
    $stmt = $dbh->prepare($sql);
    $params = array(
      ":name" => $name,
      ":email" => $email,
      ":memo" => $memo
    );
    $stmt->execute($params);

    header('Location: '.SITE_URL.'/thanks.html');
    exit;
  }
}

?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
  <h1>お問い合わせフォーム</h1>
  <form method="POST" action="">
    <p>お名前:<input type="text" name="name" value="<?php echo h($name); ?>"></p>
    <p>メールアドレス*:<input type="text" name="email" value="<?php echo h($email); ?>">
    <?php if($error&#91;'email'&#93;){ echo h($error&#91;'email'&#93;); } ?></p>
    <p>内容*:</p>
    <p><textarea name="memo" cols="40" rows="5"><?php echo h($memo); ?></textarea>
    <?php if($error&#91;'memo'&#93;){ echo h($error&#91;'memo'&#93;); } ?></p>
    <p><input type="submit" value="送信"></p>
    <input type="hidden" name="token" value="<?php echo h($_SESSION&#91;'token'&#93;); ?>">
  </form>
  <p><a href="<?php echo ADMIN_URL; ?>">管理者ページ</a>
</body>
</html>

contact

<?php

require_once('../config.php');
require_once('../functions.php');

$dbh = connectDb();

$entries = array();

$sql = "select * from entries where status = 'active' order by created desc";

foreach($dbh->query($sql) as $row){
  array_push($entries, $row);
}

// var_dump($entries);
// exits;

?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>お問い合わせ一覧</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
</head>
<body>
  <h1>一覧データ</h1>
  <p><span id="num"><?php echo count($entries); ?></span>件あります。</p>
  <ul>
    <?php foreach($entries as $entry): ?>
      <li id="entry_<?php echo h($entry&#91;'id'&#93;); ?>"><?php echo h($entry&#91;'email'&#93;); ?>
        <a href="edit.php?id=<?php echo h($entry&#91;'id'&#93;); ?>">[編集]</a>
        <span class="deleteLink" data-id="<?php echo h($entry&#91;'id'&#93;); ?>">[削除]</span>
      </li>
    <?php endforeach; ?>
  </ul>
  <style>
  .deleteLink{
    color: blue;
    cursor: pointer;
  }
  </style>
  <p><a href="<?php echo SITE_URL; ?>">お問い合わせフォームに戻る</a></p>
  <script>
  $(function(){
    $('.deleteLink').click(function(){
      if (confirm("削除してもよろしいですか?")){
        var num = $('#num').text();
        num--;
        $.post('./delete.php', {
           id: $(this).data('id')
          }, function(rs){
            $('#entry_' + rs).fadeOut(800);
            $('#num').text(num);
          });
      }
      });
    });
  </script>
</body>
</html>

Basic認証の作り方

コマンドラインから、htpasswd -c .htpass loginnameと打ちます。

[vagrant@localhost admin]$ htpasswd -c .htpasswd password
New password:
Re-type new password:
Adding password for user password
[vagrant@localhost admin]$ ls -la
合計 12
drwxr-xr-x. 2 vagrant vagrant 4096 11月 15 00:33 2016 .
drwxrwxr-x. 3 vagrant vagrant 4096 11月 15 00:31 2016 ..
-rw-rw-r--. 1 vagrant vagrant   23 11月 15 00:33 2016 .htpasswd

続いて、.htaccessを作ります。

[vagrant@localhost admin]$ vi .htaccess
AuthType Basic
AuthName "Enter your ID & Password"
AuthUserFile /home/vagrant/contact/admin/.htpasswd
require valid-user
[vagrant@localhost admin]$ ls -la
合計 16
drwxr-xr-x. 2 vagrant vagrant 4096 11月 15 00:39 2016 .
drwxrwxr-x. 3 vagrant vagrant 4096 11月 15 00:31 2016 ..
-rw-rw-r--. 1 vagrant vagrant  122 11月 15 00:39 2016 .htaccess
-rw-rw-r--. 1 vagrant vagrant   23 11月 15 00:33 2016 .htpasswd

php さいころ

三項演算子で、条件判定し、trueならぞろ目と表示させています。

<?php

$dice = mt_rand(1, 6);
$dice2 = mt_rand(1, 6);

$zorome = ($dice == $dice2) ? true: false;

?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>さいころ</title>
  <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
</head>
<body>
  <h1>サイコロ</h1>
  <p>サイコロの目は「<?php echo $dice; ?>」と「<?php echo $dice2; ?>」でした!</p>
  <?php if ($zorome == true): ?>
    ぞろ目です!
  <?php endif; ?>
  <p><a href="<?php echo $_SERVER&#91;"SCRIPT_NAME"&#93;; ?>">もう一度!</a></p>
</body>
</html>

mt_rand()はrand()より、4倍処理が速いとphpのドキュメントに記載があります。
php mt_rand()

/*
Many random number generators of older libcs have dubious or unknown characteristics and are slow. By default, PHP uses the libc random number generator with the rand() function. The mt_rand() function is a drop-in replacement for this. It uses a random number generator with known characteristics using the » Mersenne Twister, which will produce random numbers four times faster than what the average libc rand() provides.
*/

php おみくじ

phpで配列の数はcount、ランダムはmt_rand()、ページのURLは$_SERVER[“SCRIPT_NAME”];で取得します。

<?php

$omikuji = array('小吉','大吉','中吉','凶');

$result = $omikuji&#91;mt_rand(0, count($omikuji)-1)&#93;;
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>おみくじ</title>
  <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
</head>
<body>
  <h1>おみくじ</h1>
  <p>今日の運勢は「<?php echo $result; ?>」です!</p>
  <p><a href="<?php echo $_SERVER&#91;"SCRIPT_NAME"&#93;; ?>">もう一度</a></p>
</body>
</html>

PHPのcountに関するドキュメントです。
PHP; count-Manual

wp mytheme

mythemeを作成していく際には、indexをまず作成し、それをheader, sidebar, footer, functions, style.cssなどにファイル分割していきます。wp_header、wp_footer、ウェジェットなど独自のルールが幾つかありますが、調べながら進めるとよいでしょう。
ショートコードなども簡単に作成できます。

<?php get_header(); ?>
    <div id="main" class="container">
      <div id="posts">

        <?php
        if (have_posts()):
          while(have_posts()):
            the_post();
          ?>
        <div class="post">
            <div class="post-header">
              <h2>
                <a href="<?php echo the_permalink(); ?>"><php the_title(); ?></a>
              </2>
              <div class="post-meta">
                <?php echo get_the_date(); ?>【<?php the_category(', '); ?>】
              </div>
            </div>
            <div class="post-content">
                <div class="post-image">
                  <?php if (has_post_thumbnail()): ?>
                  <?php the_post_thumbnail(array(100, 100)); ?>
                  <?php else: ?>
                    <img src="<?php echo get_template_directory_uri();?>img/noimage.png" width="100" height="100">
                  <?php endif; ?>
                </div>
                <div class="post-body">
                  <p>
                    <?php the_excerpt(); ?>
                  </p>
                </div>
            </div>
        </div>

      <?php endwhile;
    else:
      ?>
      <p>記事はありません! </p>
      <?php
    endif;
     ?>

        <div class="navigation">
            <div class="prev"><?php previous_posts_link(); ?></div>
            <div class="next"><?php next_posts_link(); ?></div>
        </div>
      </div><!-- /posts -->

      <?php get_sidebar(); ?>
    </div><!-- /main -->
<?php get_footer(); ?>
<?php

add_theme_support('menus');
register_sidebar(
  array(
    'before_widget' => '<div class="widget">',
    'after_widget' => '<div>',
    'before_title' => '<h3>',
    'after_title' => '</h3>',
  )
);

add_theme_support('post_thumbnails');

function shortcode_tw(){
  return '<a href="http://twitter.com/hogehoge">@hogehoge</a>をフォローしてね'
}
add_shortcode('tw','shortcode_tw');

WP mytheme header情報の挿入

mythemを作る場合は、stylecssにヘッダー情報を挿入しなければなりません。
wordpress codexよりコピーします。
wordpress codex them_Development

/*
Theme Name: Twenty Thirteen
Theme URI: http://wordpress.org/themes/twentythirteen
Author: the WordPress team
Author URI: http://wordpress.org/
Description: The 2013 theme for WordPress takes us back to the blog, featuring a full range of post formats, each displayed beautifully in their own unique way. Design details abound, starting with a vibrant color scheme and matching header images, beautiful typography and icons, and a flexible layout that looks great on any device, big or small.
Version: 1.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: black, brown, orange, tan, white, yellow, light, one-column, two-columns, right-sidebar, flexible-width, custom-header, custom-menu, editor-style, featured-images, microformats, post-formats, rtl-language-support, sticky-post, translation-ready
Text Domain: twentythirteen

This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned with others.
*/

そうすると、管理画面からテーマの編集ができるようになります。

開発環境にwordpressのインストール

mysqlでまずwodpress用のデータベースを作成します。

[vagrant@localhost wordpress]$ mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.34 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database wordpress;
Query OK, 1 row affected (0.11 sec)

mysql> grant all on wordpress.* to dbuser@localhost identified by 'xxxx';

その後、wp-config-sample.phpをコピーして、wp-config.phpに変更し、ファイルの中身を編集します。

define('DB_NAME', 'wordpress');

/** MySQL データベースのユーザー名 */
define('DB_USER', 'dbuser');

/** MySQL データベースのパスワード */
define('DB_PASSWORD', 'xxxx');

/** MySQL のホスト名 */
define('DB_HOST', 'localhost');

/** データベースのテーブルを作成する際のデータベースの文字セット */
define('DB_CHARSET', 'utf8');

/** データベースの照合順序 (ほとんどの場合変更する必要はありません) */
define('DB_COLLATE', '');

さらに、認証用ユニークキーを追加し、PHPサーバーを立ち上げると、wordpress初期画面が表示されるはずです。

php ビンゴシート

乱数を生成し、n個切り取る際は、range, shuffle, array_sliceで作ります。
$col = range($i * 15 + 1, $i * 15 + 15);
shuffle($col);
$nums[$i] = array_slice($col, 0, 5);
index.php

<?php
require_once(__DIR__ . '/config.php');
require_once(__DIR__ . '/Bingo.php');

$bingo = new \MyApp\Bingo();
$nums = $bingo->create();

?>
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQueryスライドショー</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <div id="container">
      <table>
        <tr>
          <th>B</th><th>I</th><th>N</th><th>G</th><th>O</th>
        </tr>
        <?php for ($i = 0; $i < 5; $i++) : ?>
        <tr>
          <?php for ($j = 0; $j< 5; $j++) : ?>
          <td><?= h($nums&#91;$j&#93;&#91;$i&#93;); ?></td>
          <?php endfor; ?>
        </tr>
      <?php endfor; ?>
      </table>
    </div>
  </body>
</html>

php基礎

データの型を確認

var_dump($msg);

定数

var_dump(__LiNE__);
var_dump(__FILE__);
var_dump(__DIR__);

文字列の連結

$s = "hello " . "world";

真偽値

$x = 5;
if ($x){
  echo "great";
}

三項演算子

$max = ($a > $b) ? $a : $b;

配列

$sales = array(
  "yama" => 200,
  "sato" => 400,
  "ito" => 600,
);
var_dump($sales["sato"]);

コロン構文

<ul>
<?php foreach ($colors as $value): ?>
  <li><?php echo "$value"; ?></li>
<?php endforeach; ?>
</ul>

クラス(オーバライドの禁止はメソッド名の前にfinalを付けます)

class User{
  public $name;
  public function __construct($name){
    $this->name = $name;
  }

  public function sayHi(){
    echo "hi, i am $this->name!";
  }
}

$tom =  new User("Tom");
$bob = new User("Bob");

echo $tom->name;
$bob->sayHi();

抽象クラス 

abstract class BaseUser{
  public $name;
  abstract public function sayHi();
}

class User extends BaseUser{
  public function sayHi(){
    echo "hello from user";
  }
}

インターフェイス

interface sayHi {
  public function sayHi();
}

interface sayHello {
  public function sayHello();
}

class User Implements sayHi, sayHello {
  public function sayHi{
    echo "hi";
  }
  public function sayHello{
    echo "hello";
  }
}

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