47
39

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 3 years have passed since last update.

PHPの文と式

Last updated at Posted at 2020-03-27
1 / 51

このスライドは突発で開催された**PHPerKaigi Online(仮)**でしゃべるために用意されたものです。


前回のあらすじ


PHPカンファレンス関西2020 【公募セッション募集について】 今年も例年どおりPHPカンファレンス関西では公募セッション枠として、有志PHPerの皆様からセッションのスピーカーを募集します。 ※LTのスピーカー募集については後日発表予定です。


コードを自在に操るためのPHP文法入門

PHPのソースコードを正確に検査したり、ソースコードの一部を書き換えたいと思ったことはありませんか? PHPにはPHP-Parserという構文解析ライブラリがあり、静的解析ツールのPHPStanやリファクタリングツールのRectorはPHP-Parserをベースにしたプラグインでソースコードを検査したり、ソースコードを書き換えたりすることができます。

しかしながら、構文木を操作するには普段何気なくPHPコードを書く以上のプログラミング言語についての知識が求められます。この発表では構文木を取り扱う前提となるプログラミング言語についての知識、PHP-Parserの構造、PHPStanとRectorそれぞれの拡張方法と実例についても紹介します。


誠に残念ではございますが、新型コロナウイルスの感染拡大を鑑み、PHPカンファレンス関西2020の開催を断念することになりました。楽しみにして頂いた皆様に心よりお詫び申し上げます。公式サイトの告知は追って更新します。


:cry:


気をとりなおして


こういう記事を先週書きました

Qiita echoとprintの違い


echoとprintの違いを要約すると

  • 関数マニュアルに載っているが関数ではない
  • echoprintは出力バッファに書き込む
  • echoだがprint(式文)
  • echoは複数の引数、printは1つの引数

echoだがprint(式文)


というわけで、今回は文と式に絞って話をします


クイズ


syntaxエラーにならないのはどちらでしょう。

echo print 1;
print echo 1;

プログラミング言語を習うと初めにこういうことを習う


入門者に叩き込まれる謎の用語

  • if文で条件分岐をします
  • for文で繰り返します
  • 代入文で変数に値を入れます
  • return文で関数から値を返します

たいていの人は、それが何なのか悩む前に使いかたをマスターしてしまうので何も困らない


PHPにはいろんな文と式がある


キーワードのリスト

PHPマニュアルに載っているPHPのキーワード(予約語)のリスト


このリストには文と式がごちゃごちゃに載っている


プログラムの構成要素を分解してみよう


PHPの場合

<?php

function sum(array $values)
{
    $sum = 0;
    
    foreach ($values as $v) {
        $sum += $v;
    }

    return $sum;
}

意味をつけていく

<?php // ← PHP開始タグ

function sum(array $values) // ← 関数定義
{
    $sum = 0; // 変数代入
    
    foreach ($values as $v) { // foreach
        $sum += $v; // 変数代入
    }

    return $sum; // 戻り値
}

文と式を分けていく

<?php // ← PHP開始タグ(特殊)

function sum(array $values) // ← 関数定義「文」
{
    $sum = 0; // 変数代入「式」
    
    foreach ($values as $v) { // foreach「文」
        $sum += $v; // 変数代入「式」
    }

    return $sum; // 戻り値「文」
}

PHPには書く場所が限られる要素がある


PHPではこういうコードは書けない

<?php

const A = hoge();

function a($a = foo())
{
    return $a;
}

PHPではこういうコードは書けない

何を当たり前のことをという

foreach (function a(){return [];} a() as $b) {
    return $b;
}

式(expression, expr)とは何か


式はこんなところに書ける

ここに書けるのは式

  • ifの条件を書くところ if ($v == 1)
  • whileの条件を書くところ while (count($a) !== 0)
  • 関数呼び出しの引数 foo($a + 1)
  • 代入の右辺 $v = 30 * MINUTES
  • return に書けるもの return foo() + bar()
  • echo, print, <?= ?> に渡せるもの

よく使われる式 (その1)

  • 関数・メソッド呼び出し printf() $obj->foo() $func()
  • 演算子式
    • 論理否定 !$foo
    • 比較式 $a == $b $user instanceof User
    • 算術演算 1 + 1
    • 短絡論理演算子 $n <= 0 && $n < 24 foo() or bar()
    • インクリメント・デクリメント $i++ --$i

