LoginSignup
13
3

More than 3 years have passed since last update.

一体いつから PHPがセミコロン省略できないと錯覚していた?

Last updated at Posted at 2020-11-30

・ヮ・)あ、おはようございまーす
PHPでセミコロン書いてますか?

PHPはCで実装されていてJavaに強く影響を受けているためか、行末にセミコロンを付けないといけません。

Python、Go、Swift、kotlin、Ruby、JavaScript などセミコロンを書かない(または省略してもいい)言語を使っている方からは
しばしば白い目で見られがちです(諸説あり):sob:

正直、悔しいです…:rage:

PHPの真の力(笑) を見せつけます!

【朗報】PHPにはセミコロンを省略できる構文が2つある:tada:

if

1つ目は if 文 です
PHPの if文 は、戻り値があるようなものであれば 変数だろうが、関数であろうが、 式でもいれることができます

$var = 0;
if ($var) {} // 変数はもちろんOK
if (fn() => 0) {} // クロージャー、アロー関数ももちろんOK
if ($var = 1) {} // 代入式でもOK

しかし 戻り値が無いような式は入れることができません:joy:

if (echo 'は戻り値がないのでだめ!!') {} // ただし print は戻り値があるからOK

if (function hoge() {}) {} // 関数の宣言はだめ

if (use Foo\Baz\Bar) {} // use 式もだめ

// もちろん for 文 はif 文 の条件には入れられません
for ($i = 0; $i < 10; ++$i) {}

?>

2つ目は ?>(閉じタグ) です
PHPには、?> の直前のみセミコロンを省略できる仕様があります

<?= 'こういう場合は' ?>
<?php echo '省略可能' ?>

これはHTMLに埋め込むときだけでなく、PHPのコードの中にも埋め込むことができます:clap:

<?php
function printLink(string $text, string $href) { ?>
    <!-- ここはHTML -->
    <a href="<?= $href ?>"><?= $text ?></a>
<?php }

// さらにこういうこともOK
printLink('りんく', 'https://example.com')?><?php

つまり ?><?php (閉じタグと開始タグのセット) はセミコロンであり、これを使うことでセミコロンを省略できると言えます(省略とは言えない説もあり)

セミコロン書かないでコーディングしてみる

簡単な文法だけだとつまらないので複雑めにFizzBuzz書きました

<?php

namespace FizzBuzz\Handler {

    abstract class Handler
    {
        public static function handle(int $value, callable $next): string
        {
            return static::isMatched($value) ? static::toString() : $next($value)?><?php
        }

        abstract public static function isMatched(int $value): bool?><?php // ここら辺IDEがエラー吐きがち
        abstract public static function toString(): string?><?php
    }

    final class FizzHandler extends Handler
    {

        public static function isMatched(int $value): bool
        {
            return $value % 3 === 0?><?php
        }

        public static function toString(): string
        {
            return 'Fizz'?><?php
        }
    }
    final class BuzzHandler extends Handler
    {

        public static function isMatched(int $value): bool
        {
            return $value % 5 === 0?><?php
        }

        public static function toString(): string
        {
            return 'Buzz'?><?php
        }
    }
    final class FizzBuzzHandler extends Handler
    {

        public static function isMatched(int $value): bool
        {
            return FizzHandler::isMatched($value) && BuzzHandler::isMatched($value)?><?php
        }

        public static function toString(): string
        {
            return FizzHandler::toString().BuzzHandler::toString()?><?php
        }
    }
}

namespace FizzBuzz {
    use FizzBuzz\Handler\FizzHandler?><?php
    use FizzBuzz\Handler\BuzzHandler?><?php
    use FizzBuzz\Handler\FizzBuzzHandler?><?php
    use Generator?><?php

    class FizzBuzz
    {
        private $handlerClassList = [
            FizzBuzzHandler::class,
            FizzHandler::class,
            BuzzHandler::class,
        ]?><?php

        public function __invoke(): Generator
        {
            $handler = fn($i) => (string)$i?><?php
            foreach (array_reverse($this->handlerClassList) as $handlerClass) {
                $handler = fn(int $i) => $handlerClass::handle($i, $handler)?><?php
            }
            // for 文の中のセミコロンもばっちり
            for ($i = 1?><?php $i <= 100?><?php ++$i) {
                yield $handler($i)?><?php
            }
        }
    }
}

namespace Main {
    use FizzBuzz\FizzBuzz?><?php

    foreach ((new FizzBuzz)() as $v) {
        echo $v, PHP_EOL?><?php
    }
}


※文法によってはIDEがエラーを吐くかもしれませんが実行できます

PHPは黙ってセミコロン書いたほうがいいですね

なんでこんな物を書こうと思ったのか不明です

13
3
2

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
13
3