WEBサイト作成時に発生するエラーやトラブル対応の備忘録を中心に、いろいろと書いております。


SwitchのContinueの挙動について(PHP5.6とPHP7.3の違い)

, ,

結論は大したことないんだけど、せっかくなので調べた痕跡を残しておきます。なんかの役に立つかもなので…。

ToolsetTypesが有料になってから、バージョンアップが出来ずにいる環境で、PHP5.6からPHP7.3に移行してみると、

Warning: “continue” targeting switch is equivalent to “break”.

というWarningが出る。

これは、PHP7.3になってから、break的に使用していたcontinueの曖昧さがWarning対象になったからという記事があった。continueを使うなら、どれだけ階層を抜けるのかを明示しなければならないらしい。

自分で書いたスクリプトじゃないので、
このSwitchの構文内の「if文」の中にあるcontinueが、ただのbreak的に使われているか、何かを抜け出すためにcontinue的に使われているのかが、判断つかない。

PHP5.6のときの挙動(期待する動き)がそもそもなんだったかを確かめなければ……ということで、テストしてみることにする。

出てくるWariningについて

Warning: “continue” targeting switch is equivalent to “break”. Did you mean to use “continue 2”? in /app/public/wp-content/plugins/types/vendor/toolset/types/embedded/includes/wpml.php on line 646

Warning: “continue” targeting switch is equivalent to “break”. Did you mean to use “continue 2”? in /app/public/wp-content/plugins/types/vendor/toolset/types/embedded/includes/wpml.php on line 663

Warning: Cannot modify header information – headers already sent by (output started at /app/public/wp-content/plugins/types/vendor/toolset/types/embedded/includes/wpml.php:663) in /app/public/wp-content/plugins/multi-device-switcher/multi-device-switcher.php on line 448

3つ目は毛色が違うので、先の二つに着目する。

まず何が書いてあるか。
Line646とLine663は同じ「function」内に記載してある。

/**
* Registers labels.
*
* @param string $prefix
* @param array $data
* @param string $context
*/
function wpcf_wpml_register_labels( $prefix, $data, $context = 'post' ) {
	foreach ( $data['labels'] as $label => $string ) {
		switch ( $context ) {
			case 'taxonomies':
			case 'taxonomy':
			case 'tax':
			$default = wpcf_custom_taxonomies_default();
			if ( $label == 'name' || $label == 'singular_name' ) {
				$string_context = array( 'domain' => 'Types-TAX' );
				$string_context['context'] = $label === 'name' ? 'taxonomy general name' : 'taxonomy singular name';
				wpcf_translate_register_string( $string_context, false, $string );
				continue;
			}
			if ( isset( $default['labels'][$label] ) && $string == $default['labels'][$label] ) {
				wpcf_translate_register_string( 'Types-TAX', $label, $string );
			} else {
				wpcf_translate_register_string( 'Types-TAX',
				$prefix . ' ' . $label, $string );
			}
			break;

			default:
			$default = wpcf_custom_types_default();

			// Name and singular_name
			if ( $label == 'name' || $label == 'singular_name' ) {
				wpcf_translate_register_string( 'Types-CPT',
				$prefix . ' ' . $label, $string );
				continue;
			}

			// Check others for defaults
			if ( isset( $default['labels'][$label] ) && $string == $default['labels'][$label] ) {
				// Register default translation
				wpcf_translate_register_string( 'Types-CPT', $label, $string );
			} else {
				wpcf_translate_register_string( 'Types-CPT',
				$prefix . ' ' . $label, $string );
			}
				break;
		}
	}
}

下記のようなプログラムを動かしてみなければ……。

$array = array();
foreach($array as $key => $value){
	switch ( $value ) {
		$a = 0;
		case 'A':
			if(D){
				$a = 4;
				continue;
			}
			if(E){
				$a = 1;
			}
		break;

		case 'B':
			$a = 2;
		break;

		case 'C':
			$a = 3;
		break;
	}
}

つまり、Aのときに、Dという条件を通ったときに、$aの値がどうなるかがPHP5.6とPHP7.3で差が出るのではないかという予想。また、DとEがtrueのときとEがfalseのときと何か変わるのかな。という実験。

所属会社:課:名前という配列を作る。

りんご会社:総務課:山本
りんご会社:開発課:鈴木
みかん会社:総務課:山田
ぶどう会社:総務課:佐藤

$array[] = array('company'=>'りんご会社','ka'=>'総務課','name'=>'山本');
$array[] = array('company'=>'りんご会社','ka'=>'開発課','name'=>'鈴木');
$array[] = array('company'=>'みかん会社','ka'=>'総務課','name'=>'山田');
$array[] = array('company'=>'ぶどう会社','ka'=>'総務課','name'=>'佐藤');


foreach($array as $value){
	$a = 0;
	switch ( $value['company'] ) {

		case 'りんご会社':
			if($value['ka'] == "総務課"){
				$a = 4;
				break;
			}
			if($value['name'] == "鈴木"){
				$a = 1;
			}
			if($value['name'] == "山本"){
				$a = 8;
			}
		break;

		case 'みかん会社':
			$a = 2;
		break;

		case 'ぶどう会社':
			$a = 3;
		break;

	}
	echo $value['name']."は".$a;
}

PHP5.6もPHP7.3も
山本は4鈴木は1山田は2佐藤は3

うーん。スキップしたいだけなら、breakで良いのではないかなぁ。switchとcaseの間に何かいれるとエラーが出るし、やはり単純に下のif文を飛ばしたかっただけなのではないかという気がしている。ので、breakでよいのかなと思います。
たとえば、「continue;」を「continue 2;」にしたら?

PHP5.6もPHP7.3だと
鈴木は1山田は2佐藤は3

Switchを最後までせずに、その上に上ってしまう。

たとえば、「continue;」を「continue 3;」にしたら?
Fatal error: Cannot ‘continue’ 3 levels in
というエラーが出ます。

なので「番号のついてない continue」は「break」と同じ挙動を想定されているのではないかと思います。

が、何故「break」にしなかったのかな。

switchとcontinueについて調べていて、わかりやすかった記事があったので紹介します。

さてますますbreakとcontinueの違いがわからなくなってきましたよ。

と、調べていて、continueについてPHPのマニュアルを見る(まず見ろよ)

continue

注意: PHP では、continue の動作に関しては switch 文がループ構造とみなされます。 continue に引数を渡さなかった場合の動きは break と同じですが、間違いの元なので警告が生成されます。 switch がループ内にある場合、 continue 2 とすると、外側のループの次回の処理から続行します。

ばっちり書いてあった……。
ので、continueはbreakにしてよかろう!

「switch文がループ構文とみなされます」というところが肝だと思いました。
だから、foreachの中のswitchの中のif分で「continue」が書かれてようが「break」が書かれていようが挙動は一緒になんですね。
これが、switchの関わらない「foreach」だったら「foreach」最初に戻るか抜け出るかみたいになるので、違うんでしょうけど……。foreachの中のswitchの上に行こうが下に行こうが次の行き先は同じというか、breakの先にcontinueでたどり着く場所があるということなので……。

ちゃんとマニュアル読めばよかったーと思ったけど、最初からマニュアルを読んでたら、多分意味がわからなかっただろうなぁと思うので、まぁ、よいのです。

なので、「Types」のプラグインの「wpml.php」のエラーが出ている場所の「continue」を「break」にして動作確認しました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください