web-dev-qa-db-ja.com

PHP関数の結果を逆参照するための構文

背景

私が定期的に使用する他のすべてのプログラミング言語では、関数の結果を保持するための新しい変数を宣言しなくても、関数の戻り値を操作するのは簡単です。

ただし、PHPでは、これはそれほど単純ではないようです。

example1(関数の結果は配列です)

<?php 
function foobar(){
    return preg_split('/\s+/', 'zero one two three four five');
}

// can php say "zero"?

/// print( foobar()[0] ); /// <-- nope
/// print( &foobar()[0] );     /// <-- nope
/// print( &foobar()->[0] );     /// <-- nope
/// print( "${foobar()}[0]" );    /// <-- nope
?>

example2(関数の結果はオブジェクトです)

<?php    
function zoobar(){
  // NOTE: casting (object) Array() has other problems in PHP
  // see e.g., http://stackoverflow.com/questions/1869812
  $vout   = (object) Array('0'=>'zero','fname'=>'homer','lname'=>'simpson',);
  return $vout;
}

//  can php say "zero"?       
//  print zoobar()->0;         //  <- nope (parse error)      
//  print zoobar()->{0};       //  <- nope                    
//  print zoobar()->{'0'};     //  <- nope                    
//  $vtemp = zoobar();         //  does using a variable help?
//  print $vtemp->{0};         //  <- nope     
34
dreftymac

これは特に配列の逆参照であり、現在php5.3ではサポートされていませんが、次のリリースである5.4で可能になるはずです。一方、オブジェクトの逆参照は、現在のphpリリースで可能です。この機能も楽しみです!

20
smassey

PHPは、関数からの配列結果にアクセスできません。これを問題と呼ぶ人もいれば、言語の設計方法としてこれを受け入れる人もいます。したがって、PHPを使用すると、必要なデータを抽出するためだけに不要な変数を作成できます。

だからあなたはする必要があります。

$var = foobar();
print($var[0]);
26
Ólafur Waage

配列の逆参照はPHP 5.4:の時点で可能です

例( ソース ):

function foo() {
    return array(1, 2, 3);
}
echo foo()[2]; // prints 3

PHP 5.3を使用すると、

Parse error: syntax error, unexpected '[', expecting ',' or ';' 

元の回答:

これは された尋ねられたすでに でした。答えはいいえだ。それは不可能。

To quoteAndi Gutmans このトピックについて:

これはよく知られている機能リクエストですが、PHP 5.0ではサポートされません。サポートされるかどうかはわかりません。調査と多くの検討が必要です。

また、これを見つけることができます リクエスト回数 PHPバグトラッカー。技術的な詳細については、私は 公式RFC を確認するか、 PHP Internals で質問することをお勧めします。

17
Gordon

状況に応じて、次のソリューションのいずれかを使用できます。

function foo() {
    return array("foo","bar","foobar","barfoo","tofu");
}
echo(array_shift(foo())); // prints "foo"
echo(array_pop(foo())); // prints "tofu"

または、を使用して、返された配列から特定の値を取得できます リスト()

list($foo, $bar) = foo();
echo($foo); // prints "foo"
echo($bar); // print "bar"

編集:のサンプルコード 各() 私が以前に与えたのは間違っていました。 各() キーと値のペアを返します。だから使いやすいかもしれません foreach()

foreach(foo() as $key=>$val) {
    echo($val);
}
14
Calvin

残念ながら、他のほとんどのプログラミング言語ではありますが、それを行う方法はありません。

本当にワンライナーをやりたいのなら、a()という関数を作って、次のようなことをすることができます。

$test = a(func(), 1); // second parameter is the key.

ただし、それ以外の場合、func()[1]はPHPではサポートされていません。

7
Tyler Carter

同じことを実現するラッパー関数を記述します。 PHPは型キャストが簡単なため、これはかなり制限がありません。

function array_value ($array, $key) {
return $array[$key];
}
5
Nolte

他の人が言ったように、これは不可能です。 PHPの構文ではそれが許可されていません。しかし、私は他の方向から問題を攻撃する1つの提案があります。

getBarArrayメソッドを制御していて、PHP標準ライブラリ(多くのPHP 5.2.Xホストにインストールされている)にアクセスできる場合デフォルトではPHP 5.3)でインストールされ、ネイティブのPHP配列/コレクションではなくArrayObjectを返すことを検討する必要があります。ArrayObjectsにはoffetGetメソッドがあり、これを使用して任意のインデックスを取得できるため、コードは次のようになります。

<?php
class Example {
    function getBarArray() {
        $array = new ArrayObject();
        $array[] = 'uno';
        $array->append('dos');
        $array->append('tres');
        return $array;
    }
}

$foo = new Example();
$value = $foo->getBarArray()->offsetGet(2);

また、ネイティブの配列/コレクションが必要な場合は、いつでも結果をキャストできます。

//if you need 
$array = (array) $foo->getBarArray();
5
Alan Storm

配列の最初の項目を返したいだけの場合は、current()関数を使用します。

return current($foo->getBarArray());

http://php.net/manual/en/function.current.php

5
AntonioCS

PHPではそのような式を連鎖させることはできないため、array_test()の結果を変数に保存する必要があります。

これを試して:

function array_test() {
  return array(0, 1, 2);
}

$array = array_test();
echo $array[0];
3
ashrewdmint

