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-19-2009

[eluser]OverZealous[/eluser]
This is one of the things I was trying to solve. In the current, official version of DataMapper, you have to have a column for every model type when working with multiple relationships (to the same table).

In other words, you need this as your join table:
join_files_users
- id NOT NULL
- file_id NOT NULL
- user_id
- creator_id

Note that they must allow nulls. Now the queries will work.

However, there is a big problem with this. If you look up the creator ($file->creator->get()), that creator will not work for any relationships that were set as a user. Assuming that Users have a relationship to Roles, this will not work:
Code:
$creator = $file->creator->get();
$role = $creator->role->get(); // there is no relationship here, because it will look for the column creator_id again.

$user = new User();
$user->get_by_id($creator->id);
$role = $user->role; // this works, now

In the updated version, you can assign the same exact model in multiple ways, just using different field names:
Code:
class User extends DataMapper {
    $has_many = array(
        'file',
        'created_file' => array(
            'class' => 'file',
            'other_field' => 'creator'
    );
}

class File extends DataMapper {
    $has_one = array(
        'user',
        'creator' => array(
            'class' => 'user',
            'other_field' => 'created_file'
    );
}

// in controller
$creator = $file->creator->get(); // $creator is a User class
$user = $file->user->get(); // ditto

What's even better, you can create the file table like this:
files
- id,
- ...
- user_id int32, Must allow nulls
- creator_id int32 Must allow nulls


DataMapper 1.6.0 - El Forum - 02-19-2009

[eluser]macigniter[/eluser]
Thank you so much for your explanation Phil. I am still very new to CodeIgniter and ORM. But learning very fast and loving it. I will try to use your updated version of DataMapper with my application and let you know how it works out. Since I am new to CI and DataMapper your documentation file wasn't that easy to comprehend compared to DM's user guide. But I am trying my best since I really appreciate all your contributions to this great library!


DataMapper 1.6.0 - El Forum - 02-19-2009

[eluser]OverZealous[/eluser]
I apologize for not having better examples prepared. My own projects have taken up a lot of time lately, so I appreciate the effort being put in by those testing it. I know my "documentation" was fairly light. I'll try to get a complete example available some time soon!


DataMapper 1.6.0 - El Forum - 02-20-2009

[eluser]fancms[/eluser]
First, thanks for this class; I'm definitely having better productivity with it!

I'm a little puzzled over something. If I want to display all records from a table, I cannot use a select call. For example:

Code:
//This allows me to list all users
$u = new User();
$u->get();

//Say I want to show just their username and email
$u = new User();
$u->select("username,email")->get();
//This will only list one record :-\

Is there any way to be able to select only the needed fields? I don't usually need every column when making a call. Any advice/direction would be appreciated! :-)


DataMapper 1.6.0 - El Forum - 02-20-2009

[eluser]OverZealous[/eluser]
Select works. You might want to check the queries being run, and make sure you aren't getting the correct results.


DataMapper 1.6.0 - El Forum - 02-21-2009

[eluser]fancms[/eluser]
D'oh! I just looked at one of my views again and realized I was using the same variable in my foreach as in the controller. That is:

Controller
Code:
$u = new User();
$u->select("username,email")->get();
//...
$data['users'] = $u->all;

View
Code:
foreach($users as $u) {
Username: $u->username<br />
Email: $u->email
}

I completely forgot that accessing it via $u->whatever would only show me one record. Blush Changing it to $use in the view solved it.

Thanks for the response, OverZealous!


DataMapper 1.6.0 - El Forum - 02-22-2009

[eluser]TheBushMunky[/eluser]
Hey, I was wondering how do I repopulate a form with its previous values if the data is validated and there is an error?

I've tried using what I've found in DataMapper's Validation docs and the Form Helper & Form Validation docs for CodeIgniter. I'm using the DataMapper model's save() method to validate the data & save if valid. If the save fails, then I redisplay the form with the errors. I figured I'd use the Form Helper method set_value() to repopulate the fields as they show in the docs but that doesn't seem to work for me. Here's the code I have:

Controller Method:

Code:
function add()
{
    $post = new Post();
  
    $post->title = $this->input->post('title');
    $post->body = $this->input->post('body');
    $post->teaser = $this->input->post('teaser');
    $post->slug = $this->input->post('slug');
    $post->published = $this->input->post('published');
  
    // Apply Markdown on `body` text before saving.
    $post->markdown();
  
    if ($post->save())
    {
      $data = array(
        'title'=> $post->title,
      );
  
      $this->load->view('admin/post_created', $data);
    }
    else
    {
      $data = array(
        'title' => 'Create Post',
        'error' => $post->error->string,
      );
  
      $this->load->view('admin/post_create', $data);
    }
}


And the view:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
&lt;html &gt;

  &lt;head&gt;
    &lt;title&gt;&lt;?=$title?&gt;&lt;/title&gt;
    &lt;link rel="stylesheet" href="&lt;?=base_url()?&gt;/media/css/admin.css" type="text/css" media="screen" /&gt;
  &lt;/head&gt;

  &lt;body&gt;
    <div id="dashboard-wrapper">
    </div>
    
