2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Dockerの公式コンテナにPHP7.1が現れたので、マニュアルサイト見ながら動作確認してみる

Posted at

みなさんこんにちは

いつの間にかDockerの公式コンテナの正式なlatestバージョンが7.1になりました。
私のようにソースコードのビルドめんどくさいマンはdockerイメージとして配布されると、とても導入しやすくなるので、嬉しい限りなのです。

そんなわけで、せっかくPHPのdockerイメージをバージョンアップしたので、動作確認をしてみようと思います。
PHPのマニュアルサイトは異様なほど充実しており、それを見ただけで、どんな変更があるかわかるのが便利です。
そこで、マニュアルにある新機能をソースコードをパクりながら動作確認していきましょう。
検証自体は他の人が先にやってたりしますが、自分でも動かしてみて、実行結果を見ていくのもいいんじゃないかって思いました。

各新機能の動作確認

追加された新機能の中で、面白いものをピックアップしていきます。

nullable

なんかちょっと前に流行ったnullableがPHPにも登場です。
「null安全でない言語なんてもはや言語ではないわ!」「nullable最高や!」みたいなエンジニアにも、「あ、PHPもnullableありますよ!」っていえますな。

これは関数の引数もしくは関数の返り値に型を指定した際、引数の値にnullを許すというものです。
書式は簡単で、指定した方の先頭に「?」を付け加えるだけです。
サンプルコードを上述のマニュアルから持ってきますが。。。現時点(2016/12/15)では、そのままコピると関数の二重定義で動かないので、ちょっとだけ変えて動作確認してみましょう。

nullable.php
<?php

function testReturn(): ?string
{
    return 'elePHPant';
}

var_dump(testReturn());

function testReturn2(): ?string
{
    return null;
}

var_dump(testReturn2());

function test(?string $name)
{
    var_dump($name);
}

test('elePHPant');
test(null);
test();

こいつを実行すると以下の通りの挙動になります。

# php nullable.php
string(9) "elePHPant"
NULL
string(9) "elePHPant"
NULL

Fatal error: Uncaught ArgumentCountError: Too few arguments to function test(), 0 passed in /var/dev/nullable.php on line 24 and exactly 1 expected in /var/dev/nullable.php:17

最後のエラーに関しては、nullは許すけど、引数に何も与えないとかは許さないって感じですね。
この辺は返り値にも当てはまるようです。

nullable2.php
<?php

function testRet(): ?string
{
    return null;
}

function testRet2(): ?string
{

}

var_dump(testRet());
var_dump(testRet2());

に対して、

# php nullable2.php
NULL

Fatal error: Uncaught TypeError: Return value of testRet2() must be of the type string or null, none returned in /var/dev/nullable2.php:11

void関数

前述のように、返却値を返すか、返却値すら返さないかは大きな違いになります。
返却値を全く返さない場合は、そういう関数であることを指定する別の方があり、それがvoidです。

void.php
<?php

function test(): void
{
    echo '1';
}

function test2(): void
{
    echo '2';
    return;
}

function test3(): void
{
    echo '3';
    return null;
}

var_dump(test());
var_dump(test2());
var_dump(test3());

これを動作させてみると、

# php void.php

Fatal error: A void function must not return a value (did you mean "return;" instead of "return null;"?) in /var/dev/void.php on line 17

関数を読み込んだ時点で、エラーが出ます。
返却値はnullですら許しません。
一方でtest3の部分を削除して動作させると以下のようになります。

# php void.php
1NULL
2NULL

返却値がないので、var_dumpの値はnullを示しています。

Symmetric array destructuring

話は変わって、多重代入ですね。
今までlistで書いていた多重代入が配列表記でできます。「list」って打たなくて良くなりました。
関数で複数のパラメータを返却したいとかに使うのですが、ちょっとだけ楽にかけそうです。

list.php
<?php

$data = [
    [1, 'niisan'],
    [2, 'harukao'],
];

function retList()
{
    return [3, 'remore'];
}

// list() 形式
list($id1, $name1) = $data[0];
echo "$id1: $name1\n";
list($id2, $name2) = retList();
echo "$id2: $name2\n";

foreach ($data as list($id, $name)) {
    echo "$id: $name\n";
}

echo "////////////////\n";

