Héctor Ramón Jiménez Fri Dec 10 14:54:22 -0500 2010

Subject: Some improvements!

Hi everybody!

First of all, sorry for my english... I'm not an usually english speaker / writer.

I had been using the stable build since yesterday, when I downloaded the Nightly build because I'm interested in eager loading and cache features.
The first thing that surprised me is that the validator option 'on' wasn't functioning... I saw that It isn't any code related with it in Validations.php . I need this option to only check a user password when it creates and changes, not at every update. I solved this adding some modifications to this file:

 1 // File Validations.php
 2 public function __construct(Model $model)
 3 {
 4     $this->model = $model;
 5     $this->record = new Errors($this->model);
 6     // [...]
 7     // Added, add this private property in the class
 8     $this->action = $this->model->is_new_record() ? 'create' : 'update';
 9 }

Then, I added two lines for every validator method, to check if the model is creating, updating, or if the attribute is dirty.

 1 // File Validations.php
 2 // In every validation method... (in validates_presence_off only add the ifs)
 3 // [...]
 4 foreach ($attrs as $attr)
 5 {
 6     $options = array_merge($configuration, $attr);
 7     // Condition to set validation on UPDATE or on CREATE, or if it's DIRTY. DEFAULT: on SAVE
 8     // You can join the ifs (&&) if you want
 9     // ON == save || ON == ModelAction -> Validate
10     if($options['on'] != 'save' && $options['on'] != $this->action)
11         // ON == dirty && Atrribute IS dirty --> Validate
12         if($options['on'] != 'dirty' or !$this->model->dirty_attr($attr[0]))
13             continue;

And the method dirty_attr() in Model.php is...

1 // File Model.php
2 public function dirty_attr($attr)
3 {
4     if(!$this->__dirty)
5         return false;
6 
7     return array_key_exists($attr,$this->__dirty);
8 }

Now, this is working well... I think you can add more 'on' options easily because you know the ORM much better than me.

Finally, I was interested to use eager loading to load some relationships, but I need to do this using the conditions of the relationship... And that wasn't supported. Well, I added some code to get this functionality.

It's simple, I added this lines into Relationships eager loading method:

 1 // File Relationship.php
 2 protected function query_and_attach_related_models_eagerly(/*[...]*/)
 3 {
 4     // [...]
 5     $values = array($values);
 6     $options['conditions'] = SQLBuilder::create_conditions_from_underscored_//[ ... ]
 7 
 8     if (!empty($includes))
 9         $options['include'] = $includes;
10 
11     // Add relationship conditions and order (you can add more options)
12     Utils::add_condition($options['conditions'], $this->options['conditions']);
13     $options['order'] = $this->options['order'];

Finally, I've had a problem with this code that clones the model if is already used. I commented it like this:

 1 // File Relationship.php
 2 foreach ($related_models as $related)
 3 {
 4     // I added here the read_attribute method to avoid use custom getters
 5     if ($related->read_attribute($query_key) == $key_to_match)
 6     {
 7         //$hash = spl_object_hash($related);
 8 
 9         //if (in_array($hash, $used_models))
10             //$model->set_relationship_from_eager_load(clone($related), /*[...]*/);
11         //else
12             $model->set_relationship_from_eager_load($related, $this->attribute_name);
13         //$used_models[] = $hash;
14 
15         $matches++;
16     }
17 }
I don't know why you clone the model if they are referring to the same...

This is working well for me now! I would be very happy if you add these functionalities to the ORM in the future.

Thank you for this easy to use ORM!