EllisLab text mark
Advanced Search
3 of 15
3
   
Gas ORM 2
Posted: 23 March 2012 03:24 AM   [ Ignore ]   [ # 41 ]   [ Rating: 0 ]
Joined: 2012-03-22
11 posts

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.

 
Posted: 27 March 2012 03:18 AM   [ Ignore ]   [ # 42 ]   [ Rating: 0 ]
Joined: 2012-03-22
11 posts

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?

 
Posted: 27 March 2012 05:38 AM   [ Ignore ]   [ # 43 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts

I have this simple extension as a convinience way to interact with result.

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... 
 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 28 March 2012 03:14 PM   [ Ignore ]   [ # 44 ]   [ Rating: 0 ]
Joined: 2012-03-09
23 posts
toopay - 22 March 2012 05:16 AM

@Khrome83 and @Dan Tdr

Khrome83 - 21 March 2012 06:33 PM

To answer your question, if I use this code, where the only thing that changed is that all() is replaced with find(1), i get errors.

Code -

$skills Model\Skills::find(1);
   
$this->output->enable_profiler(TRUE); 

   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 :

$config['models_path'= array(
   
'Model' => APPPATH.'models',
   
'Model\\Foo' => APPPATH.'modules/foo/models',
   
'Model\\Bar' => APPPATH.'modules/bar/models',
); 

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?

 
Posted: 29 March 2012 05:38 AM   [ Ignore ]   [ # 45 ]   [ Rating: 0 ]
Joined: 2012-03-29
7 posts

Hi !

Thanks for this awesome ORM ! i love it !

But i have a problem with relationships.

I have a Class Foo and an Class Bar
Foo has Many Bar
Bar belongs to Foo.

When I use Foo->bar(), i want to have my Bar datas order by Date.

I try

self::$relationships = array(
            
'bar' => ORM::has_many('\\Model\\Bar', array('order_by:date[asc]')),
        ); 

But nothing change if I try with ASC/DESC in the profile I don’t see OrderBy ...
What am i doing wrong? :(

Thanks smile

 
Posted: 29 March 2012 06:01 PM   [ Ignore ]   [ # 46 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts
Khrome83 - 28 March 2012 03:14 PM

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 

You may also want to look up Result extension.

 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 29 March 2012 06:04 PM   [ Ignore ]   [ # 47 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts
Thibaut L. - 29 March 2012 05:38 AM

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

 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 29 March 2012 06:08 PM   [ Ignore ]   [ # 48 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts

Updated to v.2.1.0

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.

 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 30 March 2012 02:41 AM   [ Ignore ]   [ # 49 ]   [ Rating: 0 ]
Joined: 2012-03-22
11 posts
toopay - 29 March 2012 06:01 PM

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 

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.

 
Posted: 30 March 2012 03:30 AM   [ Ignore ]   [ # 50 ]   [ Rating: 0 ]
Joined: 2012-03-29
7 posts
toopay - 29 March 2012 06:08 PM

Updated to v.2.1.0

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 smile

I’ve just downloaded 2.1.0 version and I have some issues :

Messagearray_merge() [function.array-merge]Argument #1 is not an array
Filenamelibraries/gas.php
Line Number
88 

L88 :

$config array_merge($CI->config->item('gas'), array('migration' => $CI->config->item('migration'))); 

If I try to change to :

$config array_merge(array($CI->config->item('gas')), array('migration' => $CI->config->item('migration'))); 

New error :

MessageUndefined indexauto_create_models
Message
Undefined indexauto_create_tables 

And CI write :

Invalid runtime configuration.

For the moment I use old libraries/gas.php and everything is ok and order_by works fine smile

 

 
Posted: 30 March 2012 06:06 AM   [ Ignore ]   [ # 51 ]   [ Rating: 0 ]
Joined: 2007-12-08
22 posts

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.


Thanks smile

 
Posted: 30 March 2012 06:06 AM   [ Ignore ]   [ # 52 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts

@Thibaut L, you donwload from Spark or the zipped files?

 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 30 March 2012 06:12 AM   [ Ignore ]   [ # 53 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts

@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... 
 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 30 March 2012 06:29 AM   [ Ignore ]   [ # 54 ]   [ Rating: 0 ]
Joined: 2012-03-29
7 posts
toopay - 30 March 2012 06:06 AM

@Thibaut L, you donwload from Spark or the zipped files?

Zipped file from link in DOC v2.1

 
Posted: 30 March 2012 07:02 AM   [ Ignore ]   [ # 55 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts
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.

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.

 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
3 of 15
3