Edited at

PHPにおけるvoidとは何か

More than 1 year has passed since last update.

PHPの文脈ではvoidはいくつかの異なる意味で利用されます。


そもそもvoidってなんだ


void(ボイド)は、プログラミング言語において、「何もない」といった意味の型などに使われる名前である。プリミティブとしてキーワードないし予約語であることも多い。


(void (コンピュータ) - Wikipedia1より引用)

C言語では「引数を受け取らず、引数を返さない」関数のプロトタイプを void f(void); のように記述できますね。


PHPマニュアルにおけるvoid

PHP: 本ドキュメントにおける疑似的な型および変数 - Manualに記載があります。


void

返り値の型が void である場合は、 返り値に意味がないことを表します。パラメータ一覧で void が使用されている場合は、 その関数がパラメータを受け付けないことを表します。


具体的には以下の通りです。


header

(PHP 4, PHP 5, PHP 7)

header — 生の HTTP ヘッダを送信する


説明

void header ( string $string [, bool $replace = true [, int $http_response_code ]] )


(PHP: header - Manualより引用)

これは、header()の実行結果に何の値も返さないことを意味します。

つまり、 $result = header($str);var_dump(header($str)); のような実行は無意味です。無意味ではありますが、これらの返り値は実際にはNULLになります。


get_defined_vars

(PHP 4 >= 4.0.4, PHP 5, PHP 7)

get_defined_vars — 全ての定義済の変数を配列で返す


説明

array get_defined_vars ( void )


(PHP: get_defined_vars - Manualより引用)

今度は引数が ( void ) です。これは特別な引数を期待するわけではなく、リストの中身がvoid、つまり空なので、引数には何も受け取らないことを意味します。このような関数に対して引数を渡しても多くの場合エラーにはなりませんが、無意味です。


PHPDocにおけるvoid

PHPマニュアルと同じく@returnタグなどで利用できる擬似的な型です。

引数を返さない関数は、PHPDocの型注釈記法では以下のように書きます。

/**

* @return void
*/

function hoge()
{
echo "hoge";
}

後述する型宣言とは異なりPHPDocは実行時には何の影響も及ぼしません。実際ただのコメント行なので、PHP 7.1未満でも当然利用することができます。


PHP7.1の型宣言におけるvoid

PHP7から返り値に型宣言が書けるようになりましたが、PHP7.1ではさらに機能が強化され、voidキーワードが書けるようになりました。

function hoge(): void

{
echo "hoge";
}

この型宣言は、型を返すとエラーになることが特徴です。

<?php

function a(): void
{
echo "a";
if (false) {
return true;
}
}

a();
// Fatal error: A void function must not return a value in /in/ZidNI on line 7

この特徴は、実際に実行されない処理であってもreturnに返り値を書くだけでエラーとして捕捉できるので安心です。

以下のように引数のないreturnは問題ありません。

function b(): void

{
if (foo()) {
return;
}

bar();
buz();

return; // 省略可能
}


ツールのサポート

PhpStormは返り値がvoidである関数の返り値を利用しようとすると、わかりやすくハイライトされます。

PhpStorm: 'void' function 'a' result used

また、これはPhanのような単体の静的解析ツールでも検出できます。

funcs.php:8 PhanTypeVoidAssignment Cannot assign void return value


PHPDocと型宣言、どちらで書くか

PHPDoc形式の型注釈@return voidと、PHP 7.1形式の型宣言: voidのどちらで書くかは、「そのコードベースがPHP 7.1以降専用か否か」だけで選んで支障ありません。

さきほど紹介した二つのツール、PhpStormとPhanは、この二種類の表記を同じように見做しますので、どちらで書いても同じです。: void型宣言は特別なツールを追加で導入しなくても、PHP 7.1があれば定義時に間違って返り値を返してしまったことを簡単に検出できるのでおすすめです。

二種類の形式を両方書くことも可能ですが、冗長なだけなので両方書くメリットはありません。どちらかだけを書けば大丈夫です。金輪際PHP7.1未満でコードを動かすことはないと明らかならば、: void型宣言に統一した方が簡潔になります。

広く利用されたいライブラリなどでPHP7.1未満をサポートしたいならば、PHPDoc形式の@return voidで書いた方が無難です。


どうでもいいこと

<?php

namespace
{
const void = null; // 1

goto void;

function void( // 2
$void = void // 3
): void // 4
{
var_dump(void);
return void; // 5
}
}

namespace void
{
void:
void(void);
}

voidはPHP7.1で擬似的な型名としてその他の予約語に追加されました。


PHP 7.0.0 以降は、これらのキーワードを プロパティや定数の名前として使えるようになりました。 また、クラスやインターフェイスそしてトレイトのメソッド名としても使えるようになりました


その前の、PHP7.0でメソッドとしての使用が許可されたキーワードのリストとは異なり、「その他の予約語」はクラス名(トレイト・インターフェイスを含む)として利用できないだけで、関数名・メソッド名・名前空間・定数名・gotoのラベルなどのシンボルとして、問題なく定義することができます。

そんなことをわざわざやっても特にメリットはないので、PHPおもしろ知識として留めておいてください…… 忘れて問題ないです。

void, void, void, void, void, void, void, void, void, void, void, void...


[追記] PHPにvoidキャスト/演算子はない


また、JavaScriptなど、言語によっては、void演算子が存在する。JavaScriptのvoid演算子は、オペランドの式を評価してその値を得る計算をおこなうが、その値は捨てられ、値を返さない。C言語における、値を捨てることを明示するためのvoid型へのキャスト(たとえば、(void)printf("Hello"); のように書く)に似ている。


PHPには、この用途の(void)はありません。その代りと言ってはなんですが、(unset)キャストが存在します。これは、どんな値をもnullにキャストします。

Psy Shell v0.8.17 (PHP 7.1.14  cli) by Justin Hileman

>>> (unset)[]
=> null
>>> (unset)fopen('php://stdout', 'w');
=> null
>>> $a = "AAAAA";
=> "AAAAA"
>>> (unset)$a
=> null
>>> $a
=> "AAAAA"
>>> unset($a)
>>> $a
PHP Notice: Undefined variable: a on line 1

注意したいのは、(unset)キャストはどんな値が来てもnullを返しますが。変数を未定義状態に戻すわけではありません。それはunset($v)です。

こんなの何の訳に立つのか? ふつうに null って書けばいいじゃね? なんでこんなキャストがあるの?

さあ、わかりません……。むかしそうやってぼやいてたら誰かに納得のいく説明をしてもらった気がしますが、僕はもう覚えてないので、きっとどうでもいい感じのことです。


脚注