Только возвращаемые значения (без ключей/ассоциативного массива) в Laravel

Ситуация

У меня есть следующий код для получения всех данных в виде массива:

Data::select('id', 'text')->get()->toArray();

Это вернет данные в следующем формате:

array:1 [
  0 => array:2 [
    "id" => "1"
    "text" => "Stack"
  ]
  1 => array:2 [
    "id" => "2"
    "text" => "Overflow"
  ]
]

Но мне нужны только значения в виде обычного массива (без ключей/ассоциативного массива), поэтому массив не преобразуется в объект, когда я конвертирую его в JSON:

array:1 [
  0 => array:2 [
    0 => "1"
    1 => "Stack"
  ]
  1 => array:2 [
    0 => "2"
    1 => "Overflow"
  ]
]

Неадекватные решения

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

Также я ищу способ «настроить» Eloquent/Query Builder, а не метод для преобразования однажды возвращенных результатов.

Вопросы

Есть ли настройка или способ сделать это с помощью Eloquent/Query Builder?


person totymedli    schedule 12.02.2016    source источник


Ответы (2)


TL;DR

Просто скажите PDO, чтобы он работал следующим образом:

DB::connection()->setFetchMode(PDO::FETCH_NUM);
Data::select('id', 'text')->get()->toArray();
DB::connection()->setFetchMode(PDO::FETCH_OBJ;);

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

use DB;
use PDO;

Подробно (за кадром)

Это контролируется самим базовым PDO, которым можно управлять через fetch_style. Нам нужна вот эта константа:

PDO::FETCH_NUM: возвращает массив, проиндексированный по номеру столбца, возвращенному в вашем наборе результатов, начиная со столбца 0.

Теперь нам просто нужно передать это в стиле Laravel. Эта константа передается в PDO в файле Illuminate/Database/Connection.php в последней строке функции select() с помощью геттера:

public function select($query, $bindings = [], $useReadPdo = true)
{
    return $this->run($query, $bindings, function ($me, $query, $bindings) use ($useReadPdo) {
        if ($me->pretending()) {
            return [];
        }

        // For select statements, we'll simply execute the query and return an array
        // of the database result set. Each element in the array will be a single
        // row from the database table, and will either be an array or objects.
        $statement = $this->getPdoForSelect($useReadPdo)->prepare($query);

        $statement->execute($me->prepareBindings($bindings));

        return $statement->fetchAll($me->getFetchMode());
    });
}

Конечно, есть и общедоступный сеттер: setFetchMode(), поэтому нам просто нужно получить коннектор и мы можем его установить. Согласно документации:

При использовании нескольких соединений вы можете получить доступ к каждому соединению с помощью метода connection на фасаде DB.

Итак, у нас есть все для этого:

DB::connection()->setFetchMode(PDO::FETCH_NUM);
person totymedli    schedule 12.02.2016

Больше не вариант после laravel 5.4

Возможный обходной путь: https://github.com/awesomedeba10 предлагается здесь: https://github.com/laravel/framework/issues/17557#issuecomment-536879106

Вы можете добавить переменную .env со значением по умолчанию в config.

конфиг/база данных.php:

fetch_mode => env('DB_FETCHMODE', 'FETCH_OBJ');

.env:

FETCH_MODE=FETCH_OBJ

Затем в Illuminate/Database/Connection.php›подготовлено

Добавь это:

$statement->setFetchMode($config['fetch_mode'] == "FETCH_OBJ" ? 5 : ($config['fetch_mode'] == "FETCH_NUM" ? 3 : 2));

вставка из:

$this->fetchMode

Затем вы можете перезаписать свою конфигурацию:

config()->set('database.connections.mysql.fetch_mode', 'FETCH_NUM');

Это сохраняет режим выборки по умолчанию FETCH_OBJ по умолчанию, но вы все равно можете переключиться на FETCH_NUM, когда вам нужно.

person Július Ľuptovec    schedule 21.05.2021