質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

1755閲覧

phpの参照渡し

SugiuraY

総合スコア318

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2016/10/19 12:32

お世話になっております。
下記のコードについて、function triming (&$item)の引数が参照渡しでなければならない理由がどうしてもわかりません。
本当に初心者で申し訳ないのですが、順番にどの様に値が渡されてどの点で問題が起きるのか噛み砕いてご教示を願いたいです。
以下のコールバック関数を使用する場合の、定義関数の第1引数は、配列の要素であることは理解しているのですが、それぞれの配列の要素にtrimを使い改めて引数である$itemに適用後の要素を格納し配列を再構築しているのかと想像しているのですが、、参照渡しである理由が飲み込めません。。
宜しくお願い申し上げます。
注)実際に配列は多次元連想配列のため、recurciveをつかっており、下記は単純化のため、シンプルな配列の例にしております。

$array=array(' good','bad');
function triming (&$item)
{
$item= trim($item);
}
array_walk_recursive($array,'triming');

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kei344

2016/10/19 14:07

コードはコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
SugiuraY

2016/10/19 14:53

すみません、携帯からの投稿でも、コードブロックは使用可能ですか?ボタンが見当たらなかったため、そのままペーストしてしまいました。また、パソコンを開けたら修正致します。
kei344

2016/10/19 15:04

携帯電話からの投稿のUIがわかりませんが、```(バッククオート3つ)で囲み、前後に改行をいれればコードブロックになると思いますよ。
guest

回答2

0

ベストアンサー

それは、array_walk_recursive関数(リファレンス)の性質によります。この関数は、

array 配列の各要素にユーザー定義関数 callbackを適用します。

ふつうの関数なら返り値で結果を返せばいいのですが、array_walk_recursiveのコールバック関数は実行されるだけで返り値は使わないので、引数を参照にして直接書き換える以外に元の配列を変更する手段はありません。

なお、再帰的でなくていい(配列が1段だけ)という状態でしたら、array_mapを使えば「返り値を配列にセットする」という挙動になるので、標準関数のtrimをそのまま使えます。

php

1$array = array(' good','bad'); 2$array = array_map('trim', $array);

投稿2016/10/19 23:02

maisumakun

総合スコア145201

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2016/10/20 03:29

ご回答有難うございます。なるほど、返り値を使わないのですね、とても不便に感じますが、そのような仕様になっている理由がきっとあるのでしょう。素人なりに配列の各要素に自己定義関数を適用>適用後の要素を含む配列を返すといのが自然であると勝手に解釈をしておりました。。 反対に返り値を返さないコールバック関数にどんな使い勝手があるのかが想像ができませんが、、、なにかこれぞというものはあるのでしょうか? また、バックスラッシュについて、失礼致しました。単なるエスケープですね。うっかりです。
maisumakun

2016/10/20 04:14

たとえば、「全要素を表示する」ような用事を行うときに、返り値は不要ですよね。
SugiuraY

2016/10/20 04:23

funtion($item){ print_r ($items); } のようなイメージでしょうか?(このコールバック関数の場合はもしかしたらechoでもすべての配列の要素を表示してくれるのかもしれませんが)
maisumakun

2016/10/20 04:31

そんな感じですね(たしかに、array_walk_recursiveである以上、更にprint_rで再帰的に表示させる必要もないですが)。
SugiuraY

2016/10/20 04:33

ご回答有難うございます。なるほど、たしかにそのように使用する場合は考えられますね。とても理解が深まりました。 お力添えに深謝を申し上げます!
guest

0

途中経過を表示するように、少し追記しました。なお引数の前の '&' はあえて抜いています。

php:

1<?php 2$array=array(' good','bad'); 3function triming ($item) 4{ 5 $item= trim($item); 6 echo "Inside trimming(): $item="; 7 var_dump($item); 8} 9array_walk_recursive($array,'triming'); 10echo "Outside trimming(): \$array="; 11var_dump($array);

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

bash

1$ php a.php 2Inside trimming(): good=string(4) "good" 3Inside trimming(): bad=string(3) "bad" 4Outside trimming(): $array=array(2) { 5 [0]=> 6 string(5) " good" 7 [1]=> 8 string(3) "bad" 9}

このように、関数の中ではちゃんと変換されているのに、呼び出し元では値が元に戻って
しまっています。

'&' をつけないと「値渡し」になります。値だけが渡されますので、関数側ではその値を
受け取るために、$item という仮の変数(仮引数と呼ばれます)が一時的に用意され、
その中に渡ってきた値がコピーされます。

関数の中ではその変数の中身を自由に変更できますが、コピーを変更しているので、元の
『$arrayの領域』は変更されません。

関数から戻ったあとは『元の$array』を表示していますので、当然中身も変わりません。

'&' をつけて参照渡し(マニュアルではリファレンス渡し)にした場合、
$array と $item が同じところ(実際に値が格納される領域)を指すようになります。
$item を変えると、即時に $array のその部分も上書きされます。このため、関数から
戻った後も、変更内容が保持されます。

投稿2016/10/19 13:51

hotta

総合スコア1613

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2016/10/19 15:22

ご回答ありがとうございます。 すなわち、仮引数である$itemはどんなに計算や代入をしても、functionの中でしか有効とならないという事でしょうか。 1.例えば以下の様な場合には、3ではなく5で計算の結果を返してくれる聞いて気がしますが、何が違うのでしょう?そもそも、上記の関数もreturn trim($item)にしてらその計算の結果を常に返してくるという考えは誤りなんでしょうか? function tashi($a){ return $a+2; } $b=3; echo tashi($b); 2.純粋に初めて見たのですが、 Outside trimming(): \$array="; のバックスラッシュはどんな意味でしょうか? 宜しくお願い申し上げます。
hotta

2016/10/20 00:16

> 仮引数である$itemはどんなに計算や代入をしても、functionの中でしか有効とならない ('&' なしの場合は)そう考えていただいて結構です。 あと、$item の値を変更するのと、($item が関係するかどうかに関わらず) 何らかの値を返すというのは別の話です。 『return $a + 2;』は計算結果を返します($a自体は変わらない)が、 return の場合、どう呼び出すかで意味合いが変わってきます。 呼び出したほうが echo tashi($a); とか $b = tashi($a); のように 返された値を使えば返された値(足し算の結果)が使われますし、 単に tashi($a); とした場合、エラーにはなりませんが、返された値は 消えてしまい、このケースでは呼んでも呼ばなくても同じ結果になります。 バックスラッシュ(=円マーク)は後続の文字(このケースでは '$')の 意味を打ち消します。円マークを付けないと、$array のところがその時点の $array の内容で置き換わります。円マークを付けることで、'$array' と そのまま表示されます。詳細はマニュアルを参照してください。 http://php.net/manual/ja/regexp.reference.escape.php
SugiuraY

2016/10/20 04:35

ご回答有難うございます。 無事理解し、納得することができました。 御礼申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問