#contents ** 概要 [#c084a835] - 公式サイト:http://php.net/ - 用途:Webアプリケーション開発 ** 環境 [#e7873d4b] - 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のインストール [#o0df1904] - Remiリポジトリの追加 $ sudo yum -y install epel-release $ cd /etc/yum.repos.d $ sudo wget http://rpms.famillecollet.com/enterprise/remi.repo - yum listで提供されているパッケージを確認 $ 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の標準的なライブラリ php-devel ... PHP開発用モジュール php-pear ... ライブラリのリポジトリ php-opcache ... PHPスクリプトをコンパイルしキャッシュ php-mbstring ... マルチバイト文字モジュール php-mcypt ... 暗号化モジュール php-mysqlnd ... MySQLモジュール - PHPバージョン確認 $ 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 [#z0708051] - index.php作成 <?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サーバーを起動 [#d4e62b41] $ 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. - ブラウザで"http://192.168.33.10:8000"にアクセスすると結果を表示 - エラー時はビルトインサーバーのログを確認 ** 変数とデータ型 [#g24859d3] <?php $msg = "hello from the TOP!"; echo $msg; - データ型 -- 文字列 string -- 数値 integer, float -- 論理値 boolean / true false -- 配列 -- オブジェクト -- null - 変数のデータ型を確認する方法 var_dump($msg); ** 定数 [#c4c6605a] <?php define("MY_EMAIL", "yuji@dot.com"); echo MY_EMAIL; // MY_EMAIL = "hogehoge"; // エラー発生 var_dump(__LINE__); // 現在の行(何行目か)を表示 var_dump(__FILE__); // ファイル名を表示 var_dump(__DIR__); // ディレクトリ名を表示 ** 数値の計算 [#x226fabb] - 演算子:+ - * / % **(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); ** 文字列 [#v108abc6] - "":特殊文字(\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文による条件分岐 [#vbd9b20b] - 比較演算子:> < >= <= == === != !== &color(red){※}; === !==の場合はより厳密に値と型を含めて比較 - 論理演算子:and && , or || , ! $score = 85; if ($score > 80) { echo "great!"; } elseif ($score > 60) { echo "good"; } else { echo "so so ..."; } ** 真偽値 [#o7689904] - 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文による条件分岐 [#aabfe42d] $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文によるループ処理 [#q5449f29] - while文 // 0〜9を表示 $i = 0; while ($i < 10) { echo $i; $i++; } - do..while文 // 0〜9を表示 do { echo $i; $i++; } while ($i < 10); - while文とdo..while文の違い:条件が偽の場合、while文は処理を行わないがdo..while文は1回は処理を行う ** for文によるループ処理 [#k78322ca] // 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; } ** 配列 [#j0092afb] - key / value $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 [#n663269e] - 配列の内容をループ処理で取り出すことができる命令 $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; - HTML内にコードを埋め込む際に可読性が向上する <?php $colors = ["red", "blue", "pink"]; ?> <ul> <?php foreach ($colors as $value) : ?> <li><?php echo "$value "; ?></li> <?php endforeach; ?> </ul> ** 関数 [#b32307a9] 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); ** ローカル変数 [#c69bcf2b] $lang = "ruby"; // グローバル変数 function sayHi ($name) { $lang = "php"; // ローカル変数 echo "hi!" . $name; } sayHi("Tom"); var_dump($lang); // ruby ** 便利な組み込み関数 [#s5162564] - 数値に関する関数 $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); // 配列の要素を指定した区切り文字で連結 ** クラスとインスタンス [#q89824af] - Property:クラスが持つ変数 - Method:クラスが持つ関数 - instance:クラスを元に実際にデータを持たせたオブジェクト - インスタンスを作成する際にはnew演算子を利用 - Constructor:クラスがインスタンス化される際に必ず呼ばれるメソッド ** クラスを作成 [#x645c44e] 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! ** クラスの継承 [#d9a85671] 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 ** ** アクセス権 [#bddd9458] - private:そのクラス内からのみアクセス可能 - protected:そのクラス+親子クラス内からのみアクセス可能 - public:どこからでもアクセス可能 ** staticキーワード [#n0f55b78] - インスタンス化しなくても使えるプロパティやメソッドを定義可能 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 ** 抽象クラス [#mb61c029] - 他のクラスに継承されることを前提にそのクラス自体はインスタンス化不可のクラス 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(); ** インターフェース [#w8112065] - 任意のクラス内で必ず実装するメソッドを定義するためのもの 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だが、インターフェースはクラスに複数実装することが可能 ** 外部ファイルの読み込み [#e2f4a2c4] - 外部ファイルを読み込む方法 -- require:fatal error(処理が終了) -- require_once -- include:warning(処理は続行) -- include_once - require_once, include_onceはPHPが自動的にそのファイルが読み込まれているかチェックして読み込まれていたらスキップ - User.class.php作成 <?php class User { public $name; public function __construct($name) { $this->name = $name; } public function sayHi() { echo "hi, i am $this->name!"; } } - index.php 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! ** 名前空間 [#lb8d1729] - 名前空間:ファイル名の衝突を防ぐために使用 - 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!"; } } - index.php 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! ** 例外処理 [#b7cf6111] 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 - try-catch(例外処理) 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クラスを継承して処理を変えることも可能 ** フォームからのデータ処理 [#sb465066] - フォームに入力されたデータが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を利用 [#hc56ca34] - Cookieをセット(index.php) setcookie("username", "yuji"); // key-valueでセット - Cookieを利用(testcookie.php) echo $_COOKIE['username']; - index.php実行後(Cookieセット後)にブラウザ側に値が保存されるためtestcookie.phpを実行するとその値を表示 - index.php実行後(Cookieセット後)にブラウザ側に値が保存されるためtestcookie.phpを実行するとその値が表示される - 有効期限の設定 ※有効期限を明示的に設定しない場合はブラウザを閉じるまで有効 setcookie("username", "yuji", time()+60*60); // 60秒×60分=1時間 - Cookieの削除 setcookie("username", "yuji", time()-60*60); // 60秒×60分をマイナス ** セッションを利用 [#pa14d728] - Cookieとは違いサーバー側に値を保存 - Cookieはブラウザ側に値を保存するため改ざんの危険性あり - セッションを保存(index.php) session_start(); // セッションを利用する場合に宣言 session_start(); // セッションを利用する場合に必ず宣言 $_SESSION['username'] = "yuji"; - セッションを利用(testsession.php) session_start(); echo $_SESSION['username']; - セッションの削除 unset ($_SESSION['username']);