Синтаксис 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/info/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?

Ответы

Ответ 1

Это, в частности, разыменование массива, которое в настоящее время не поддерживается в php5.3, но должно быть возможным в следующей версии 5.4. С другой стороны, разыменование объектов возможно в текущих версиях php. Я также с нетерпением жду этой функциональности!

Ответ 2

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

Итак, вам нужно сделать.

$var = foobar();
print($var[0]);

Ответ 3

Разбиение Array возможно с 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 ';' 

Исходный ответ:

Это спросил уже до. Ответ - нет. Это невозможно.

В quote Andi Gutmans на эту тему

Это хорошо известный запрос функции но не поддерживается в PHP 5.0. я не могу сказать, будет ли это когда-либо поддерживается. Это требует некоторых исследований и много думал.

Вы также можете найти этот запрос число времени в PHP Bugtracker. Для технических подробностей я предлагаю вам проверить официальный RFC и/или запросить Внутренние PHP.

Ответ 4

Хорошо, вы могли бы использовать любое из следующих решений, в зависимости от ситуации:

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

Или вы можете получить определенные значения из возвращаемого массива с помощью list():

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

Изменить: код примера для each(), который я дал ранее, был неправильным. each() возвращает пару ключ-значение. Поэтому было бы проще использовать foreach():

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

Ответ 5

Невозможно сделать это, к сожалению, хотя на большинстве других языков программирования.

Если вы действительно хотите сделать один лайнер, вы можете сделать функцию с именем a() и сделать что-то вроде

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

Но кроме этого функция func() [1] не поддерживается в PHP.

Ответ 6

Напишите функцию-оболочку, которая выполнит то же самое. Из-за простого простого ввода в PHP это может быть довольно открытым:

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

Ответ 7

Как уже упоминалось, это невозможно. Синтаксис PHP не позволяет этого. Однако у меня есть одно предложение, которое атакует проблему с другого направления.

Если вы контролируете метод getBarArray и имеете доступ к стандартной библиотеке PHP (установленной на многих хостах PHP 5.2.X и установленной по умолчанию с помощью PHP 5.3), вам следует рассмотреть возможность возврата ArrayObject вместо собственный массив/коллекция PHP. 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();

Ответ 8

Если вы просто хотите вернуть первый элемент в массиве, используйте функцию current().

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

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

Ответ 9

Собственно, я написал библиотеку, которая допускает такое поведение:

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

Работает со всем: функциями, методами. Кэши, так быстро, как сам PHP:)

Ответ 10

Вы не можете цеплять выражения, подобные этому в PHP, поэтому вам нужно сохранить результат array_test() в переменной.

Попробуйте следующее:

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

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

Ответ 11

Это слишком надуманно, но если вам действительно нужно быть в одной строке:


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

/* ... */

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

Ответ 12

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

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

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

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

Ответ 13

Вы могли бы, конечно, вернуть объект вместо массива и получить доступ к нему следующим образом:

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

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

Ответ 14

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

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

а затем

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

в качестве бонуса, это также предотвращает предупреждение undefined index ", когда оно вам не нужно.

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

Ответ 15

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

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

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

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";

Ответ 16

Исключительно гетто, но это можно сделать, используя только 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'));

Длины, которые мы должны пройти, чтобы сделать что-то прекрасное на большинстве других языков.

Для записи я делаю что-то похожее на то, что делает Nolte. Извините, если у меня кто-то пропустит глаза.

Ответ 17

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

Ответ 18

Существует три способа сделать одно и то же:

  • Как говорит Chacha102, используйте функцию для возврата значения индекса:

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

    Затем вы можете использовать:

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

    чтобы получить первый элемент и т.д.

  • Ленточный способ использования current и array_slice:

    $first = current(array_slice($foo->getBarArray(),0,1));
    $second = current(array_slice($foo->getBarArray(),1,1));
    
  • Используя ту же функцию для возврата обоих, массив и значение:

    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);
    

Ответ 19

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

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

Пример ссылки2:

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

Случаи:

  • Результат функции - это массив, и ваша версия PHP достаточно современна.
  • Результат функции - это объект, и член объекта, который вы хотите, доступен [

Ответ 20

Ранее в 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

Ответ 21

Это работает?

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

В противном случае вы можете опубликовать функцию getBarArray()? Я не понимаю, почему это не сработало бы с того, что вы опубликовали до сих пор.

Ответ 22

Вы можете использовать ссылки:

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

Таким образом, вы не создаете дубликат возвращаемого массива.