宣言

<?php ?>

変数

$a = "Hello";

出力

echo $a;

配列

$color1 = ["red", "green", "blue"];

連想配列

$color2 = [ "1" => "red", "2" => "green", "3" => "blue" ];

配列の中身を表示する

print_r($color2); Array ( [1] => red [2] => green [3] => blue )


echo '<pre>'; var_dump($color2); echo '</pre>'; array(3) { [1]=> string(3) "red" [2]=> string(5) "green" [3]=> string(4) "blue" }

文字列演算子

結合演算子「.」 結合代入演算子「.=

クォーテーション

シングルクォーテーションで囲んだ文字列に変数を入れても、変数が展開されず文字列として扱われる。
ダブルクォーテーションを使用した場合は、変数内の値が展開される。
ヒアドキュメントは、ダブルクォーテーションで囲まれた文字列のように機能する。


if 文

if (条件) { 処理 } elseif (条件) { 処理 } else { 処理 }

switch 文

switch( 変数 ) { case 値A: 文A break; case 値B: 文B break; default: 文C }

比較演算子

a == b (値は等しい) a === b(値は等しい かつ 型も等しい) a != b (値は等しくない) a <> b (値は等しくない) a !== b(値が等しくない または 型が等しくない) a > b (より大きい) a >= b (より大きい または 等しい) a < b (より小さい) a <= b (より小さい または 等しい)

論理演算子

p && q(pかつq) p || q(pまたはq) !p (pでない)

for 文

for ($i = 0; $i < 3; $i++){ echo $i; }

※break — ループ処理を途中で終了する
※continue — ループ処理で処理をスキップする


foreach 文

foreach ($color1 as $a){ echo $a; }


foreach ($color2 as $a => $b){ echo $a; echo $b; }

while 文

$num = 0; while ($num < 5){ echo $num; $num ++; }

do-while 文

$num = 0; do{ echo $num; $num ++; }while ($num < 5)

※1回は処理が実行される


コロン構文

if

<?php if (条件): ?> <?php elseif (条件): ?> <?php else: ?> <?php endif; ?>

switch

<?php switch( 変数 ): ?> <?php case 値A: ?> <?php break; ?> <?php case 値B: ?> <?php break; ?> <?php default: ?> <?php endswitch; ?>

for

<?php for ($i = 0; $i < 3; $i++): ?> <?php endfor; ?>

foreach

<?php foreach ($color2 as $a => $b): ?> <?php endforeach; ?>

while

<?php $num = 0; ?> <?php while ($num < 5): ?> <?php $num ++; ?> <?php endwhile; ?>

三項演算子

$str = ( 条件 ) ? 'red' : 'blue'; echo ( 条件 ) ? 'red' : 'blue';

関数から複数の値を返す

// 配列で複数の値を返す function getProduct() { $name = 'ABC'; $price = 123; return array($name, $price); } // list() で受け取る list($name, $price) = getProduct(); echo $name; echo $price;

フォームからデータを受け取る(GET , POST)

・isset

if(isset($_GET['name'])){ }

if(isset($_POST['name'])){ }

・filter_input 関数

$username = filter_input(INPUT_GET, 'name');

$username = filter_input(INPUT_POST, 'name');

配列の場合。

$username = filter_input(INPUT_POST, 'name', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);

・Null 合体演算子
$_GET['user']($_POST['user'])を取得。存在しない場合は、'nobody' を使用。

$username = $_GET['user'] ?? 'nobody';

$username = $_POST['user'] ?? 'nobody';

※[ ]内は受け取りたいフォームのname属性
※参考:PHP isset vs empty vs is_null


チェックボックスが OFF でも値を送信する

チェック無しだと値が送信されないので、チェックボックスの前に同一 name で「hidden」を記述する。
チェック無しの時には「hidden」の「0」が送信される。
チェック有りの場合は、後に書かれているチェックボックスの「1」が送信される。

<input type="hidden" name="chkItem1" value="0"> <input type="checkbox" name="chkItem1" value="1">

ファイルの作成と削除

