1

I am trying to migrate from mysqli procedural to PDO because my website was halfway, half in pdo, and the rest in mysqli procedural, now I want to shift to PDO completely. Here is an example of the code I run

$rowNum = 0;
foreach ($result->fetchAll(PDO::FETCH_ASSOC|PDO::FETCH_OBJ) as $row) {
  $rowNum = $rowNum + 1;
   $dbUsername = $row['Username'];
}
if ($row>0) {
    echo $dbUsername;
}

But in some scenarios, the code gives me an error that trying to get property 'Username' of non-object

I know it was possible to use only ($result->fetchAll(PDO::FETCH_ASSOC)

But doing this ($result->fetchAll(PDO::FETCH_ASSOC|PDO::FETCH_OBJ) becomes a need as some context of the code I'm modifying use the symbol like $row->Usename and the other use $row['Username'], How can I make it accept both modes as shown above?

I tried to use PDO:: FETCH_BOTH but the problem persists.

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • 4
    `some context of the code I'm modifying use the symbol like $row->Usename and the other use $row['Username']` - How it's even possible? I mean, neither mysqli or PDO would even allow that, so it means it **never** worked. How did it make into your code? – Your Common Sense Jan 22 '23 at 12:25
  • 2
    @Dharman or while($row = $result->fetch(PDO::FETCH_LAZY)) :) – Your Common Sense Jan 22 '23 at 22:17

2 Answers2

2

As @YourCommonSense pointed out in his comment, you can use PDO::FETCH_LAZY to accomplish this. However, you cannot use that with fetchAll, only with fetch:

while ($row = $result->fetch(PDO::FETCH_LAZY)) {
    // Both of these will work
    $username = $row['Username'];
    $username = $row->Username;
}

If you really want to use fetchAll, you'll have to fetch the rows as one type and cast them back and forth between arrays and objects:

foreach ($result->fetchAll(PDO::FETCH_ASSOC) as $row) {
    // with PDO::FETCH_ASSOC, $row is an array
    $username = $row['Username'];

    $row = (object)$row;
    // $row is an object now
    $username = $row->Username;

    $row = (array)$row;
    // $row is now an array again
    $username = $row['Username'];
}
rickdenhaan
  • 10,857
  • 28
  • 37
  • Did you read my comment actually? – Your Common Sense Jan 24 '23 at 05:51
  • @YourCommonSense Your first comment about how neither mysqli or PDO would allow this, yes. Your second comment about `FETCH_LAZY`, not really since I thought you were responding to a comment by @Dharman. I'd never heard of `FETCH_LAZY` so I wrote a quick test script to try that out, and it turns out that could indeed be the solution to OP's problem. I've updated my answer to include it. – rickdenhaan Jan 24 '23 at 10:49
0

It's not possible. You cannot get both at the same time. There would be no way to represent such a result in PHP.

When you try to use both with PDO::FETCH_ASSOC|PDO::FETCH_OBJ you are actually fetching the result as PDO::FETCH_COLUMN. That's because fetch parameter is a bitwise flags parameter. When you do an OR operation on these flags it is the same as 2|5 = 7. 7 is the value for PDO::FETCH_COLUMN.

I don't know what use case you have for this, but it sounds like an XY problem. If you use fetchAll() you cannot have it both as an array and an object. But if you are fetching it row by row with fetch(), you could fetch each row in a different way.

$res = $pdo->query("SELECT 1 as foo UNION ALL SELECT 2 as foo");
var_dump($res->fetch(PDO::FETCH_ASSOC));
var_dump($res->fetch(PDO::FETCH_OBJ));
/*
Outputs:
array(1) {
  ["foo"]=>
  int(1)
}
object(stdClass)#3 (1) {
  ["foo"]=>
  int(2)
}
*/
Dharman
  • 30,962
  • 25
  • 85
  • 135