Returning Array of Objects from PDO - php

I have a PHP class (POJO_FOO) which maps to a table (TABLE_FOO).
e.g. one row equal to one object of that class.
Now I am writing a manager which returns array of such objects matching a particular query. Using PDO, how can I return array of objects ?
When I do simple fetchAll, it returns array (representing number of results) of associative array (column => value). Is there a option in fetchALL which can give me result in form of array of objects ?

you can use PDO::FETCH_CLASS to hydrate your class with your data :
return $pdo->query('SELECT * FROM tablefoo')->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE,'POJO_FOO');
it is also useful to use PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE because it makes the construction of the object more consistent. Habitualy your constructor is called before everything. If you do not use FETCH_PROPS_LATE it will called after your properties are hydrated.

Related

Laravel collection of object results in associative array instead of object?

When I wrap a regular object into a collection, the result is an associative array.
I would like to keep using it as an object.
$obj = (object) ['count'=>1, 'now'=>Carbon::now()];
dump($obj); // $obj->count = 1, $obj->now = Carbon {...}
$collection = collect($obj);
dump($collection); // unwanted: $collection['count'] = 1, $collection['now'] = Carbon {...}
In a similar question the offered solution is to json_encode/json_decode the $collection.
But that modifies the object and loses information (e.g. converts the now Carbon object to a string).
$collection = json_decode(collect($obj)->toJson());
dump($collection); // unwanted: $collection->count = 1, $collection->now = "2021-05-25T10:43:34.301505Z"
How can I wrap an object into a collection without turning it into an associative array?
Maybe that's because a collection is considered an array of multiple entries. Technically, you're passing just one unwrapped entry whose properties are considered array entries for the collection. So I'd say, you're using the collection wrong.
From the docs:
The Illuminate\Support\Collection class provides a fluent, convenient wrapper for working with arrays of data.
Another way of emphasizing this, is that the Collection class implements the ArrayAccess interface. Therefore, this is what happens: When creating a Collection via collect(), the passed data is set to $this->items. So Collection is not an array, it just lets you access the contents of $this->items via array notation.

Laravel: Get model attributes by key array

I'm attempting to access a models attributes by an array of keys. The desired functionality would work something like $model->getAttribute('name'), but accept an array instead of a string.
Let's say we had a model with attributes name of 'A', age of 2 and blood_type of 'B'.
$attributesToPull = ['name', 'age'];
$model->getAttributes($attributesToPull);
// returns ['A', 2]
I've checked through the Laravel docs and cant find anything that quite fits.
The results dont need to come straight from the model, they can be pulled into their own associative array using $model->getAttributes() and then have a native PHP array function such as array_intersect to filter the results, but even then I can't seem to find a function that will allow me to filter an associative array with an indexed array.
Does anyone know how I could go about this, ideally without using a loop or a callback? The answer can be pretty open, it can return a collection or an array and use either the associative array of the model attributes or call a function on the model itself.
The Model has a only method:
$model->only($attributesToPull);

Why does Laravel store two different array syntaxes in databases and which one is correct?