作成。
touch 関数は、ファイルの最終更新日および最終アクセス時間をセットする関数。
ファイルが存在していなかったら、ファイルが作成される。

touch('makefile.txt');

削除。


ファイルを読み込む

全文読み込む。( file_get_contents 関数 )

$filename = 'example.txt'; $content = file_get_contents($filename); echo $content;

一行ずつ配列に格納する。( file 関数 )

$filename = 'example.txt'; $lines = file($filename); print_r($lines);

改行まで格納されるので、不要な場合は「FILE_IGNORE_NEW_LINES」のフラグを第二引数に付ける。

$lines = file($filename, FILE_IGNORE_NEW_LINES);

ファイルに書き込む(file_put_contents)

上書き。

$filePath = 'file.txt'; $data = 'testMessage'; file_put_contents($filePath, $data, LOCK_EX);

追記。

$filePath = 'file.txt'; $data = "testMessage\n"; file_put_contents($filePath, $data, FILE_APPEND | LOCK_EX);

第1引数に指定したファイルが存在しない場合はファイルを作成します。
存在する場合はそのファイルを上書きします。但し、第3引数に「FILE_APPEND」が設定されている場合は追記となります。

第3引数に渡せる定数は以下の3つです。
FILE_APPEND:ファイルが存在している場合、上書きではなく追記を行う。
LOCK_EX:書き込み処理中にファイルを排他ロックする。
FILE_USE_INCLUDE_PATH:ファイルをインクルードディレクトリから探す。
複数指定したい場合は「|」(OR演算子)で連結し指定する。


パーミッション

PHP でファイルを作成,編集,削除,読み取り,一覧(ディレクトリの内容を表示)に最低必要な実行ユーザのパーミッションは、それぞれ以下のとおり。

実行ユーザの必要なパーミッション
ディレクトリファイル
作成-wx
編集--x-w-
削除-wx---
読み取り--xr--
一覧r-----

PHP で作成したファイルなら、ファイルの所有者は PHP の実行ユーザ(apacheなど)。
サーバの cron を使って PHP ファイルを実行する場合、その PHP ファイルの実行ユーザは cron の実行ユーザーになる。


変数名に連番を付加

$example1 = "例1です"; $example2 = "例2です"; $example3 = "例3です"; for ($i=1; $i<=3; $i++) { echo ${"example".$i}; }

カンマ区切りデータを配列にする

explode 関数は指定した区切り文字によって、文字列を分割して配列にする。

$data = "りんご,みかん,いちご,メロン,バナナ"; $sample = explode(',',$data);

配列をカンマ区切りに変換する

implode 関数は配列の要素を結合して文字列に変換する。
結合時に区切り文字を付加することができる。

$arr = array("taro","jiro","saburo"); $result = implode(',', $arr);

グローバル変数

$hoge = 'hoge'; function func(){ global $hoge; echo $hoge; } func();

※グローバル変数は、デフォルトでは関数外でのみ使用される変数となっていて、関数内で使うためにはグローバルで使う変数を宣言しなくてはならない。


セレクトボックスを作る

<?php $list = [ "1" => "選択1", "2" => "選択2" ]; ?> <form method="GET"> <select name="data" onChange="submit(this.form)"> <?php foreach ($list as $a => $b): ?> <option value="<?php echo $a; ?>"<?php if(isset($_GET['data']) && $_GET['data'] == $a) echo " selected"; ?>><?php echo $b; ?></option> <?php endforeach; ?> </select> </form>

※form 要素の action 属性は、HTML5 から省略が可能で、省略した場合には自身にデータを送信します。
※onChange="submit(this.form)" で、変更時 submit されます。
※foreach 文はコロン構文を使っています。


ヒアドキュメント

$site = 'guitar site WAVE'; $str = <<<EOD ようこそ。<br /> ここは、{$site} です。 EOD; echo $str;

メール送信(mb_send_mail)

mail_form.html

