วิธีการรับอาร์เรย์สเกลาร์มิติเดียวเป็นผลการสืบค้น dql หลักคำสอน?


116

ฉันต้องการรับอาร์เรย์ของค่าจากคอลัมน์ id ของตารางการประมูล ถ้านี่เป็น SQL ดิบฉันจะเขียน:

SELECT id FROM auction

แต่เมื่อฉันทำสิ่งนี้ในหลักคำสอนและดำเนินการ:

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

ฉันได้รับอาร์เรย์ดังนี้:

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

แต่ฉันต้องการรับอาร์เรย์เช่นนี้:

array(
    1,
    2
)

ฉันจะทำเช่นนั้นโดยใช้หลักคำสอนได้อย่างไร?

คำตอบ:


197

PHP <5.5

คุณสามารถใช้array_mapและตั้งแต่คุณมีเพียงในรายการต่ออาร์เรย์คุณอย่างหรูหราสามารถใช้ 'current'เป็นโทรกลับแทนการเขียนปิด

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

ดูคำตอบของ Petr Sobotka ด้านล่างสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการใช้หน่วยความจำ

PHP> = 5.5

ในฐานะที่เป็นjcbwlkr ที่ตอบด้านล่างarray_columnที่วิธีที่แนะนำไปใช้


9
getScalarResult () จะให้สตริง - ใช้ getArrayResult () ถ้าคุณต้องการจำนวนเต็ม
pHoutved

ดังนั้น! array_column () ดีกว่าในการจัดการหน่วยความจำหรือเป็นวิธี foreach เราทำอะไร?
Dheeraj

151

ใน PHP 5.5 คุณสามารถใช้array_columnเพื่อแก้ปัญหานี้ได้

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

98

PDO:FETCH_COLUMNทางออกที่ดีคือการใช้งาน ในการทำเช่นนั้นคุณต้องมีไฮเดรเตอร์แบบกำหนดเอง:

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

เพิ่มในหลักคำสอน:

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

และคุณสามารถใช้งานได้ดังนี้:

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

ข้อมูลเพิ่มเติม: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes


2
ฉันแก้ไขสิ่งนี้เพื่อให้รองรับ indexBy gist.github.com/ostrolucky/f9f1e0b271357573fde55b7a2ba91a32
gadelat

18

คำตอบของ Ascarius นั้นสวยงาม แต่ระวังการใช้หน่วยความจำ! array_map()สร้างสำเนาของอาร์เรย์ที่ส่งผ่านและเพิ่มการใช้งานหน่วยความจำเป็นสองเท่า หากคุณทำงานกับอาร์เรย์หลายแสนรายการสิ่งนี้อาจกลายเป็นปัญหาได้ เนื่องจาก PHP 5.4 call-time pass โดยการอ้างอิงถูกลบออกดังนั้นคุณจึงไม่สามารถทำได้

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

ในกรณีนี้คุณสามารถไปได้อย่างชัดเจน

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

2
ซึ่งดูเหมือนจะใช้งานง่ายเล็กน้อยเนื่องจากเป้าหมายของเราคือ "เกือบจะคัดลอก" อาร์เรย์ในทั้งสองกรณี ฉันต้องทดสอบด้วยตัวเองเพื่อให้มั่นใจว่าเป็นเรื่องจริง: gist.github.com/PowerKiKi/9571aea8fa8d6160955f
PowerKiKi

4

ฉันคิดว่ามันเป็นไปไม่ได้ในหลักคำสอน เพียงแค่แปลงอาร์เรย์ผลลัพธ์เป็นโครงสร้างข้อมูลที่คุณต้องการโดยใช้ PHP:

$transform = function($item) {
    return $item['id'];
};
$result = array_map($transform, $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult());
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.