概要 †
環境 †
- OS X 10.11 El Capitan
- Vagrant 1.8.1
- VirtualBox 5.0.20
- CentOS 7.2.1511
- PHP 5.6.21
PHP 5.6のインストール †
$ sudo yum -y install epel-release
$ cd /etc/yum.repos.d
$ sudo wget http://rpms.famillecollet.com/enterprise/remi.repo
$ yum list --enablerepo=remi --enablerepo=remi-php56 | grep php
- RemiリポジトリからPHP 5.6をインストール
$ sudo yum -y install --enablerepo=remi --enablerepo=remi-php56 php php-opcache php-devel php-pear php-mbstring php-mcrypt php-mysqlnd
php-devel ... PHP開発用モジュール
php-pear ... ライブラリのリポジトリ
php-opcache ... PHPスクリプトをコンパイルしキャッシュ
php-mbstring ... マルチバイト文字モジュール
php-mcypt ... 暗号化モジュール
php-mysqlnd ... MySQLモジュール
$ php -v
PHP 5.6.21 (cli) (built: Apr 28 2016 07:39:37)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
Hello World †
<?php
// 1行コメント
# 1行コメント
/*
複数行コメント
複数行コメント
複数行コメント
*/
echo "hello from the TOP!"
?>
<!DOCTYPE html>
<html lang="ja">
<body>
<p>Hello World <?php echo "from PHP";?></p>
<body>
</html>
ビルトインWebサーバーを起動 †
$ php -S 192.168.33.10:8000
PHP 5.6.21 Development Server started at Sat May 21 05:27:21 2016
Listening on http://192.168.33.10:8000
Document root is /home/vagrant/php_lessons
Press Ctrl-C to quit.
変数とデータ型 †
<?php
$msg = "hello from the TOP!";
echo $msg;
- データ型
- 文字列 string
- 数値 integer, float
- 論理値 boolean / true false
- 配列
- オブジェクト
- null
var_dump($msg);
定数 †
<?php
define("MY_EMAIL", "yuji@dot.com");
echo MY_EMAIL;
// MY_EMAIL = "hogehoge"; // エラー発生
var_dump(__LINE__); // 現在の行(何行目か)を表示
var_dump(__FILE__); // ファイル名を表示
var_dump(__DIR__); // ディレクトリ名を表示
数値の計算 †
- 演算子:+ - * / % **(PHP5.6-)
$x = 10 % 3; // 1
$y = 30.2 / 4; // 7.55
var_dump($x);
var_dump($y);
$z = 5;
$z++; // 6
var_dump($z);
$z--; // 5
var_dump($z);
$x = 5;
$x += 2; // $x = $x + 2;と同じ。その他の四則演算も利用可能
var_dump($x);
文字列 †
- "":特殊文字(\n, \t) 変数展開可
- '':通常の文字、変数展開は不可
$name = "yuji";
$s1 = "hello $name!\nhello again!"; // 特殊文字、変数の展開が有効
$s2 = 'hello $name!\nhello again!'; // 特殊文字、変数の展開が無効
var_dump($s1);
var_dump($s2);
- ブラウザコンソールより実行結果のソースコードを表示
string(24) "hello yuji!
hello again!"
string(26) "hello $name!\nhello again!"
// 以下の何れの記述でも可
$s1 = "hello $name!\nhello again!";
$s1 = "hello ${name}!\nhello again!";
$s1 = "hello {$name}!\nhello again!";
$s = "hello" . "world"; // helloworld
var_dump($s);
if文による条件分岐 †
- 比較演算子:> < >= <= == === != !== ※ === !==の場合はより厳密に値と型を含めて比較
- 論理演算子:and && , or || , !
$score = 85;
if ($score > 80) {
echo "great!";
} elseif ($score > 60) {
echo "good";
} else {
echo "so so ...";
}
真偽値 †
- falseになる場合
- 文字列:空, "0"
- 数値:0, 0.0
- 論理値:false
- 配列:要素の数が0
- null
$x = 5;
if ($x) { // $xが0でない場合はtrue($x == true)
echo "great";
}
// 真であれば$aを$maxに代入、偽であれば$bを$maxに代入。
$max = ($a > $b) ? $a : $b;
// 下記のif文で置き換え可能
if ($a > $b) {
$max = $a;
} else {
$max = $b;
}
switch文による条件分岐 †
$signal = "red";
switch ($signal) {
case "red":
echo "stop!";
break;
// $signalが"blue"または"green"の場合
case "blue":
case "green":
echo "go!";
break;
case "yellow":
echo "caution";
break;
default: // どの条件にも該当しない場合
echo "wrong signal";
break;
}
while文によるループ処理 †
// 0〜9を表示
$i = 0;
while ($i < 10) {
echo $i;
$i++;
}
// 0〜9を表示
do {
echo $i;
$i++;
} while ($i < 10);
- while文とdo..while文の違い:条件が偽の場合、while文は処理を行わないがdo..while文は1回は処理を行う
for文によるループ処理 †
// 0〜9を表示
for ($i = 0; $i < 10; $i++) {
echo $i;
}
- break:ループを抜ける
- continue:それ以降の処理を実行せずに次のループに移る
for ($i = 0; $i < 10; $i++) {
if ($i === 5) {
// break; // $iが5の時にループを抜けるため0〜4を表示
// continue; // $が5の時のみ以降の処理をスキップするので5を除いた0〜9を表示
}
echo $i;
}
配列 †
$sales = array(
"tanaka" => 200,
"suzuki" => 800,
"sato" => 600, // 最後の行のカンマは省略可
);
// PHP5.4 or later
$sales = [
"tanaka" => 200,
"suzuki" => 800,
"sato" => 600, // 最後の行のカンマは省略可
];
var_dump($sales["suzuki"]); // 800
$sales["suzuki"] = 900; // 900を代入
var_dump($sales["suzuki"]); // 900
// 配列のkeyを省略(0から連番でkeyが自動で付与される)
$colors = ["red", "blue", "pink"];
var_dump($colors[1]); // blue
foreach †
$sales = [
"tanaka" => 200,
"suzuki" => 800,
"sato" => 600,
];
foreach ($sales as $key => $value) {
echo "($key) $value ";
}
// 配列のkeyが省略されている場合
$colors = ["red", "blue", "pink"];
foreach ($sales as $value) {
echo "$value ";
}
- コロン構文(foreach if while for)
$colors = ["red", "blue", "pink"];
foreach ($colors as $value) :
echo "$value ";
endforeach;
<?php
$colors = ["red", "blue", "pink"];
?>
<ul>
<?php foreach ($colors as $value) : ?>
<li><?php echo "$value "; ?></li>
<?php endforeach; ?>
</ul>
関数 †
function sayHi () {
echo "hi!";
}
sayHi();
function sayHi ($name) {
echo "hi!" . $name;
}
sayHi("Tom");
sayHi("Bob");
- 引数の初期値を設定(引数が指定されなかった場合に初期値を使用)
function sayHi ($name = "Tanaka") {
echo "hi!" . $name;
}
sayHi();
function sayHi ($name = "Tanaka") {
return "hi! " . $name;
}
$s = sayHi();
var_dump($s);
ローカル変数 †
$lang = "ruby"; // グローバル変数
function sayHi ($name) {
$lang = "php"; // ローカル変数
echo "hi!" . $name;
}
sayHi("Tom");
var_dump($lang); // ruby
便利な組み込み関数 †
$x = 5.6;
echo ceil($x); // 6:切り上げ
echo floor($x); // 5:切り捨て
echo round($x); // 6:四捨五入
echo rand(1, 10); // 1〜10の乱数
$s1 = "hello";
$s2 = "ねこ";
echo strlen($s1); // 5:文字数カウント
echo mb_strlen($s2); // 2:文字数カウント(マルチバイト)
printf("%s - %s - %.3f", $s1, $s2, $x);
$colors = ["red", "blue", "pink"];
echo count($colors); // 配列の要素カウント
echo implode("@", $colors); // 配列の要素を指定した区切り文字で連結
クラスとインスタンス †
- Property:クラスが持つ変数
- Method:クラスが持つ関数
- instance:クラスを元に実際にデータを持たせたオブジェクト
- インスタンスを作成する際にはnew演算子を利用
- Constructor:クラスがインスタンス化される際に必ず呼ばれるメソッド
クラスを作成 †
class User { // クラス名の1文字目は大文字
// property
public $name;
// constructor
public function __construct($name) { // 引数はインスタンス作成時に渡される値
$this->name = $name; // 引数で渡された値をUserクラスのnameプロパティにセット
}
// method
public function sayHi() {
echo "hi, i am $this->name!";
}
}
$tom = new User("Tom");
$bob = new User("Bob");
echo $tom->name; // Tom
$bob->sayHi(); // hi, i am Bob!
クラスの継承 †
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function sayHi() {
echo "hi, i am $this->name!";
}
}
class AdminiUser extends User { // Userクラスの子クラス
public function sayHello() {
echo "hello from Admin!";
}
// override
public function sayHi() {
echo "hi, i am $this->name!";
}
}
$tom = new User("Tom");
$steve = new AdminUser("Steve");
echo $steve->name;
$steve->sayHi();
$steve->sayHello();
- overrideを禁止する場合はfinal修飾子を利用(final public function ...)
192.168.33.1:63620 [500]: / - Cannot override final method User::sayHi() in /home/vagrant/php_lessons/index.php on line **
アクセス権 †
- private:そのクラス内からのみアクセス可能
- protected:そのクラス+親子クラス内からのみアクセス可能
- public:どこからでもアクセス可能
staticキーワード †
- インスタンス化しなくても使えるプロパティやメソッドを定義可能
class User {
public $name;
public static $count = 0;
public function __construct($name) {
$this->name = $name;
self::$count++; // インスタンス作成の度にカウントアップ
}
public function sayHi() {
echo "hi, i am $this->name!";
}
public static function getMessage() {
echo "hello from User class!";
}
}
User::getMessage(); // インスタンス化せずに直接呼び出し可能
$tom = new User("Tom");
$bob = new User("Bob");
echo User::$count; // 2
抽象クラス †
- 他のクラスに継承されることを前提にそのクラス自体はインスタンス化不可のクラス
abstract class BaseUser {
public $name;
abstract public function sayHi(); // この時点で実装は不要
}
class User extends BaseUser {
public function sayHi() { // 抽象クラス内のメソッド名&アクセス権を同じにする必要あり
echo "hello from User";
}
}
$tom = new User("Tom");
$tom->sayHi();
インターフェース †
- 任意のクラス内で必ず実装するメソッドを定義するためのもの
interface sayHi {
public function sayHi(); // インターフェースではアクセス権は必ずpublic
}
interface sayHello {
public function sayHello();
}
class User implements sayHi, sayHello { // クラスの継承と違い複数インターフェースを実装可能
public function sayHi() {
echo "hi";
}
public function sayHello() {
echo "hello";
}
}
$tom = new User("Tom");
$tom->sayHi();
$tom->sayHello();
- 抽象クラスとの違い
- 抽象クラスではプロパティも宣言できるがインターフェースではpublicなメソッドのみ宣言可能
- クラスの親子関係は1対1だが、インターフェースはクラスに複数実装することが可能
外部ファイルの読み込み †
- 外部ファイルを読み込む方法
- require:fatal error(処理が終了)
- require_once
- include:warning(処理は続行)
- include_once
- require_once, include_onceはPHPが自動的にそのファイルが読み込まれているかチェックして読み込まれていたらスキップ
<?php
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function sayHi() {
echo "hi, i am $this->name!";
}
}
require "User.class.php";
$bob = new User("Bob");
$bob->sayHi(); // hi, i am Bob!
- autoload:クラスが未定義の(requireされていない)場合にもインスタンス作成時に自動的に必要なクラスファイルを自動で読み込む仕組み
spl_autoload_register(function($class) {
require $class . ".class.php";
});
$bob = new User("Bob");
$bob->sayHi(); // hi, i am Bob!
名前空間 †
- 名前空間:ファイル名の衝突を防ぐために使用
- User.class.php
<?php
namespace Yuji\Lib;
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function sayHi() {
echo "hi, i am $this->name!";
}
}
require "User.class.php";
$bob = new Yuji\Lib\User("Bob");
$bob->sayHi(); // hi, i am Bob!
require "User.class.php";
use Yuji\Lib as Lib; // use Yuji\Lib; でも書き換え可
$bob = new Lib\User("Bob");
$bob->sayHi(); // hi, i am Bob!
例外処理 †
function div($a, $b) {
echo $a / $b;
}
div(7, 2);
div(5, 0); // PHP Warning発生
PHP Warning: Division by zero in /home/vagrant/php_lessons/index.php on line 4
function div($a, $b) {
try {
if ($b === 0) {
throw new Exception("cannot divide by 0!");
}
echo $a / $b;
} catch (Exception $e) {
echo $e->getMessage();
}
}
div(7, 2);
div(5, 0);
- PHP側で事前に用意されている例外もあり明示的なthrow不要
- 独自にExceptionクラスを継承して処理を変えることも可能
フォームからのデータ処理 †
- フォームに入力されたデータが8文字より長いかチェックするサンプル
<?php
$username = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') { // $_SERVERはPHPにて定義済み変数
$username = $_POST['username']; // $_POSTはPHPにて定義済み変数
$err = false;
if (strlen($username) > 8) {
$err = true;
}
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Check username</title>
</head>
<body>
<form action="" method="POST">
<input type="text" name="username" placeholder="user name" value="<?php echo htmlspecialchars($username, ENT_QUOTES, 'UTF-8'); ?>">
<!-- $usernameが投稿する度に消えないようvalueの中に埋め込む -->
<!-- PHPではユーザーからの入力データはそのまま使用不可のためhtmlspecialcharsで悪意のある文字列をエスケープ -->
<input type="submit" value="Check!">
<?php if ($err) { echo "Too long!"; } ?>
</form>
</body>
</html>
Cookieを利用 †
setcookie("username", "yuji"); // key-valueでセット
- Cookieを利用(testcookie.php)
echo $_COOKIE['username'];
- index.php実行後(Cookieセット後)にブラウザ側に値が保存されるためtestcookie.phpを実行するとその値が表示される
- 有効期限の設定 ※有効期限を明示的に設定しない場合はブラウザを閉じるまで有効
setcookie("username", "yuji", time()+60*60); // 60秒×60分=1時間
setcookie("username", "yuji", time()-60*60); // 60秒×60分をマイナス
セッションを利用 †
- Cookieとは違いサーバー側に値を保存
- Cookieはブラウザ側に値を保存するため改ざんの危険性あり
session_start(); // セッションを利用する場合に必ず宣言
$_SESSION['username'] = "yuji";
- セッションを利用(testsession.php)
session_start();
echo $_SESSION['username'];
unset ($_SESSION['username']);