Синтаксис 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 1 August 2019 в 10:45
поделиться

16 ответов

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

Так что вам нужно сделать.

$var = foobar();
print($var[0]);
26
ответ дан Ólafur Waage 27 November 2019 в 16:00
поделиться

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

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);
}
14
ответ дан Calvin 27 November 2019 в 16:00
поделиться

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

function array_value ($array, $key) {
return $array[$key];
}
5
ответ дан 27 November 2019 в 16:00
поделиться

Как уже упоминалось, это невозможно. Синтаксис 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();
5
ответ дан 27 November 2019 в 16:00
поделиться

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

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

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

. Но в остальном func () [1] не поддерживается в PHP.

7
ответ дан 27 November 2019 в 16:00
поделиться

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

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

Это было запрошено уже до . Ответ - нет. Это невозможно.

На процитируйте Энди Гутманс по этой теме:

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

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

17
ответ дан 27 November 2019 в 16:00
поделиться

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

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

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

0
ответ дан 27 November 2019 в 16:00
поделиться

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


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

/* ... */

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

2
ответ дан 27 November 2019 в 16:00
поделиться

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

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

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

5
ответ дан 27 November 2019 в 16:00
поделиться

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

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

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

3
ответ дан 27 November 2019 в 16:00
поделиться

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

1
ответ дан 27 November 2019 в 16:00
поделиться

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

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

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

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

2
ответ дан 27 November 2019 в 16:00
поделиться

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

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

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

2
ответ дан 27 November 2019 в 16:00
поделиться

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

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

, а затем

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

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

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

2
ответ дан 27 November 2019 в 16:00
поделиться

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

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

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

0
ответ дан 27 November 2019 в 16:00
поделиться

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

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

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

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
ответ дан 27 November 2019 в 16:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: