Синтаксис PHP для результата разыменования функции - PullRequest
34 голосов
/ 13 апреля 2009

Фон

В любом другом языке программирования, который я использую на регулярной основе, просто работать с возвращаемым значением функции без объявления новой переменной для хранения результата функции.

Однако в 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     

Кто-нибудь может подсказать, как это сделать в PHP?

Ответы [ 22 ]

2 голосов
/ 17 февраля 2011

Чрезвычайно гетто, но это можно сделать только с помощью 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 голосов
/ 20 ноября 2009

Вот несколько способов решить вашу проблему.

Сначала вы можете использовать для именования переменных напрямую, если вы возвращаете массив переменных, которые не являются частью коллекции, но имеют отдельное значение для каждой.

Два других способа - вернуть результат, представляющий собой набор значений.

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 голосов
/ 20 ноября 2009

Мой обычный обходной путь - иметь общую функцию, подобную этой

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

, а затем

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

в качестве бонуса, это также позволяет избежать предупреждения «неопределенный индекс», когда он вам не нужен.

Что касается причин, по которым foo()[x] не работает, ответ довольно невежлив и не будет здесь опубликован. ;)

2 голосов
/ 20 ноября 2009

Конечно, вы можете вернуть объект вместо массива и получить к нему доступ таким образом:

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

Но я не нашел возможности сделать это с массивом: (

2 голосов
/ 20 ноября 2009

После дальнейших исследований я считаю, что ответ отрицательный, такая временная переменная действительно является каноническим способом работы с массивом, возвращаемым из функции.

Похоже, это изменится, начиная с PHP 5.4.

Кроме того, этот ответ был первоначально для этой версии вопроса:

Как избежать временных переменных в PHP при использовании массива, возвращаемого функцией

2 голосов
/ 25 июля 2009

Это слишком надумано, но если вам действительно НУЖНО это быть в одной строке:


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

/* ... */

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

1 голос
/ 25 мая 2017

Ранее в 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 голос
/ 20 ноября 2009

Если это просто эстетично, то запись Object будет работать, если вы вернете объект. Что касается управления памятью, никакое временное копирование, если оно сделано, только изменение ссылки.

1 голос
/ 03 апреля 2013

Краткий ответ:

Да. Можно работать с возвращаемым значением функции в PHP, если только результат функции и ваша конкретная версия PHP поддерживают его.

Ссылка на пример2:

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

Случаи:

  • Результатом функции является массив, и ваша версия PHP достаточно свежа
  • Результатом функции является объект, и требуемый член объекта доступен
1 голос
/ 04 марта 2011

Есть три способа сделать то же самое:

  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);
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...