CodeIgniter Forums
DataMapper ORM v1.8.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 ORM v1.8.0 (/showthread.php?tid=37531)



DataMapper ORM v1.8.0 - El Forum - 05-18-2011

[eluser]Anestetikas[/eluser]
Hello,
I cant figure out how can i get multiple objects related to multiple objects. Like I need to get all articles related to specific tags:
1. IT
2. Database
3. PHP

I get wanted tags from multiselect as an array, but if i do:
Code:
$obj->where_related('tag','id',$tagArray);

It generates where in (1, 2, 3) statement.


DataMapper ORM v1.8.0 - El Forum - 05-18-2011

[eluser]WanWizard[/eluser]
What does your $tagArray look like? When you pass an array as parameter to a where() method, Datamapper switches to where_in() automatically.

It calls CI's database class where_in() method to execute the query, the array should be compliant to the definition of that method.


DataMapper ORM v1.8.0 - El Forum - 05-18-2011

[eluser]Andy78[/eluser]
What exactly would it take to make the ion_auth library work with datamapper? I understand that ion_auths tables will work with datamapper but other than that would I have to basically rewrite ion_auth?

Iv got a basic login and auth system working with datamapper no probs but Im not confident about security especially when it comes to users wanting to reset passwords and so on. So if anybody has done this type of thing with datamapper and are willing to share the code please do.


DataMapper ORM v1.8.0 - El Forum - 05-18-2011

[eluser]IgnitedCoder[/eluser]
This is secure enough for me... Set an encryption key in your config file, see the _prep_password function. Hope it helps to get you started.

[code]<?php
/**
* User: Brendan
* Date: 2/19/11
* Time: 12:57 AM
* To change this template use File | Settings | File Templates.
*/

class User extends DataMapper
{

var $has_one = array('profile' => array());
var $related_profile_fields = array('id', 'job_title', 'company', 'country', 'region', 'postal_code', 'industry', 'current_status');

function __construct($id = NULL)
{
parent::__construct($id);
}

function login($email_address, $password)
{
$CI = get_instance();
$this->session = $CI->session;
$this->where('email_address', $email_address)->where('password', $this->_prep_password($password))->get();
if ($this->result_count() == 1)
{
$data = array(
'username' => $this->username,
'user_id' => $this->id,
'first_name' => $this->first_name,
'last_name' => $this->last_name,
'user_email' => $email_address),
'is_logged_in' => true
);
$this->session->set_userdata($data);
return $this->result_count();
} else {
return 0;
}

}

function add_new($form_data)
{
$this->first_name = $form_data['first_name'];
$this->last_name = $form_data['last_name'];
$this->email_address = $form_data['email_address'];
$this->password = $this->_prep_password($form_data['password']);
$this->activationkey = md5($form_data['email_address']);
return ($this->save_as_new());
}

function update_user($form_data)
{
$this->first_name = $form_data['first_name'];
$this->last_name = $form_data['last_name'];
$this->email_address = $form_data['email_address'];
$this->password = $this->_prep_password($form_data['password']);
return ($this->save());
}

function update_user_email($user_id,$new_email)
{
$status = '';
if ($this->where('id', $user_id)->update('email_address', $new_email))
{
$CI = get_instance();
$this->session = $CI->session;
$this->session->set_userdata(array('user_email' => $new_email));
$status .= "<span style='color:#006600'>updated successfully</span>";
}
else
{
$status .= "<span style='color:#990000'>update failed!!";
}
return($new_email.' ['.$status.']');
}

function confirm_signup($key = 0)
{
return ($this->where('activationkey', $key)->update('confirmed', 1));
}

function reset_pwd($email)
{

$normal_pwd='';
if($this->user_exists($email)){
$normal_pwd = $this->generatePassword();
$pwd = $this->_prep_password($normal_pwd);

if ($this->where('email_address', $email)->update('password', $pwd)){
return $normal_pwd;
}
}

return $normal_pwd;

}

function user_exists($email_address)
{
return ($this->where('email_address', $email_address)->count() == 1 ? TRUE : FALSE);
}

function getbyid($id = 0)
{
return ($this->where('id', $id)->get());
}

function getbyemail($email_address)
{
return ($this->where('email_address', $email_address)->get());
}

function _prep_password($password)
{
return sha1($password . $this->config->item('encryption_key'));
//return sha1($password.md5(uniqid(rand(), true)));
}

}


DataMapper ORM v1.8.0 - El Forum - 05-18-2011

[eluser]Anestetikas[/eluser]
[quote author="WanWizard" date="1305741170"]What does your $tagArray look like? When you pass an array as parameter to a where() method, Datamapper switches to where_in() automatically.

It calls CI's database class where_in() method to execute the query, the array should be compliant to the definition of that method.[/quote]

I have found the solution for what i needed:
Code:
$article->where_related('tag', 'id', $tagArray)->group_by('id');
$article->having('count(articles_tags.article_id) = ' . count($tagArray));
Using:
Handling many to many relations part #3

