I have a question regarding PDO.
Is there a difference between
$sql = "SELECT * FROM pages";
$pdo = $this->db->query($sql);
$result = $pdo->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC);
and
$sql = "SELECT * FROM pages";
$pdo = $this->db->query($sql);
$pdo->setFetchMode(PDO::FETCH_GROUP|PDO::FETCH_ASSOC);
$result = $pdo->fetchAll();
?
I get a different $result
for each of them.
The documentation from PHP about these fetch modes is not very clear to me.
I have a table with different pages, and I want to fetch all the pages indexed by their ID.
The first method returns this:
[
[id of page 1] => [
[0] => [ page 1 ],
],
[id of page 2] => [
[0] => [ page 2 ],
],
...
]
When I do the second method, I only get:
[
[0] => [ page 1 ],
[1] => [ page 2 ],
[3] => [ page 3 ],
...
]
I want it like this:
[
[id of page 1] => [ page 1 ],
[id of page 2] => [ page 2 ],
[id of page 3] => [ page 3 ],
...
]
The first one is good enough for me because I can easily tweak it with the array map function:
array_map('reset', $result);
PDOStatement::fetchAll() returns an array containing all of the remaining rows in the result set. The array represents each row as either an array of column values or an object with properties corresponding to each column name.
By default, user-missing values are converted to the Python data type None.
The fetchAll() is a method of the PDOStatement class. The fetchAll() method allows you to fetch all rows from a result set associated with a PDOStatement object into an array. The $mode parameter determines how the fetchAll() returns the next row.
fetchall() fetches all the rows of a query result. An empty list is returned if there is no record to fetch the cursor. fetchone() method returns one row or a single record at a time. It will return None if no more rows / records are available.
The explanation seems to be that fetchAll()
and setFetchMode()
support different sets of PDO::FETCH__
constants.
I think setFetchMode()
ignores PDO::FETCH_GROUP
, but not PDO::FETCH_ASSOC
.
I confirmed this from the PHP source code, see the setFetchMode()
implementation. The list of constants supported by setFetchMode
does not include PDO::FETCH_GROUP
.
setFetchMode()
and fetchAll()
are different<?php
$db = new PDO('mysql:host=localhost;dbname=test', 'root');
// print the default output, no constants
$sql = "SELECT * FROM service_table";
$q = $db->query($sql);
$result = $q->fetchAll();
echo 'Result 0' . PHP_EOL;
var_dump($result);
// use fetchAll() with constants
$sql = "SELECT * FROM service_table";
$q = $db->query($sql);
$result = $q->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);
echo 'Result 1' . PHP_EOL;
var_dump($result);
// use setFetchMode with constants
$sql = "SELECT * FROM service_table";
$q = $db->query($sql);
$q->setFetchMode(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);
$result = $q->fetchAll();
echo 'Result 2' . PHP_EOL;
var_dump($result);
mysql> select * from test.service_table;
+----+------+
| id | name |
+----+------+
| 1 | one |
| 2 | two |
+----+------+
This is the default, results are not grouped and there are both name-based and index-based fields:
array(2) {
[0] =>
array(4) {
'id' => string(1) "1"
[0] => string(1) "1"
'name' => string(3) "one"
[1] => string(3) "one"
}
[1] =>
array(4) {
'id' => string(1) "2"
[0] => string(1) "2"
'name' => string(3) "two"
[1] => string(3) "two"
}
}
This is the result of $q->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC)
. We have the effects of both FETCH_GROUP
and FETCH_ASSOC
:
array(2) {
[1] => array(1) {
[0] => array(1) {
'name' => string(3) "one"
}
}
[2] => array(1) {
[0] => array(1) {
'name' => string(3) "two"
}
}
}
This is the result of $q->setFetchMode(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);
, we have only the effect of FETCH_ASSOC
:
array(2) {
[0] => array(2) {
'id' => string(1) "1"
'name' => string(3) "one"
}
[1] => array(2) {
'id' => string(1) "2"
'name' => string(3) "two"
}
}
This way, FETCH_GROUP
works for fetchAll()
, but doesn't work for setFetchMode()
. FETCH_ASSOC
works in both cases.
Now, an indirect confirmation from docs:
Here is the list of all PDO constants. The description for PDO::FETCH_FUNC
says:
Allows completely customize the way data is treated on the fly (only valid inside
PDOStatement::fetchAll()
).
So we know that at least this constant only works for fetchAll()
, and can assume that other constants may work not everywhere.
Also if we look at the docs for fetch()
, we see a limited list of constants there.
For example PDO::FETCH_GROUP
and PDO::FETCH_UNIQUE
are present in the fetchAll()
description, but are not present in the fetch()
description.
So I think constants related to multi-row operations, such as PDO::FETCH_GROUP
, are only used for fetchAll()
and ignored by fetch()
and setFetchMode()
.
I tried few combinations and it looks like FETCH_GROUP
+ FETCH_UNIQUE
does it.
$sql = "SELECT * FROM service_table";
$q = $db->query($sql);
$result = $q->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_UNIQUE | PDO::FETCH_ASSOC);
var_dump($result);
array(2) {
[1] => array(1) {
'name' => string(3) "one"
}
[2] => array(1) {
'name' => string(3) "two"
}
}
Another option can be to use FETCH_FUNC
with custom function to format data, see the fetchAll()
docs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With