Використання зворотного дзвінка в implode ()

У мене є багатовимірний масив, наприклад:

$values = array(
    'one' => array(
        'title' => 'Title One',
        'uri'   => 'http://example.com/one',
    ),
    'two' => array(
        'title' => 'Title Two',
        'uri'   => 'http://example.com/two',
    ),
);

... і я хотів би проаналізувати це через закриття в моїй функції implode , à la:

$final_string = implode(' | ', function($values) {
    $return = array();

    foreach($values as $value)
        $return[] = '' . $value['title'] . '';

    return $return;
});

Однак це використання дає помилку Недійсні аргументи передається . Є синтаксис, який мені не вистачає, що дозволить використовувати закриття можливо ? Я використовую PHP v5.3.16.

10
Згідно з документами, implode не приймає зворотний виклик ... Чи я щось не вистачає? Якщо ви просто хочете створити масив з функцією і використовувати його як параметр, то вам потрібно виконати цю функцію за допомогою call_user_func .
додано Автор elclanrs, джерело
Дякую @elclanrs - можливо, я неправильно розумію закриття, але я так не думаю. Анонімна функція, яку я визначив у питанні робить , повертає масив, що задовольняє вимогу для implode . Чи I щось не вистачає? :)
додано Автор jterry, джерело
Дякую @elclanrs - можливо, я неправильно розумію закриття, але я так не думаю. Анонімна функція, яку я визначив у питанні робить , повертає масив, що задовольняє вимогу для implode . Чи I щось не вистачає? :)
додано Автор jterry, джерело
$ return = array (); foreach ($ values ​​as $ value) $ return [] = '
додано Автор ccd580ac6753941c6f84fe2e19f229, джерело
$ return = array (); foreach ($ values ​​as $ value) $ return [] = '
додано Автор ccd580ac6753941c6f84fe2e19f229, джерело

7 Відповіді

Використовуйте array_map :

$final_string = implode(' | ', array_map(function($item) {
    return '' . $item['title'] . '';
}, $values));

Я довіряю, що ви правильно виберете ці значення як HTML у своєму реальному коді.


Що стосується того, чому це працює, і ваш код не є, ви передали функцію як другий аргумент для implode . Чесно кажучи, це не має сенсу: ви можете приєднатися до безлічі струн разом або навіть до безлічі функцій, але ви не можете об'єднати одну функцію. Це звучить дивно, особливо якщо ви говорите це таким чином.

Замість цього ми спочатку хочемо перетворити всі елементи в масив за допомогою функції і передавати результат що в implode . Ця операція найчастіше називається map . На щастя, PHP надає цю функцію як добре, array_map . Після перетворення елементів в масив, ми можемо приєднатися до результатів.

17
додано
Видалив мою відповідь, це просто чистіше. Немає необхідності в додатковому закритті.
додано Автор elclanrs, джерело

Здається, вам потрібно призначити цю функцію змінній, а потім передати її, щоб вона працювала.

$fn = function($values) {
    $return = array();
    foreach($values as $value)
        $return[] = '' . $value['title'] . '';
    return $return;
};
$final_string(' | ', $fn($values));
echo $final_string;

Я не знаю, що таке причина, і потрібно буде перевірити його набагато глибше, щоб мати змогу дати вам правильну причину.

You can see the code working here

EDIT : Converted this answer to a community wiki so that everyone can contribute here.

EDIT : Explanation by @kmfk

Коли ви передаєте закриття безпосередньо методу implode - який явно хоче другий аргумент типу масив , він по суті перевіряє instanceof - отже недійсний аргумент Функція implode не очікує типу mixed і не знає, як виконувати закриття, щоб отримати масив .

Коли ви спочатку присвоюєте цю функцію змінній, це спонукає PHP спочатку оцінити цю змінну, і вона закінчується передачею поверненого значення з функції в implode .

У такому випадку ви повертаєте масив з функції і передаєте його в implode - це перевіряється.

Ця анонімна функція буде instanceof Closure , і

Closure !== array
3
додано
Тому що ви не можете просто патч будь-що, що вам подобається при вживанні PHP функцій. Вони повинні використовуватися як розроблені та задокументовані.
додано Автор Beetroot-Beetroot, джерело
Дякуємо @Ashwin Mukhija - хотіли б знати, чому ми повинні пройти цей додатковий крок, щоб виконати по суті те саме.
додано Автор jterry, джерело
пояснив у своїй відповіді тут
додано Автор kmfk, джерело
@AshwinMukhija - це незручно - все ще не допомогло вікі-відповіді на спільноту. ти б просто редагувати?
додано Автор kmfk, джерело
Я мав на увазі, для подальшого використання, я просто редагую вашу відповідь?
додано Автор kmfk, джерело
@kmfk Ви можете поставити своє пояснення саме в цій відповіді.
додано Автор Achrome, джерело
Це вікі-спільнота, що означає, що кожен може редагувати його, і це корисно для налаштування спільних відповідей.
додано Автор Achrome, джерело