<html> <head> <meta charset="utf-8" /> </head> <body> <form action="./mail.php" method="post"> <p>送り先</p><input type="text" name="to"> <p>件名</p><input type="text" name="title"> <p>メッセージ</p><textarea name="message" cols="60" rows="10"></textarea> <p><input type="submit" name="send" value="送信"></p> </form> </body> </html>

mail.php

<html> <head> <meta charset="utf-8" /> </head> <body> <?php mb_language("Japanese"); mb_internal_encoding("UTF-8"); $to = $_POST['to']; $title = $_POST['title']; $message = $_POST['message']; $headers = "From: from@example.com"; if(mb_send_mail($to, $title, $message, $headers)) { echo "メール送信成功です"; } else { echo "メール送信失敗です"; } ?> </body> </html>

PHP + MySQL

env.php

<?php define('DB_HOST', 'localhost'); define('DB_NAME', 'mydb'); define('DB_USER', 'myname'); define('DB_PASS', 'password');

dbconnect.php

<?php require_once 'env.php'; function connect() { $host = DB_HOST; $db = DB_NAME; $user = DB_USER; $pass = DB_PASS; $dsn = "mysql:host=$host;dbname=$db;charset=utf8mb4"; try { $dbh = new PDO($dsn, $user, $pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false ]); return $dbh; } catch(PDOException $e) { echo '接続失敗です!' . $e->getMessage(); exit(); } }

※ PDO::ERRMODE_EXCEPTION
エラーが発生した時に、PDOException の例外を投げてくれる。

※ PDO::FETCH_ASSOC
カラム名をキーとする連想配列で返す。

※ PDO::ATTR_EMULATE_PREPARES
データベース側が持つ「プリペアドステートメント」という機能のエミュレーションをPDO側で行うかどうかを設定する。

create.php

<?php require_once 'dbconnect.php'; function blogCreate($blogs) { $sql = 'INSERT INTO table_name (title, content, category, publish_status) VALUES (:title, :content, :category, :publish_status)'; $dbh = connect(); $dbh->beginTransaction(); try { $stmt = $dbh->prepare($sql); $stmt->bindValue(':title',$blogs['title'], PDO::PARAM_STR); $stmt->bindValue(':content',$blogs['content'], PDO::PARAM_STR); $stmt->bindValue(':category',$blogs['category'], PDO::PARAM_INT); $stmt->bindValue(':publish_status',$blogs['publish_status'], PDO::PARAM_INT); $stmt->execute(); $dbh->commit(); echo 'ブログを投稿しました!'; } catch(PDOException $e) { $dbh->rollBack(); exit($e); } }

※ PDO::PARAM_INT
SQL INTEGER データ型を表します。

※ PDO::PARAM_STR
SQL CHAR, VARCHAR, または他の文字列データ型を表します。

※ カラム名と IN 句にプレースホルダは使えない。

※ トランザクション
(一連の処理の整合性を保つための機能。一つでも処理が失敗すれば、その全ての処理を無効とする。)
beginTransaction() → トランザクション開始
commit() → データベースに反映させる
rollBack() → 処理を全て無効とする
注)トランザクションを利用する場合は、テーブル形式は InnoDB を使用する。MyISAM はトランザクション機能がない。

get.php

<?php require_once 'dbconnect.php'; // データを取得する // 引数:なし // 返り値:取得したデータ function getAll() { $dbh = connect(); //①SQLの準備 $sql = 'SELECT * FROM table_name order by id'; //②SQLの実行 $stmt = $dbh->query($sql); //③SQLの結果を受け取る $result = $stmt->fetchall(); return $result; $dbh = null; } // 引数:$id // 返り値:$result function getById($id) { if(empty($id)) { exit('IDが不正です。'); } $dbh = connect(); // SQL準備 $sql = 'SELECT * FROM table_name where id = :id'; $stmt = $dbh->prepare($sql); $stmt->bindValue(':id', (int)$id, PDO::PARAM_INT); // SQL実行 $stmt->execute(); // 結果を取得 $result = $stmt->fetch(); if(!$result) { exit('ブログがありません。'); } return $result; } // レコード数を取得 // 引数:$category // 返り値:$count function countCategory($category) { $dbh = connect(); $sql = 'SELECT COUNT(*) FROM table_name WHERE category = :category'; $stmt = $dbh->prepare($sql); $stmt->bindValue(':category', (int)$category, PDO::PARAM_INT); $stmt->execute(); $count = $stmt->fetchColumn(); return $count; }