Was missing the part with having.


DataMapper ORM v1.8.0 - El Forum - 05-18-2011

[eluser]gh0st[/eluser]
How do I generate an array of all the join_ fields when I use

Code:
// get all alarms for this user, and include the extra 'wasfired' field
$u->alarm->include_join_fields()->get();

In my code I can generate an array of all the fields created by Datamapper, this is a great timesaver for me.

Code:
$c = New Company();
$c->get();

$companyRoot     = array();

// Build an array that will have the table field as the key
// an use the row data as the value.
// ie.
// Instead of $c->name, etc
// We make Datamapper do the heavy lifting of generating
// an array of the table fields

foreach($c as $cItems):
    $cItems->workers->include_join_fields()->get();

    $cItems->check_last_query();

    // Companies
    $companyStack     = array();
    foreach($cItems->fields as $field):
        $tmp             = array($field => $cItems->$field);
        $companyStack     = array_merge( $companyStack, $tmp );                
    endforeach;
    
    
    
    array_push($companyRoot, $companyStack);
    
endforeach;

$root = array('companies'=>$companyRoot);

Taking this further I can generate an inner array of all the employees for a company. But I cannot seem to get it to automatically include the join_ fields into the array.

Instead it will give me a list of all the employees using the table field as the key and the table row data as the value of the array.

ie:

Code:
foreach($wok->fields as $wfield):
  print '<br>' . $wfield . ' -> ' . $wok->$wfield;                    
endforeach;

This (above) won't list the join_ fields. How do I go about doing that?

thank you


DataMapper ORM v1.8.0 - El Forum - 05-18-2011

[eluser]Andy78[/eluser]
@IgnitedCoder

Thanks for that! Not sure I understand how the activation code part works though


DataMapper ORM v1.8.0 - El Forum - 05-19-2011

[eluser]felix_[/eluser]
I also have the "problem" with the Could not find the language line problem...
is there a way to disable the auto generated validation rules or hav to set the labels for each field to avoid these error messages?


DataMapper ORM v1.8.0 - El Forum - 05-19-2011

[eluser]WanWizard[/eluser]
The validation rule for 'id' is defined in the Datamapper method. Look for
Code:
// set up id column, if not set
if(!isset($associative_validation['id']))
{
    // label is set below, to prevent caching language-based labels
    $associative_validation['id'] = array(
        'field' => 'id',
        'rules' => array('integer')
    );
}

This triggers a localisation lookup for the id field later on.

You could also modify
Code:
// Finally, localize the labels here (because they shouldn't be cached
// This also sets any missing labels.
$validation =& DataMapper::$common[$common_key]['validation'];
foreach($validation as $field => &$val)
{
    // Localize label if necessary
    $val['label'] = $this->localize_label($field,
            isset($val['label']) ?
                $val['label'] :
                FALSE);
}
unset($validation);
so that the foreach body isn't executed for $field == 'id', but defined the label hardcoded to something like 'id'.


DataMapper ORM v1.8.0 - El Forum - 05-20-2011

[eluser]Chillahan[/eluser]
I set up a test controller to save some properties to an object with one supporting table. I noticed two things, which may or may not be related. When I try to save the same data again, without specifying an id, but having the validation rule "unique" on one of the fields, I get the following error:

Code:
A PHP Error was encountered

Severity: Notice

Message: Undefined property: stdClass::$id

Filename: libraries/datamapper.php

Line Number: 5560

This relates to the function that performs the "unique" validation:

Code:
protected function _unique($field)
    {
        if ( ! empty($this->{$field}))
        {
            $query = $this->db->get_where($this->table, array($field => $this->{$field}), 1, 0);

            if ($query->num_rows() > 0)
            {
                $row = $query->row();

                // If unique value does not belong to this object
                if ($this->id != $row->id) // *** Line 5560 ***
                {
                    // Then it is not unique
                    return FALSE;
                }
            }
        }

        // No matches found so is unique
        r

Here's the odd part - it still inserts the new record! I am not using a transaction - wouldn't save run the validation first, and then insert upon success (and thus should never reach the insert since it bails at line 5560 above, without returning)?

Here's the complicating factor - the test table has a non-standard ID field name (i.e., it is auto increment numeric, but it is called "User_Id", not "id", due to design requirements of client).

So here are my questions and points:

1. Why is it still adding the record, even though it bailed (is this normal)?

2. How can I set DM to use a non-standard id field? I feel I read how to set this somewhere in the past few days while browsing, but after searching for 20 minutes in the guide, forums, even the old forums, I don't see what I thought I saw. And beyond that, it seems to be hard-coded anyway in the unique function above, is that right? (unless the object's parameter "id" can be dynamically set from wherever it is loaded, assuming there is a place to use a non-standard id field name)

3. Not directly related - for transactions, assuming I want to bunch a group of operations, there's no way to enable auto transactions but still group for the places where it's more than one save operation occurring to fulfill the transaction, right? I'd have to manually code for transactions throughout?

Thanks...