ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

DataMapper 1.6.0

September 05, 2008 12:32pm

Subscribe [115]
  • #526 / Feb 16, 2009 8:50am

    DominixZ

    23 posts

    Thanks for code and reason. 😊

  • #527 / Feb 16, 2009 4:56pm

    Matthew Lanham

    145 posts

    What’s in the pipeline for further developments for DataMapper, although it’s working great i’d love to see it keep going as i think it’s a fantastic library, is someone still maintaining it?

  • #528 / Feb 16, 2009 5:35pm

    OverZealous

    1030 posts

    @Matthew Lanham

    I can’t speak for stensi - it is his project after all - but if you look just a few posts back, you’ll see I am working on extending the project.  So far, several of my modifications to DataMapper have worked their way into the actual project, including the where_related() methods.

    I’ve already mostly developed has_one relationships that don’t require a join table.  I’ve added more advanced relationship capabilities, that allow multiple-relationships to the same object without separate classes (ie: tracking an editor and a creator) - however, they might be a bit confusing right now.  I also added the ability to “join” the results from several tables directly into DataMapper.

    stensi is still the maintainer, and the owner of the project.  I don’t think I have the ability to maintain it as well as he has.

  • #529 / Feb 16, 2009 5:46pm

    GregX999

    39 posts

    Hey guys,

    I’m trying to use a password confirmation in my sign-up form and I’m having trouble getting the error message working if it doesn’t match your password. I don’t have a “confirm_password” field in my database table - I shouldn’t need one right? My other errors work fine.

    I always get this error in my list of form errors (any errors generated by data not passing validation… ie: “The Email field is required”):
    “Unable to access an error message corresponding to your field name.”

    And I get this error:
    Undefined property: stdClass::$confirm_password
    when I try to access “User->error->confirm_password”.
    (See my HTML below)


    Here’s what I have in my validation array:

    array(
      ‘field’ => ‘password’,
      ‘label’ => ‘Password’,
      ‘rules’ => array(‘valid_password’, ‘required’, ‘trim’)
    ),
    array(
      ‘field’ => ‘confirm_password’,
      ‘label’ => ‘Confirm Password’,
      ‘rules’ => array(‘matches’ => ‘password’)
    ),

    Here’s my HTML:
    ($form_errors is set to $user->errors, $user being my User object)

    <div class=“field_row”>
      <?= form_label(‘Choose a Password’, ‘password’); ?>
      <?= form_password(array(‘name’ => ‘password’, ‘value’ => set_value(‘password’), ‘class’ => ‘field’ . $form_errors->password ? ’ error’ : ‘’)); ?>
    </div>
    <div class=“field_row”>
      <?= form_label(‘Confirm Password’, ‘confirm_password’); ?>
      <?= form_password(array(‘name’ => ‘confirm_password’, ‘value’ => set_value(‘confirm_password’), ‘class’ => ‘field’ . $form_errors->confirm_password ? ’ error’ : ‘’)); ?>
    </div>


    Any advice?

    Greg

  • #530 / Feb 16, 2009 6:00pm

    OverZealous

    1030 posts

    I have to assume you have a typo in your class.  There’s nothing wrong with your code you posted, however, the only way I can see that you would have the second error (undefined property) is if the field ‘confirm_password’ was not properly set on the fields array.  DataMapper sets the error value for every field to ‘’ when it starts.

    The first error would only occur if the ‘password’ field is completely empty.  If it is empty, you cannot save to the database, since you marked it as required.  If you are trying to save an existing user, but don’t want to change the password, you’ll want to ->get_by_id($id) on the existing user, change the changed fields, and then re-save the user.

  • #531 / Feb 16, 2009 6:45pm

    GregX999

    39 posts

    I’m still confused… :(

    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::DataMapper();

    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 'You have successfully registered';
    exit;
    }
          else
          {
    $data['error_messages'][] = $u->error->string;
    }
      }
      $data[‘form_errors’] = $u->error;
      $this->view->render($data, ‘member’, ‘signup’);
    }


    And the entire HTML form:

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

  • #532 / Feb 16, 2009 10:25pm

    OverZealous

    1030 posts

    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.

  • #533 / Feb 16, 2009 10:53pm

    xtramix

    7 posts

    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:

    // 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();
  • #534 / Feb 16, 2009 10:56pm

    OverZealous

    1030 posts

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

    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:

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

  • #535 / Feb 16, 2009 11:03pm

    xtramix

    7 posts

    Without this change, the following code:

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

    ... generates this sql statement:

    SELECT *
    FROM (`users`)

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

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

    Am I missing something here?

    Thanks.

  • #536 / Feb 16, 2009 11:07pm

    OverZealous

    1030 posts

    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

    $user->where('id', 123);
    return $user->get();
  • #537 / Feb 16, 2009 11:45pm

    xtramix

    7 posts

    I don’t know what else might be wrong, but that issue certainly doesn’t exist on when I use DM

    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.

  • #538 / Feb 16, 2009 11:50pm

    OverZealous

    1030 posts

    “Species”, actually, in both cases.  But you’ll have to hand type in the table name, since the pluralizing class isn’t that smart:

    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:

  • #539 / Feb 17, 2009 12:01am

    xtramix

    7 posts

    var $model = 'species';
    var $table = 'species';

    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:

    $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…

    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’. :-(

  • #540 / Feb 17, 2009 12:12am

    OverZealous

    1030 posts

    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.

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases