CodeIgniter Forums
DataMapper 1.6.0 - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Libraries & Helpers (https://forum.codeigniter.com/forumdisplay.php?fid=22)
+--- Thread: DataMapper 1.6.0 (/showthread.php?tid=11358)



DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]GregX999[/eluser]
I'm still confused... Sad

When I print_r the class instead of saving it, the fields array does not contain "confirm_password". Do I need to add that field to the database for that to work?

This is a sign-up form, so the object is an empty object that I assign screen_name, email and password to and then try to save. But yes, you are correct in that I only get the "Unable to access an error message corresponding to your field name." error when the password does not validate (empty OR just not passing my validation function) - if the password validates, I don't get that error. But I don't get any error if my password validates but the confirm password does not match (it should give an error saying it doesn't match).

Here's the entire first part of my User class:

class User extends DataMapper
{
var $created_field = 'created_on';

var $validation = array(
array(
'field' => 'screen_name',
'label' => 'Screen Name',
'rules' => array('required', 'trim', 'min_length' => 2, 'max_length' => 100, 'unique')
),
array(
'field' => 'url_name',
'label' => 'URL Name',
'rules' => array('make_url_name')
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => array('valid_password', 'required', 'trim')
),
array(
'field' => 'confirm_password',
'label' => 'Confirm Password',
'rules' => array('matches' => 'password')
),
array(
'field' => 'email',
'label' => 'Email',
'rules' => array('required', 'trim', 'unique', 'valid_email')
)
);

function User($new_data='')
{
parent:Big GrinataMapper();

if($new_data)
{
$this->set_data($new_data);
}
}


// --------------------------------------------------------------------


/**
* Set Data
*
* Sets an array of data based on $this->manual_fields
*
* @access public
* @param array[$new_Data]
* @return true
*/
function set_data($new_data)
{
if(is_array($new_data))
{
foreach($this->fields as $f)
{
if($new_data[$f])
{
$this->$f = $new_data[$f];
}
}
return true;
}
else
{
return false;
}
}

}


This is from my Users controller:

public function signup()
{
$data['page_title'] = "New Member Sign-up";
$u = new User($_POST);
if($_POST)
{
if($u->save())
{
echo '<p>You have successfully registered</p>';
exit;
}
else
{
$data['error_messages'][] = $u->error->string;
}
}
$data['form_errors'] = $u->error;
$this->view->render($data, 'member', 'signup');
}


And the entire HTML form:

&lt;?= form_open('/signup'); ?&gt;
&lt;? $label_width = "6em"; ?&gt;
<div class="field_row">
&lt;?= form_label('Choose a Screen Name', 'screen_name'); ?&gt;
&lt;?= form_input(array('name' => 'screen_name', 'value' => set_value('screen_name'), 'class' => 'focus_me field' . $form_errors->screen_name ? ' error' : '')); ?&gt;
x&lt;?= set_value('screen_name') ?&gt;x
</div>
<div class="field_row">
&lt;?= form_label('Your Email Address', 'email'); ?&gt;
&lt;?= form_input(array('name' => 'email', 'value' => set_value('email'), 'class' => 'field' . $form_errors->email ? ' error' : '')); ?&gt;
</div>
<div class="field_row">
&lt;?= form_label('Choose a Password', 'password'); ?&gt;
&lt;?= form_password(array('name' => 'password', 'value' => set_value('password'), 'class' => 'field' . $form_errors->password ? ' error' : '')); ?&gt;
</div>
<div class="field_row">
&lt;?= form_label('Confirm Password', 'confirm_password'); ?&gt;
&lt;?= form_password(array('name' => 'confirm_password', 'value' => set_value('confirm_password'), 'class' => 'field' . $form_errors->confirm_password ? ' error' : '')); ?&gt;
</div>
<div class="field_row">
<label class="hidden">&nbsp;</label>
&lt;?= form_submit('signup', 'Sign-Up'); ?&gt;
</div>
&lt;?= form_close(); ?&gt;


DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]OverZealous[/eluser]
The “Unable to access an error message corresponding to your field name.” error means that the error is occuring within one of your custom validation routines (or that the datamapper_lang file is not installed). If it is one of yours, either that rule is failing, and you do not have an error message associated with the error (the rule valid_password [method name: _valid_password($field)] needs a language line valid_password).

I suspect that your custom validation routine is what is failing.