実際、私はそのような振る舞いを可能にするライブラリを書きました:

http://code.google.com/p/php-preparser/

関数、メソッドなど、すべてで機能します。キャッシュなので、PHP自体:)と同じくらい高速です

3
Valentin Golev

非常にゲットーですが、PHPのみを使用して実行できます。これはラムダ関数(PHP 5.3)で導入されました)を利用します。見て驚いてください(そして、ええと、おびえています):

function foo() {
    return array(
        'bar' => 'baz',
        'foo' => 'bar',
}

// prints 'baz'
echo call_user_func_array(function($a,$k) { 
    return $a[$k]; 
}, array(foo(),'bar'));

他のほとんどの言語でとても美しいことをするために私たちが経験しなければならない長さ。

記録のために、私はノルテがするのと同じようなことをします。誰かの目を出血させたらごめんなさい。

2
KyleFarris

これらはあなたの問題に取り組むいくつかの方法です。

まず、コレクションの一部ではないが、それぞれに個別の意味を持つ変数の配列を返す場合は、変数に直接名前を付けるために使用できます。

他の2つの方法は、値のコレクションである結果を返すためのものです。

function test() {
  return array(1, 2);
}   
list($a, $b) = test();
echo "This should be 2: $b\n";

function test2() {
   return new ArrayObject(array('a' => 1, 'b' => 2), ArrayObject::ARRAY_AS_PROPS);
}
$tmp2 = test2();
echo "This should be 2: $tmp2->b\n";

function test3() {
   return (object) array('a' => 1, 'b' => 2);
}
$tmp3 = test3();
echo "This should be 2: $tmp3->b\n";
2
ivanjovanovic

これは行き過ぎですが、本当に必要な場合は1行にまとめてください。


return index0( $foo->getBarArray() );

/* ... */

function index0( $some_array )
{
  return $some_array[0];
}

2
Petruza

さらに調査した結果、答えはノーだと思います。そのような一時変数は、関数から返された配列を処理するための標準的な方法です。

これはPHP 5.4から変更されるようです。

また、この回答は元々、このバージョンの質問に対するものでした。

PHP)の一時変数を回避する方法

2
dreeves

もちろん、配列の代わりにオブジェクトを返し、次の方法でアクセスすることもできます。

echo "This should be 2: " . test()->b ."\n";

しかし、配列でこれを行う可能性は見つかりませんでした:(

2
Pesse

私の通常の回避策は、このような汎用関数を持つことです

_ function e($a, $key, $def = null) { return isset($a[$key]) ? $a[$key] : $def; }
_

その後

_  echo e(someFunc(), 'key');
_

ボーナスとして、これにより、不要な場合の「未定義のインデックス」警告も回避されます。

foo()[x]が機能しない理由については、答えは非常に失礼であり、ここでは公開されません。 ;)

2
user187291

同じことを行うには3つの方法があります。

  1. Chacha102が言うように、関数を使用してインデックス値を返します。

    function get($from, $id){
        return $from[$id];
    }
    

    次に、次を使用できます。

    get($foo->getBarArray(),0);
    

    最初の要素を取得するなど。

  2. Currentとarray_sliceを使用した怠惰な方法:

    $first = current(array_slice($foo->getBarArray(),0,1));
    $second = current(array_slice($foo->getBarArray(),1,1));
    
  3. 同じ関数を使用して、配列と値の両方を返します。

    class FooClass {
        function getBarArray($id = NULL) {
            $array = array();
    
            // Do something to get $array contents
    
            if(is_null($id))
                return $array;
            else
                return $array[$id];
            }
    }
    

    次に、配列全体と単一の配列アイテムを取得できます。

    $array = $foo->getBarArray();
    

    または

    $first_item = $foo->getBarArray(0);
    
1
Andrés Morales

短い答え:

はい。関数の結果と特定のバージョンのPHPがサポートしている限り、PHPで関数の戻り値を操作することは可能です。

例2を参照:

//  can php say "homer"?      
//  print zoobar()->fname;     //  homer <-- yup

ケース:

  • 関数の結果は配列であり、PHPバージョンは十分に新しいものです
  • 関数の結果はオブジェクトであり、必要なオブジェクトメンバーに到達可能です
1
dreftymac

以前はPHP 5.3でこれを行う必要がありました:

function returnArray() {
  return array(1, 2, 3);
}
$tmp = returnArray();
$ssecondElement = $tmp[1];

結果:2

PHP 5.4以降、次のように配列を逆参照することができます。

function returnArray() {
  return array(1, 2, 3);
}
$secondElement = returnArray()[1];

結果:2

PHP 5.5:

あなたも賢くなることができます:

echo [1, 2, 3][1];

結果:2

文字列でも同じことができます。これは文字列逆参照と呼ばれます。

echo 'PHP'[1];

結果:H

1
Robert Rocha

それが単に美的である場合、オブジェクトを返すとオブジェクト表記が機能します。メモリ管理に関する限り、一時的なコピーは作成されず、参照の変更のみが行われます。

1
bucabay

参照を使用できます:

$ref =& myFunc();
echo $ref['foo'];

そうすれば、返された配列の複製を実際に作成することにはなりません。

0
mattbasta

これは機能しますか?

 return ($foo->getBarArray())[0];

それ以外の場合は、getBarArray()関数を投稿できますか?あなたがこれまでに投稿したものから、なぜそれがうまくいかないのかわかりません。

0
thedz