Здається, вам потрібно призначити цю функцію змінній, а потім передати її, щоб вона працювала.

$fn = function($values) {
    $return = array();
    foreach($values as $value)
        $return[] = '' . $value['title'] . '';
    return $return;
};
$final_string(' | ', $fn($values));
echo $final_string;

Я не знаю, що таке причина, і потрібно буде перевірити його набагато глибше, щоб мати змогу дати вам правильну причину.

You can see the code working here

EDIT : Converted this answer to a community wiki so that everyone can contribute here.

EDIT : Explanation by @kmfk

Коли ви передаєте закриття безпосередньо методу implode - який явно хоче другий аргумент типу масив , він по суті перевіряє instanceof - отже недійсний аргумент Функція implode не очікує типу mixed і не знає, як виконувати закриття, щоб отримати масив .

Коли ви спочатку присвоюєте цю функцію змінній, це спонукає PHP спочатку оцінити цю змінну, і вона закінчується передачею поверненого значення з функції в implode .

У такому випадку ви повертаєте масив з функції і передаєте його в implode - це перевіряється.

Ця анонімна функція буде instanceof Closure , і

Closure !== array
3
додано
Тому що ви не можете просто патч будь-що, що вам подобається при вживанні PHP функцій. Вони повинні використовуватися як розроблені та задокументовані.
додано Автор Beetroot-Beetroot, джерело
Дякуємо @Ashwin Mukhija - хотіли б знати, чому ми повинні пройти цей додатковий крок, щоб виконати по суті те саме.
додано Автор jterry, джерело
пояснив у своїй відповіді тут
додано Автор kmfk, джерело
@AshwinMukhija - це незручно - все ще не допомогло вікі-відповіді на спільноту. ти б просто редагувати?
додано Автор kmfk, джерело
Я мав на увазі, для подальшого використання, я просто редагую вашу відповідь?
додано Автор kmfk, джерело
Це вікі-спільнота, що означає, що кожен може редагувати його, і це корисно для налаштування спільних відповідей.
додано Автор Achrome, джерело
@kmfk Ви можете поставити своє пояснення саме в цій відповіді.
додано Автор Achrome, джерело

Ashwin's answer is correct. Here's why:

Коли ви передаєте закриття безпосередньо методу implode - який явно хоче другий аргумент типу масив , він по суті перевіряє instanceof - отже недійсний аргумент Функція implode не очікує mixed і не знає, як виконати закриття.

Коли ви спочатку присвоюєте цю функцію змінній, це спонукає PHP спочатку оцінити цю змінну, і вона закінчується передачею поверненого значення з функції в implode .

У такому випадку ви повертаєте масив з функції і передаєте його в implode - це перевіряється.

edit/adding: that anonymous function would be instanceof Closure.

Closure !== array
2
додано
Сторона уваги, спасибі, що відповіли на актуальний питання - а не тільки надання деякого рішення :)
додано Автор jterry, джерело
Урок дізнався ... спасибі @kmfk. Простий доказ того, що ви абсолютно правильно: is_array (function() {return array ();}); повертає false .
додано Автор jterry, джерело

Ви не можете використовувати implode для того, що намагаєтесь досягти, оскільки implode приймає лише масив як другий аргумент.

Ви можете спробувати щось подібне.

$values = array(
    'one' => array(
        'title' => 'Title One',
        'uri'   => 'http://example.com/one',
    ),
    'two' => array(
        'title' => 'Title Two',
        'uri'   => 'http://example.com/two',
    ),
);

$links = array();
foreach ($values as $value) {
      $links[] = "";
}

$string = implode(" | ", $links);
0
додано
function implode_callback( $array, $separator = '', $callback = false )
{
    return implode(
                    $separator,

                    $callback === false ?
                      $array : array_map( $callback, $array )
                  );
}

Приклад використання:

$tab = array( 1, 2, 3 );

echo implode_callback( $tab, '

', function($x) { return "
$x"; } );

Див код прикладів

0
додано
function implode_callback( $array, $separator = '', $callback = false )
{
    return implode(
                    $separator,

                    $callback === false ?
                      $array : array_map( $callback, $array )
                  );
}

Приклад використання:

$tab = array( 1, 2, 3 );

echo implode_callback( $tab, '

', function($x) { return "
$x"; } );

Див код прикладів

0
додано
Ukrainian PHP comunity
Ukrainian PHP comunity
885 учасників

dev-ua/php