    <div id="app">

      &lt;?=form_open('admin/blog/add');?&gt;

          <div class="title">
            <h2>Write a new Post.</h2>
            <p></p>
          </div>
  
          <div id="test" class="test">
            &lt;?=$error?&gt;
          </div>
          
          <div class="field required">
            <label for="body" class="label">Content <span class="help"> And so the boy roared.</span></label>
            <div class="input">&lt;?=form_textarea('body', set_value('body'));?&gt;</div>    
          </div>


          <div class="field required">
            <label for="title" class="label">Title <span class="help">Make it pop and fizz.</span></label>  
            <div class="input">&lt;?=form_input('title', set_value('title'));?&gt;</div>
          </div>


          <div class="field">
            <label for="teaser" class="label">Teaser <span class="help">Sell the sizzle.</span></label>        
            <div class="input">&lt;?=form_input('teaser', set_value('teaser'));?&gt;</div>
          </div>

          <div class="field required">
            <label for="slug" class='label'>Slug <span class="help">URL friendly title.</span></label>
            <div class="input">&lt;?=form_input('slug', set_value('slug'));?&gt;</div>
          </div>

          <div class="field">
            &lt;?=form_label('Published','publish', array('class' => 'label'));?&gt;    
            &lt;?=form_checkbox('publish', 'publish', TRUE);?&gt;
          </div>


          <div class="field">
            <label class="label">&nbsp;</label>
            <div class="input">&lt;?=form_submit('create', 'Save');?&gt;</div>
          </div>

          &lt;!-- Does set value work? --&gt;
          <p>&lt;?=set_value('body') ?&gt;</p>
          
        &lt;?=form_close();?&gt;
    </div>

  &lt;/body&gt;
  
&lt;/html&gt;

Aside from not repopulating the user's input if the form doesn't pass validation, it works Tongue But I'd really like to be able to repopulate the data the user already entered, especially if some of it was valid


DataMapper 1.6.0 - El Forum - 02-22-2009

[eluser]OverZealous[/eluser]
For future reference, please be a little more selective in what you post - obviously we don't need the whole web page.

When using DataMapper, you don't have to resort to any tricks for your form. Simply pass the same object in before or after it is edited:
Code:
// controller
function edit($id = NULL) {
    $post = new Post();
    // do security checks, etc.
    if( ! is_null($id)) {
        // load in the object to be edited
        $post->get_by_id($id);
        // verify input
    } else if($this->input->post('id') !== FALSE) {
        // load in the already edited object
        $post->get_by_id($this->input->post('id'));
        // save form data, validate, etc.
        // redirect on successful save
    } else {
        show_error("Invalid id.");
    }
    $this->load->view('edit_post', array('post' => $post));
}


// in view
?&gt;
&lt;input type="text" name="title" id="title" value="&lt;?= htmlspecialchars($post-&gt;title) ?&gt;"/> &lt;?= $post->error->title ?&gt;
&lt;?
// etc.

You can expand this to be a little smarter, if necessary. You can even use the same form for adding new ones, simply don't throw an error if the ID is not passed. On saving, the id will be 0, so you can check for that if necessary. Calling ->save() will work for new or existing objects, and you can get the id of the saved object as $post->id on new saves as well.


DataMapper 1.6.0 - El Forum - 02-22-2009

[eluser]TheBushMunky[/eluser]
Oh, great, thanks! That's actually alot simpler than I thought it would be. Sorry about being so verbose and thanks for the tips Smile


DataMapper 1.6.0 - El Forum - 02-22-2009

[eluser]tdktank59[/eluser]
OverZealous I put some thought into why my single join table thing isnt work. (your new method with relations in the main table).

The reason why $asd->author->get(); as show below would not work is because there is no model named author... So my question to you is how are we to get author_id out of the dqip and relate it to the proper user.

This is where im at a loss... Since I know trying to get the author does not work.

Would I have to grab the author_id and manually relate the author_id to the user table?

Heres the example:

Code:
Code:
$asd = new Dqip();
$asd->where('id',$dqip_id)->get();
$asd->data_source->get(); // Does work since there is a data_source model (not related within the dqip table)
$asd->author->get(); // Does not work since there is no author model

user model:
Code:
var $has_many = array(  "brainstorm",
                            "role",
                            "team",

                            /* DQIP User Fields */
                            "dqip_author"       => array (  'class' => 'dqip',
                                                            'other_field' => 'author'),
                            "dqip_dciu_staff_1" => array (  'class' => 'dqip',
                                                            'other_field' => 'dciu_staff_1'),
                            "dqip_dciu_staff_2" => array (  'class' => 'dqip',
                                                            'other_field' => 'dciu_staff_2')
                         );

Dqip Model:
Code:
var $has_one = array( "author"          => array(   'class' => 'user',
                                                        'other_field' => 'dqip_author' ),

                          "dciu_staff_1"    => array(   'class' => 'user',
                                                        'other_field' => 'dqip_dciu_staff_1'),

                          "dciu_staff_2"    => array(   'class' => 'user',
                                                        'other_field' => 'dqip_dciu_staff_2')
                          );