// [] 形式
[$id1, $name1] = $data[0];
echo "$id1: $name1\n";
[$id2, $name2] = retList();
echo "$id2: $name2\n";

foreach ($data as [$id, $name]) {
    echo "$id: $name\n";
}

実行するとこんな感じになります。

# php list.php
1: niisan
3: remore
1: niisan
2: harukao
////////////////
1: niisan
3: remore
1: niisan
2: harukao

定数のアクセス範囲の指定

クラスなどで定数のアクセス範囲を設定できるようになりました。内部的に使っているのみで、外からは参照できない定数を作るのに便利です。

const.php
<?php
class ConstDemo
{
    const PUBLIC_CONST_A = 1;
    public const PUBLIC_CONST_B = 2;
    protected const PROTECTED_CONST = 3;
    private const PRIVATE_CONST = 4;
}

echo ConstDemo::PUBLIC_CONST_A . "\n";
echo ConstDemo::PUBLIC_CONST_B . "\n";
echo ConstDemo::PROTECTED_CONST . "\n";

これを実行すると以下のようになります。

# php const.php
1
2

Fatal error: Uncaught Error: Cannot access protected const ConstDemo::PROTECTED_CONST in /var/dev/constAccessor.php:12
Stack trace:
# 0 {main}
  thrown in /var/dev/const.php on line 12

アクセス範囲がpublicでない定数にアクセスしようとしてFatalエラーが出ています。

iterable型

イテレータとして使える変数の擬似型としてiterableが追加されました。
iterable型はforeachで次々値を取り出せる変数なので、foreachが含まれる関数に数値とか渡されて、変なnoticeが出なくて良くなりますね。

iterable.php
<?php

function iterableFunc(iterable $trav)
{
    foreach ($trav as $val) {
        echo "$val";
    }

    echo "\n";
}

// generator
function gen() {
    for ($i = 0; $i < 10; $i++) {
        yield $i;
    }
};

iterableFunc(['pen', 'pine', 'apple', 'pen']);
$gen = gen();
iterableFunc($gen);
iterableFunc('noiterable');

実行時の動作は以下のとおりです。

# php iterable.php
penpineapplepen
0123456789

Fatal error: Uncaught TypeError: Argument 1 passed to iterableFunc() must be iterable, string given, called in /var/dev/iterable.php on line 21 and defined in /var/dev/iterable.php:3
Stack trace:
# 0 /var/dev/iterable.php(21): iterableFunc('noiterable')
# 1 {main}
  thrown in /var/dev/iterable.php on line 3

これは関数のタイプヒントでの例ですが、返却値に対しても指定できます。

iterable2.php
<?php

function retIterable($switch = true): iterable
{
    if ($switch) {
        return [1, 2, 3];
    }

    return 123;
}

var_dump(retIterable());
var_dump(retIterable(false));

結果は以下のとおりです。

# php iterable2.php
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

Fatal error: Uncaught TypeError: Return value of retIterable() must be iterable, integer returned in /var/dev/iterable2.php:9
Stack trace:
# 0 /var/dev/iterable2.php(13): retIterable(false)
# 1 {main}
  thrown in /var/dev/iterable2.php on line 9

関数やメソッドをクロージャー化する

関数やメソッドをクロージャーにすることができます。
strategyパターンとかで使えるかもしれません。

closure.php
<?php

class Logics
{
    public function getMethod($key)
    {
        return Closure::fromCallable([$this, $key]);
    }

    private function ichi(string $str) {return $str;}
    private function ni(string $str) {return $str . $str;}
    private function san(string $str) {return $str . $str . $str;}
}

$arr = ['ichi' => 'AAA', 'ni' => 'BBB', 'san' => 'CCC'];
$logics = new Logics;
foreach ($arr as $key => $str) {
    $logic = $logics->getMethod($key);
    var_dump($logic($str));
}

実行すると以下のようになります。

# php closure.php
string(3) "AAA"
string(6) "BBBBBB"
string(9) "CCCCCCCCC"

まとめ

他にも機能はあるのですが、あまり使わなそうなので、今回はここまでにしておきます。
なんだかモリモリPHPが発展しているような気がして個人的にとてもうれしいです。

今回は以上です。

参考

http://php.net/manual/ja/migration71.new-features.php
PHP7.1.0の新機能
PHP7.1のDocker

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?