I come from a Javascript and Ruby background and this is baffling me. Laravel can store two different array syntaxes in my DB depending on how I handle my array serialization. In my understanding, collect() creates a true Laravel array. Why then is it storing a serialized array? Furthermore, is the {'key':'value'}syntax still an array despite having no square brackets surrounding it? It looks to me like a standard object or a hash, but if I try to do toArray() on it, it recognizes that it's already an array and throws an error. What am I misunderstanding and what is correct here?
Given a form:
edit.blade:
<select class="form-control m-bootstrap-select m_selectpicker" name="temp">
<option value={{ json_encode(array("$key"=>"$cph"), JSON_FORCE_OBJECT) }}>
</select>
The following two controllers syntaxes yield different database insertions.
PageController.php:
$page->cph_default = collect($request->temp);
$page->save();
Laravel stores an array with the following syntax in my database: ["{\"11\":\"1100\"}"]
PageController.php
$page->cph_default = json_decode($request->temp, true);
$page->save();
Laravel stores an array with the following syntax in my database: {"19": "1900"}
A PHP array with the syntax ['key' => 'value'] is called an associative array, and acts like a hash. A JSON-encoded associative array will show up as an object in JSON syntax. Examples and more info on PHP.net
Laravel's collect() function is a convenience wrapper for creating a new Collection. A Collection is not really a "true Laravel array" so much as it is an object wrapper with some convenience methods for modifying the underlying array. Think of it like a scalar object.
In your form when generating the option value, the submitted form value ($request->temp) will be a JSON-encoded string. Literally the string '{"19": "1900"}'.
Calling collect($request->temp) does no modification to that submitted data. It's simply creating a new Collection (array), containing a single string item. If you were to call toArray() on the collection, you'd see something like this:
[
0 => '{"19": "1900"}'
]
Note that this is not an associative array, it is a numeric array with a zero-based index. This array is encoded as a JSON array, not as a hash object. Hence your first result.
Calling json_decode($request->temp) is turning the string back into an associative array (hash) before saving it via Eloquent. Eloquent then calls json_encode() again internally, turning it back into the same JSON as your form's option value.
If you were to decode the form value before creating the collection, the resulting database save would look identical. You'd just have the convenience of the Collection wrapper:
$page->cph_default = collect(json_decode($request->temp, true));
$page->save();
If you're treating the column as a JSON type, you should ensure the data passed to Eloquent is NOT already encoded, or you'll get the double encoding experienced in your first example.
No Matter What is.
First If you are stroring the array into database convert to JSON FORMAT
For eg
$variable = json_encode($request->controlname);
This is the right way to store array
Into database

MySQLi fetch_all Error with Consecutive Calls

I've set up a class to handle my MySQLi calls. The calls are working as they should, so no problems there.
I recently removed the result handling from my class's query method to two separate setter methods. There is now an error resulting from two consecutive fetch_all calls.
The previous (working) code with a single fetch_all call loads results into the two arrays res_rows and res_cols:
// Convert results into two sets of values
// and store in properties
// $res_rows=results by row (column names in element 0)
// Each row is an indexed array
// $res_cols=results by column (associative arrays)
// Key is the column name; Value is an array
$results=$res->fetch_all(MYSQLI_ASSOC);
// $colNames is an array of the column names
$colNames=array_keys($results[0]);
// Rows
foreach($results as $r) {
$this->res_rows[]=array_values($r);
}
array_unshift($this->res_rows,$colNames);
// Columns
$vals=array();
// Count the number columns in the query
$numCols=count($colNames);
// Iterate through the columns
for($i=0;$i<$numCols;$i++) {
$col=$colNames[i];
$storage=array();
foreach($results as $r) {
$storage[]=$r[$colNames[$i]];
}
$vals[]=$storage;
}
$this->res_cols=array_combine($colNames,$vals);
I've moved this code into two methods setRes_rows and setRes_cols and called them sequentially (see code). Each method pulls results from the result object using fetch all.
$this->setRes_rows($res);
$this->setRes_cols($res);
What happens is that the first call behaves as expected, and the second call returns an empty array.
If I reverse the calls (e.g. setRes_cols first), the same thing happens (first call works as expected; second call is empty). So I know the code is good. I even changed all the variable names in one of the methods with no effect.
I dumped all properties and methods on the result object between calls and it doesn't look like it changes. But for some reason that second fetch_all does not work.
The easy fix is for me to use a single fetch_all then call my methods. But I'm interested in knowing if there's anything weird I'm missing.
Thanks, everyone.
It looks like you need to reset the result pointer after a fetch_all.
I didn't find anything in the docs specifically for fetch_all - only about resetting after a fetch_assoc(), where we can find a reference to data_seek(): http://php.net/manual/en/mysqli-result.data-seek.php
So here's what you should do:
before the second fetch_all() do a
$res->data_seek(0); // where $res is your mysqli result Object
This basicly sets the result pointer to the first record.

Is there a way to receive constructor arguments for PDO setFetchMode as associative array?

In this case:
$stmt->setFetchMode(PDO::FETCH_CLASS, 'ClassName', $pdoargs);
When I pass $pdoargs as an associative array, I get it in the class constructor, but not as an associative array anymore but as a numeric array.
Is there a way to receive the array as associative?
As far as I can get your question, it is not directly related to PDO, but to function arguments in general.
So, if you want an associative array to be sent into constructor, you can make it this way
$stmt->setFetchMode(PDO::FETCH_CLASS, 'ClassName', array($pdoargs));

Categories