よく使われる式 (その2)

  • 無名関数式 function ($a) { return $a * 2; } fn($a) => $a * 2
  • 無名クラス new class('foo'){ function __construct($name) { $this->name = $name; } }
  • 配列リテラル [$a, $b, 'foo' => foo()]
  • 三項演算子 $foo == 'bar' ? 'A' : 'B'

よく使われる式 (その3)

  • () 式のグルーピング
  • isset, empty
  • eval
  • assert
    • PHP5では関数だったがPHP7で言語構造になった
  • exit die
  • 変数・スカラーリテラル・定数・マジカル定数
    • $a 1 "a" true HOGE

式の特徴

  • 式の中に再帰的に式を書ける

こんなものも式

  • $a = include __DIR__ . '/config.php'
  • $b = eval('return 1 + 1;')
  • $c = yield 1;
  • $d == 1 or die()
  • $e = foo() and print $e

とてもひどいことに、式の種類によって () が省略可能かどうかがバラバラで、個別に覚えないといけない。(または編集中にsyntax checkする)


式はこんなところにも書けるぞ

  • foreachas の左側
  • foreach (foo() as $f)
  • include, requireの引数
  • 式の中には任意の組み合せの式が書ける
    • ただし [] + 1 のような式はPHP7ではパーサーレベルで怒られるようになった


よく使われる文

  • 関数/メソッド定義文 function
  • クラス定義文 class interface use
  • 制御構文 while for do foreach
  • 出力文 echo <?=
  • 定数定義文 const FOO = 1;
  • インポート文 use use function use const use ... as
  • 式文 $v = BAR ?: buz();

文にはこんなものもある

  • キャスト (int) (string) (bool)
  • トレイトの追加 use
  • 実行ディレクティブ declare(strict_types=1);
  • HTML出力 ?><?php の外側
  • 静的変数 static $var
  • グローバル変数 global $var

文の分類


文の特徴

  • 式は任意の式を組み合わせられる
  • 文は文ごとに決まったルールがある
    • 式を書けるもの
    • 式と文を書けるもの
    • それ以外の記述ができるもの

式文 (expression statement)

<?php
require_once ___DIR__ . '/foo.php'; // require式だけの文
$n = 100; // 代入式だけの文
printf("%f", 1.1); // 関数呼び出しだけの文
assert($n < 100); // assert式だけの文
print 1; // print式だけの文

式文 (expression statement)

  • 全ての式は ;または?> で区切ることで文になる。
  • 式を式文(expression statement)と呼ぶ。
    • ただし、;がつくからと言って式文とは限らない。
  • この記事のコード注釈で「式」と書いた場合は、その式を内包する文である

複文

複数の文が書ける。普通はifforeachと組み合わせて使う。

{
    foo();
    bar();
}

条件文 if, else, elseif

このには文を一つだけ書けるが、通常は if ($cond) echo 1; のように {} を付けずに書くことは好まれず、 if (true) { echo 1; } のように複文を使って改行して書くことが好まれる。

if () 
if ()  else  
if ()  elseif () 
if ()  elseif ()   else  

別構文

if ():  endif;
if ():  else:  endif;
if ():  elseif: ()  endif;
if ():  elseif: ()   else  endif;

繰り返し while

while () 

別構文

while ():  endwhile;

複雑な繰り返し for

for (最初に実行される式; 継続判定式; 繰り返しごとに実行される式) 

別構文

for (最初に実行される式; 継続判定式; 繰り返しごとに実行される式):  endfor;

文と式文のややこしいケース

初心者殺し

// これは関数定義文なので最後に ; は要らない
function f() { ... }

// これは変数代入式なので最後に ; が必要
$f = function() { ... };

代入式と代入文のややこしいケース

// これは代入式
$a = 1;

// これはstatic変数の宣言文
static $b = 1;

特別な式が書ける文

  • 静的に解決できる式だけ書ける (PHP 7)
    • const
    • プロパティ
const SEC = 1;
const MINUTES = 60 * SEC;
const HOUR = 60 * MINUTES;

クイズの解答


echo print 1; // echo は文なので式(print)を引数にとれる
print echo 1; // echo は文なので式(print)の引数に書けない
47
39
14

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
47
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?