※ fetch() と fetchall()
fetch → 1行ずつ取得
fetchall → 全データを配列に変換

※ query メソッドと prepare メソッド
query メソッド → ユーザからの入力を含まない SQL を実行
prepare メソッド → ユーザからの入力を含む SQL を実行

※ SELECT 文の実行結果が存在しない場合
fetch()メソッドはfalseを返します。COUNTの場合は、ゼロを返します。
COUNTを使う方法では結果の数だけを取得するのに対し、fetch()メソッドを使う方法では結果のデータ自体を取得するので、結果の存在確認だけが目的で、結果のデータ自体が不要な場合にはCOUNTを使う方法が効率的。一方、結果のデータをその後の処理で使用する場合には、fetch()メソッドを使う方法が一度のクエリで目的を達成できるため便利。


XSS対策とCSRF対策

functions.php

<?php /** * XSS対策:エスケープ処理 * * @param string $s 対象の文字列 * @return string 処理された文字列 */ function h($s) { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } /** * エスケープ処理をして改行の前に br タグを追加する */ function hbr($s) { return nl2br(htmlspecialchars($s, ENT_QUOTES, 'UTF-8')); } /** * CSRF対策 * @param void * @return string $csrf_token */ function setToken() { // トークンを生成 $csrf_token = bin2hex(random_bytes(32)); $_SESSION['csrf_token'] = $csrf_token; return $csrf_token; }

tokeninput.php
フォームからトークンを送信

<input type="hidden" name="csrf_token" value="<?php echo h(setToken()); ?>">

tokencheck.php
トークンの照会と削除(削除することで二重送信対策になる)

<?php session_start(); $token = filter_input(INPUT_POST, 'csrf_token'); // トークンがない、もしくは一致しない場合、処理を中止 if (!isset($_SESSION['csrf_token']) || $token !== $_SESSION['csrf_token']) { exit('不正なリクエスト'); } unset($_SESSION['csrf_token']);

パスワードハッシュ

ハッシュ化

$password = 'testpass'; $hash = password_hash($password, PASSWORD_DEFAULT);

検証

password_verify($password, $hash)

戻り値:パスワードとハッシュがマッチする場合に true、それ以外の場合に false を返す。


phpinfo

<?php phpinfo(); ?>

タイムゾーンを設定する

<?php date_default_timezone_set('Asia/Tokyo'); ?>

エラーの表示/非表示

表示

<?php ini_set( 'display_errors', 1 ); ?>

非表示

<?php ini_set( 'display_errors', 0 ); ?>

マジカル定数(マジック定数)

__FILE__
この定数を呼び出したファイルのフルパス。
インクルードされるファイルの中で使用された場合、インクルードされるファイルの名前が返されます。

<?php echo __FILE__; ?>

__DIR__
この定数が呼び出したファイルのあるディレクトリのフルパス。
インクルードされるファイルの中で使用された場合、インクルードされるファイルの存在するディレクトリを返します。
ルートディレクトリである場合を除き、ディレクトリ名の末尾にスラッシュはつきません。

<?php echo __DIR__; ?>

インクルード

同じ階層の場合の例

include __DIR__ . '/test.php'; require __DIR__ . '/test.php'; include_once __DIR__ . '/test.php'; require_once __DIR__ . '/test.php';

※エラー発生時、include は後の処理も実行されるが、require は処理が中断され停止する。
※_onceは一度だけファイルを読み込み、再読み込みはしない。

一つ上の階層の場合

include __DIR__ . '/../test.php';

サーバ変数

<pre> <?php var_dump($_SERVER); ?> </pre>

※提供される情報の種類はサーバによる。


コメントアウト

// コメント または # コメント または /* コメント */


- guitar site WAVE -