Làm cách nào để lấy mảng vô hướng một chiều dưới dạng kết quả truy vấn dql theo học thuyết?


116

Tôi muốn lấy một mảng giá trị từ cột id của bảng Đấu giá. Nếu đây là một SQL thô, tôi sẽ viết:

SELECT id FROM auction

Nhưng khi tôi làm điều này trong Doctrine và thực hiện:

$em->createQuery("SELECT a.id FROM Auction a")->getScalarResult(); 

Tôi nhận được một mảng như thế này:

array(
    array('id' => 1),
    array('id' => 2),
)

Thay vào đó, tôi muốn nhận một mảng như thế này:

array(
    1,
    2
)

Làm cách nào tôi có thể làm điều đó bằng Doctrine?

Câu trả lời:


197

PHP <5.5

Bạn có thể sử dụng array_map, và vì bạn chỉ có trên mục trên mỗi mảng, nên bạn có thể sử dụng một cách trang nhã 'current'dưới dạng gọi lại, thay vì viết một bao đóng .

$result = $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult();
$ids = array_map('current', $result);

Xem câu trả lời của Petr Sobotka bên dưới để biết thêm thông tin về việc sử dụng bộ nhớ.

PHP> = 5.5

Như jcbwlkr's đã trả lời bên dưới , cách được đề xuất để sử dụng array_column.


9
getScalarResult () sẽ cung cấp cho bạn các chuỗi - sử dụng getArrayResult () nếu bạn muốn số nguyên
pHoutved vào

vì thế! array_column () quản lý bộ nhớ tốt hơn hay đó là cách dẫn trước, chúng ta nên làm gì?
Dheeraj

151

Kể từ PHP 5.5, bạn có thể sử dụng array_column để giải quyết vấn đề này

$result = $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult();
$ids = array_column($result, "id");

98

Một giải pháp tốt hơn là sử dụng PDO:FETCH_COLUMN. Để làm như vậy, bạn cần một bình thủy điện tùy chỉnh:

//MyProject/Hydrators/ColumnHydrator.php
namespace DoctrineExtensions\Hydrators\Mysql;

use Doctrine\ORM\Internal\Hydration\AbstractHydrator, PDO;

class ColumnHydrator extends AbstractHydrator
{
    protected function hydrateAllData()
    {
        return $this->_stmt->fetchAll(PDO::FETCH_COLUMN);
    }
}

Thêm nó vào Doctrine:

$em->getConfiguration()->addCustomHydrationMode('COLUMN_HYDRATOR', 'MyProject\Hydrators\ColumnHydrator');

Và bạn có thể sử dụng nó như thế này:

$em->createQuery("SELECT a.id FROM Auction a")->getResult("COLUMN_HYDRATOR");

Thông tin thêm: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes


2
Tôi đã sửa đổi này vì vậy nó hỗ trợ indexBy gist.github.com/ostrolucky/f9f1e0b271357573fde55b7a2ba91a32
gadelat

18

Câu trả lời của Ascarius rất thanh lịch, nhưng hãy cẩn thận với việc sử dụng bộ nhớ! array_map()tạo một bản sao của mảng đã truyền và tăng gấp đôi hiệu quả sử dụng bộ nhớ. Nếu bạn làm việc với hàng trăm nghìn mục mảng, điều này có thể trở thành một vấn đề. Vì thời gian gọi qua tham chiếu trong PHP 5.4 đã bị xóa nên bạn không thể thực hiện

// note the ampersand
$ids = array_map('current', &$result);

Trong trường hợp đó, bạn có thể chọn

$ids = array();
foreach($result as $item) {
  $ids[] = $item['id'];
}

2
Điều đó có vẻ hơi phản trực quan, vì mục tiêu của chúng tôi là "gần như sao chép" mảng trong cả hai trường hợp. Tôi phải kiểm tra nó bản thân mình để được thuyết phục nó thực sự là đúng: gist.github.com/PowerKiKi/9571aea8fa8d6160955f
PowerKiKi

4

Tôi nghĩ điều đó là không thể trong Doctrine. Chỉ cần chuyển mảng kết quả thành cấu trúc dữ liệu bạn muốn bằng PHP:

$transform = function($item) {
    return $item['id'];
};
$result = array_map($transform, $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult());
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.