There are hooks for saving and deleting records, to do something with it before it goes through, but is it possible to hook reading records?
I’m working with a database where names and descriptions are stored as serialized arrays of localized strings. When I read records from there, I have to unserialize it and choose the right locale. I would like to do this automatically somewhere before it goes to my model or whatever code is reading the records.
EDIT:
Answering myself again, after going through the source for a while it looks like I could use the __get property overloading.
When reading records and looping through them with foreach, like in the example in the CRUD section of the User Guide, the foreach will fail if only one row matched the query.
Do I have to manually check each time to see if it returned an object or an array, and place the object in an array if not?
Is there a simpler way to make sure I always get an array even if there is just one row?
Simply create a file in the application/libraries/gas/extension/result.php contain above snippet, then you can use it as follow :
$result = Model\ORM\User::result()->all();
// Easy way to debug over your result echo $result;
// Convert the instances into an array of instance $users = $result->as_array();
foreach ($users as $user) { // $user will be a typical Gas Instance }
// Convert all instance's record into various format $records_array = $result->to_array(); // assoc array $records_json = $result->to_json(); // JSON $records_xml = $result->to_xml(); // XML
// Convert all instance's record into Gas\Data object $records_data = $result->to_data();
$first_user = $records_data->get('data.0'); // Return the first index $first_user_name = $records_data->get('data.0.name'); // Return the first index name $some_user_name = $records_data->get('data.100.name', 'Default Name'); // And so on...
foreach ($skills as $s) { echo $s->name.'<br />'; foreach ($s->types() as $t){ echo $t->name.'<br />'; } foreach ($s->professions() as $p) { echo $p->name.'<br />'; } foreach ($s->weapons() as $w) { echo $w->name.'<br />'; } //wtf($s);
}
Outputs -
A PHP Error was encountered
Severity: Notice
Message: Trying to get property of non-object
Filename: views/welcome.php
Line Number: 69
Fatal error: Call to a member function types() on a non-object in /home/guildwar/public_html/application/views/welcome.php on line 70
Obviously, you are trying to itterate object there, not an array. Try :
// Here you are try to find one record $this->output->enable_profiler(TRUE); $skill = Model\Skills::find(1);
foreach ($skill->types() as $t) { // Do your job with $t here }
Dan Tdr - 21 March 2012 08:42 PM
Hey toopay,
I searched for this info but with no luck, how can i use Gas ORM 2 with HMCV (Modular Extension) i want to put my models in my modules and not keep them in a folder models in my application folder. How can i do that?
Thank you,
Dan
Khrome83 already pointed to the right section. For example you have “foo” and “bar” module, located in application/modules, you could have something like this :
If your modules located outside your application folder, just modify the location with an absolute path within your modules.
@toopay -
Thanks for the feedback.
So multiple objects are returned as a array because I am asking for all().
If I use find, it returns a object in the object…
So how can I make my code universal for reading 1 or many objects?
For example, if i have the same page to display 1 as I do many (the view) but the model either gets all or a limited number, even a specific entry, then I have to test to see if it’s a array before presenting, or should I do a conversion to make it a array with a single entry?
So how can I make my code universal for reading 1 or many objects?
For example, if i have the same page to display 1 as I do many (the view) but the model either gets all or a limited number, even a specific entry, then I have to test to see if it’s a array before presenting, or should I do a conversion to make it a array with a single entry?
A quick cheatsheat :
// Finder method : // all => will return an array of object if records exists, or NULL // find_by_column => will return an array of object if records exists, or NULL // find => will return a Gas instance (object), or NULL // avg, max, min, sum => will return a Gas instance (object), or NULL // first, last => will return a Gas instance (object), or NULL
But nothing change if I try with ASC/DESC in the profile I don’t see OrderBy ...
What am i doing wrong? :(
No, your report is a legitimate bug. For version 2.0, only select work in additional query setting within relationship. I include this fixed within 2.1
Changes :
1. Support related entities at write operation, refer to updated documentation for usage. You may need to delete your browser cache to see the updated documentation.
2. Result Extension included.
3. Fix several minor issue on relationships methods.
// Finder method : // all => will return an array of object if records exists, or NULL // find_by_column => will return an array of object if records exists, or NULL // find => will return a Gas instance (object), or NULL // avg, max, min, sum => will return a Gas instance (object), or NULL // first, last => will return a Gas instance (object), or NULL
As far as I have noticed, “all”, “find_by_column” and “find” return an array of objects if there are multiple results and a single object (not in an array) if there was only one result.
On the other hand, getting records through relations ( like $user->messages() ) will always return an array of objects even if there was only one result.
This seems to cause some inconsistencies. Sometimes it’s good that it works that way but sometimes you have to change the type between an array and single object.
Some examples: user table has one-to-one relationship with userdata table. You call $user->userdata() and maybe you want their address so $user->userdata()->address. But wait, that causes an error, because userdata() returned an array of single object.
In another place you want to list all users so you call Model\User::all(). Now, let’s loop through them with foreach. Oh, but there is only one user and all() returns an object instead of an array with a single object, so the foreach causes an error.
Changes :
1. Support related entities at write operation, refer to updated documentation for usage. You may need to delete your browser cache to see the updated documentation.
2. Result Extension included.
3. Fix several minor issue on relationships methods.
Hi
I’ve just downloaded 2.1.0 version and I have some issues :
Message: array_merge() [function.array-merge]: Argument #1 is not an array Filename: libraries/gas.php Line Number: 88
Hi Toopay,
First of all great job again with version 2… I’ve spent a couple of hours working on an application using v2 and its great!
However one niggle is the return types of find_by_** mentioned by indCI. I think for consistency it would be better to always return null or an array of objects… as you say in your docs, if you are only after one record you can always apply a limit of 1!
indCI - 30 March 2012 02:41 AM
As far as I have noticed, “all”, “find_by_column” and “find” return an array of objects if there are multiple results and a single object (not in an array) if there was only one result.
...
In another place you want to list all users so you call Model\User::all(). Now, let’s loop through them with foreach. Oh, but there is only one user and all() returns an object instead of an array with a single object, so the foreach causes an error.
@mecharius, did you upgrade into Gas ORM 2.1? find_by_collumn will alyways return an array of object if records exists, and NULL if there is no records. Also, there is result extension included, you can use those extension as :
$result = Model\ORM\User::result()->all();
// Easy way to debug over your result echo $result;
// Convert the instances into an array of instance $users = $result->as_array();
foreach ($users as $user) { // $user will be a typical Gas Instance }
// Convert all instance's record into various format $records_array = $result->to_array(); // assoc array $records_json = $result->to_json(); // JSON $records_xml = $result->to_xml(); // XML
// Convert all instance's record into Gas\Data object $records_data = $result->to_data();
$first_user = $records_data->get('data.0'); // Return the first index $first_user_name = $records_data->get('data.0.name'); // Return the first index name $some_user_name = $records_data->get('data.100.name', 'Default Name'); // And so on...
As far as I have noticed, “all”, “find_by_column” and “find” return an array of objects if there are multiple results and a single object (not in an array) if there was only one result.
In another place you want to list all users so you call Model\User::all(). Now, let’s loop through them with foreach. Oh, but there is only one user and all() returns an object instead of an array with a single object, so the foreach causes an error.
One thing that consistent, since this ORM follow Active Record pattern, is that every Gas Instance is always hold a record not two or three or more. The returning values of finder methods, in v2.0.0 is depend on the fetched records.
Update to 2.1.0, the quick cheat sheat is for this version. You may also looks for result extension, as more conveniency way to working with finder. You always can easily extend it and adding some functionality which fit for your application.