I'm pretty sure, now that I look at this some more, that this has nothing to do with the confirm_password field. I was wrong earlier, after reviewing the code again. Non database fields are only set in the error object if there is an error (which you would expect). You can still safely check those fields using isset($object->error->field_name), which you should be doing anyway.

Honestly, you just are going to have to do some debugging on your own.


DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]xtramix[/eluser]
There seems to be another serious bug currently present, where the search criteria gets lost during a call to get().

The acceptable workaround for this issue involves calling clear() after the query has been executed:

Code:
// swap the statements - DM 1.6.0 (line 485), DM-test (line 541):

// Get by built up query
$query = $this->db->get($this->table, $limit, $offset);
        
// Clear this object to make way for new data
$this->clear();



DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]OverZealous[/eluser]
[quote author="xtramix" date="1234860838"]There seems to be another serious bug currently present, where the search criteria gets lost during a call to get().[/quote]

This is not a bug. It's the way ActiveRecord works, upon which DataMapper is built. When you call get(), the query information is erased. If you want a copy of the query info, for whatever reason, call get_clone() before calling get(). This clones the query information, as well.

Also, it isn't obvious, but you can only have one query being built up at a time. if you do this:
Code:
$user = new User();
$user->where('name', 'fred'); // this will be lost

$group = new Group();
$group->get_by_id(4);

$user->where_related($group)->get();

The first where on $user will be lost, because there is only one ActiveRecord class, and it is shared across the board. Make sure you group your query information.


DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]xtramix[/eluser]
Without this change, the following code:

Code:
$u =& new User();
$u->get_by_id(123);

... generates this sql statement:

Code:
SELECT *
FROM (`users`)

With the fix in place, the sql statement appears to be correct:

Code:
SELECT *
FROM (`users`)
WHERE `id` = 123

Am I missing something here?

Thanks.


DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]OverZealous[/eluser]
I don't know, but it's probably related to your completely unnecessary assign-by-reference in the first line of code. You shouldn't assign-by-reference on object creation, ever.

A lot of people use this code. I don't know what else might be wrong, but that issue certainly doesn't exist on when I use DM, nor many others, I would assume. If you look in the code, calling ->get_by_id(123) is exactly the same as
Code:
$user->where('id', 123);
return $user->get();



DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]xtramix[/eluser]
[quote author="OverZealous.com" date="1234861679"]I don't know what else might be wrong, but that issue certainly doesn't exist on when I use DM[/quote]

I stand corrected. This issue only manifests when User model includes has_one relation to another model that has_many relation with the User model. I'm going to try to put together a simple test case and post it back later...

Another question, if you don't mind - what name should be given to model (and FK) that refers to a table named "species"?

TIA.


DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]OverZealous[/eluser]
"Species", actually, in both cases. But you'll have to hand type in the table name, since the pluralizing class isn't that smart:
Code:
class Species extends DataMapper {
    var $model = 'species';
    var $table = 'species';
... everything else ...
You also might have trouble with self-references, because the self-referencing code automatically uses the plural() function. (Actually, it will probably be fine, since species looks plural, so it will just ignore it.)

I have to do that with statuses - since that is actually the correct plural form, and the word status just confuses the pluralizing code. :cheese:


DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]xtramix[/eluser]
[quote author="OverZealous.com" date="1234864220"]
Code:
var $model = 'species';
var $table = 'species';
[/quote]

Even after adding model name (table was already specified), I'm still getting "Trying to get property of non-object" error when executing the following code:

Code:
$p = new Patient();
$p->get_by_id(424);
$p->species->species_name;

It seems that this particular model is the source of the strange problem mentioned above...

Quote:Actually, it will probably be fine, since species looks plural, so it will just ignore it

Actually, the helper seems to convert 'species' to 'specy'. :-(


DataMapper 1.6.0 - El Forum - 02-16-2009

[eluser]OverZealous[/eluser]
Sadly, that is just one of those limitations in DataMapper that cannot be readily fixed. There just is no way to always convert single and plural nouns.

You best bet, if this is your issue, is to try to rename it to something more compatible, such as species_group(s) or species_set(s). Or, heck, forget the correct conventions, and just call it Specie :-)

Even with that, I'm not sure why you would have trouble. In looking at the DataMapper code, the magic __get method (even version 1.6.0) doesn't call plural at any point.

I hate to say it, but you probably need to look at your own code and configuration. It just doesn't make sense why you would get non-object errors, unless Patient doesn't include the correct reference. One thing is to make sure both $model and $table are all lowercase - this might be what is causing the above error. The in_array($field, $this->has_one) style checks are case-sensitive.