5.3
名前空間
名前の衝突を避けるのにつかう。
宣言
<?php
// namespaceより上はdeclareしか許されない
namespace Sample;
namespace Sample\Hoge;
考え方
namespace付のクラスなどは、ファイルシステムと同じ考え方ができる。
namespace Sample; // ここはSampleディレクトリですよー的な気持ち
function test() {} //[1]
class Hoge
{
public static function test() {} // [2]
}
test(); // [1]になる(Sample\test関数を実行)
Hoge::test(); // [2]になる(Sample\Hogeクラスのtest関数を実行)
グローバルなものへのアクセス
\test();
現在の名前空間を表す定数とキーワード
namespace Sample;
function hoge(){}
$str = __NAMESPACE__ . '\' . 'hoge'; // Sample\hoge
namespace\func(); // Sample\func関数を実行
※5.6にて、ClassName::classで完全修飾子が取得できる
エイリアス
namespace Sample;
use Hoge\Fuga\Bar as Another; // Anotherというエイリアスになる
use Hoge\Fuga\Bar; //「use Hoge\Fuga\Bar as Bar;」と一緒
use ArrayObject; // グローバルクラスのインポートになる
※5.6では関数や定数のエイリアスもできる
use function Hoge\Fuga\Bar\func;
use const Hoge\Fuga\Bar\CONS;
※7.0ではuseをグループ化できる
// 7.0以前
use Hoge\Fuga\ClassA;
use Hoge\Fuga\ClassB as B;
// 7.0以降
use Hoge\Fuga\{ClassA, ClassB as B};
遅延静的束縛
「static::」のこと。
静的継承において、親で子クラスを参照できる。
「直近」の「非転送コール」時に、
「明示されたクラス名を保持」する機能!!!!!!!
↑ 意味わからないので、わかりやすくする ↓
[1]非転送コールとは
クラス名やオブジェクトを明示的にした関数呼び出し。
Hoge::test1(); //Hogeってクラスだと明示してるよね
$hoge->test1(); //$hogeオブジェクトだと明示してるよね
※ちなみに転送コールは「self::」などのクラス内での呼び出しらしい
[2]遅延静的束縛とはこういうこと
class Hoge
{
static protected $txt = 'Hogeですよ';
public static function test1() {
return self::txt;
}
public static function test2() {
return static::txt; // 遅延静的束縛
}
}
class Fuga extends Hoge
{
static protected $txt = 'Fugaですよ';
}
/*
* test2関数はHogeクラスに存在するが、
* 非転送コール的にはFugaクラスになる。
*
* ので、static = Fugaになる
*/
Fuga::test1(); // Hogeですよ
Fuga::test2(); // Fugaですよ
[3]「直近」の「非転送コール」
「static::」にたどり着く道のりで、
複数回の非転送コールがあった場合、
「直近」の非転送コールのクラスが使用されるということ。
class Hoge
{
static protected $txt = 'Hogeですよ';
public static function test1() {
return Hoge::test2();
}
public static function test2() {
return static::txt ; // 遅延静的束縛
}
}
class Fuga extends Hoge
{
static protected $txt = 'Fugaですよ';
}
/*
* [1]Fuga::test1();
* → static = Fuga
*
* [2]return Hoge::test2();
* → static = Hoge
*
* [3]return static::txt;
* → [2]が直近として適用される
*/
Fuga::test1(); // Hogeですよ
参考:PHPを愛する試み 〜self:: parent:: static:: および遅延静的束縛〜
ジャンプラベル
goto文のこと。
goto a; // aっていうラベルに飛ぶぜ
echo 'Foo';
a:
echo 'Bar';
Bar
無名関数(クロージャ)
コールバックに使ったり、変数に関数をセットできたり。
$func = function($txt) {
echo $txt;
};
$func('Hello');
use
親のスコープの変数を引き継ぎたいときに使う。
$hoge = 'hoge';
$func = function() use($hoge) {
echo $hoge;
}
$func(); // hoge
$hoge = 'fuga';
$func(); // hoge(宣言時の値が必ず使われる)
$hoge = 'hoge';
$func = function() use(&$hoge) {
echo $hoge;
}
$func(); // hoge
$hoge = 'fuga';
$func(); // fuga
this
5.4以降のはなし。
現在のクラスにバインドされる。
Nowdoc
ヒアドキュメント→ダブルクォートで囲った扱い
Nowdoc→シングルクォートで囲った扱い(パースしない)
$txt = <<<'EOD'
hoge
fuga
EOD;
constがクラス外でも使える
<?php
const HOGE = 'Hoge';
5.4
トレイト
多重継承ができないPHPに、水平方向でメンバー(関数、プロパティ)を追加する方法。
トレイトはクラスの装備みたいなもの。
※トレイトにトレイトを装備もできる
クラスに似ているが、クラスでない。
よってインスタンス化はできない。
trait Sample
{
function hoge() {}
function fuga() {}
}
class Test
{
use Sample;
// 複数ならカンマ区切りで→「use Sample1,Sample2;」
}
優先順位
現在のクラスのメソッド > トレイトのメソッド > 継承したクラスのメソッド
名前の衝突を回避
使うもの | 説明 |
---|---|
insteadof | 使うメソッドを一つに限定する |
as | エイリアスをつける、可視性も変更できる |
class Sample
{
use A,B {
B::Method insteadof A; //Aのかわりに、BのMethodを使う
A::Method as MethodA; //MethodAという関数名で呼び出す
// A::Method as protected MethodA;
}
}
クラスのメンバーを強制させる
trait Sample
{
public function sampleFunction() {
return $this->hello(); // [1]helloがないならエラーになってしまう
}
abstract public function hello(); // [2]ので、helloを強制
}
class Test
{
use Sample;
public function hello() {} // [3]実装しなければならない
}
トレイトの存在意義
トレイトは、PHPの「多重継承ができない」ことによるデメリットを補う為に生まれた。
-> 多重継承(複数の親を持つ)のメリットは、「ソースコードの再利用性」
-> トレイトを使わない = ソースのコピペが増えがち
-> 再利用性の高いコードはトレイトにしよう!
配列の短縮構文
$array = [
'key1' => 1,
'key2' => 2,
];
(7.1)取り出した値の代入でも
[$a, $b] = [1, 2];
foreach($data as [$c, $d]) {}
関数の戻り値を配列として扱える
個人的に重要だったので。
hoge()[0];
5.5
ジェネレータ
シンプルなイテレータを実装できる。
「returnではなく、yieldで結果を返す関数を作ること」
と覚えればいいかも。
メリット
Iteratorオブジェクトを作るより楽で、
配列作ってまわすよりメモリが節約できる。
いいことづくめ。
デメリット
前にしか進めない。
戻れないので、またジェネレータ関数を使って・・みたいなことをする必要がある。
/*
* foreachでイテレータオブジェクトとして指定されたら、
* $valueに値がセットされるようにyieldを
*/
function yieldTest($num) {
for($i = 0; $i < $num; $i++) {
yield $i; // foreachの$valueに1,2,3・・とセットされる
}
}
// yieldTestはジェネレータオブジェクト
foreach(yieldTest(10) as $value) {
echo $value;
}
(7.0)return
7.0からreturnもかけるようになった。
returnの値を取得して、ごにょごにょ~みたいなことができるように?
$gen = (function gen() {
yield 1;
yield 2;
return 3;
})();
foreach($gen as $val) {}
echo $gen->getReturn(); // 3
(7.0)yieldに配列やオブジェクトを指定し、順番に処理させる
yield from [1, 2]; // 1,2と順番に返却
finally
try~catchでfinallyもかけるようになった。
foreachとlistのコンボ
$array = [
[1, 2],
[3, 4]
];
foreach($array as list($a, $b)) {
echo $a . $b;
//loop1 → 12
//loop2 → 34
}
5.6
可変長引数リスト
引数で...を使う
function hoge(...$args) { // $argsは配列として扱われる
foreach($args as $val) {
echo $val;
}
}
hoge(1, 2, 3); // $args = [1, 2, 3];
関数呼び出しで...を使う
function hoge($a, $b) {
echo $a . $b;
}
hoge(...[1, 2]);
7.0
型宣言(タイプヒンディング)の強化
関数に渡す引数の型を強制させる仕組みは古くからあったが、
7でようやくスカラー型宣言が可能に!
さらに7からは戻り値の型宣言も可能。
戻り値の型がそぐわない場合、暗黙的な変換が行われる。
function hoge(int $num) {}
function hoge(int $num): string {
return $num;
}
var_dump(hoge(1)); // string(1)
指定 | 利用最低バージョン | |
---|---|---|
クラス/インターフェイス | 指定したクラスやインターフェイスのインスタンスを強制 | PHP 5.0 |
self | そのメソッドが定義されているクラスと同じクラスのインスタンスを強制 | PHP 5.0 |
array | 配列を強制 | PHP 5.1 |
callable | callableを強制 | PHP 5.4 |
bool | booleanを強制 | PHP 7.0 |
float | floatを強制 | PHP 7.0 |
int | integerを強制 | PHP 7.0 |
string | stringを強制 | PHP 7.0 |
iterable | 配列かイテレータを強制 | PHP 7.1 |
厳密化
ファイル単位で以下を記述すると、
宣言された型以外ではエラーとなる。
<?php
declare(strict_types=1);
(7.1)nullable
型の前に?を書くと、nullも許容する。
function hoge (): ?string {}
(7.1)戻り値の型宣言にvoid
戻り値の型宣言に
「reutrn;」、もしくは何も記載しない
voidを指定できるようになった。
無名クラス
「new class」を用いて、その場限りのオブジェクトを用意する。
%obj = new class {};
7.1
クラス定数にアクセス修飾子が使える
public const HOGE = 1;