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

[eluser]OverZealous[/eluser]
@tdtank59

How I'm doing it requires a little reversal of thought. Instead of using a join table, use a dedicated model for the join, with two one-to-N relationships. Then you can include whatever information you want in that table.

It isn't seamless yet, but I'm too busy to worry about making it better. You can still perform some very slick queries, though:
Code:
// relationship: user <- vote -> song
// get all votes and usernames for a song
$song->vote->join_related("user", array("name"))->get();
foreach($song->vote as $v) {
    echo($v->user_name . ": " . $v->rating);
}

// get all votes for this user
$user->vote->join_related("song", array("title", "artist"))->get();

// get all voting users for this song
$user = new User();
// this will lookup the users themselves, based on $song
$user->where_related("vote", "song_id", $song->id);

// Same as above, but add in the rating.  Note: this is a where the "hack" comes in
$user->where_related("vote", "song_id", $song->id);
$user->select("votes.rating as vote_rating");
$user->get(); // this is now similar to the first query, but using the User model.



DataMapper 1.6.0 - El Forum - 02-13-2009

[eluser]OverZealous[/eluser]
@macigniter
No. If you think about it, what you did was ask DM to look up all Products whose Client was not set. Most likely you are actually returning an array of ALL products. When you perform a $object->related->get(), and $related isn't set, $related is an actual object, just with no ID.

You need to verify that User has a Client before running the query. It can be this simple:
Code:
$p = new Product();
if($user->client->exists()) {
    $p->get_by_related($user->client);
}
// $p->all may or may not have any items



DataMapper 1.6.0 - El Forum - 02-13-2009

[eluser]macigniter[/eluser]
Good point, Phil Smile If I wouldn't be that brain-dead after hours of coding I could've realized it myself. I am actually using your solution already. Just didn't know why DataMapper needed the extra ->exists() check. But it all sounds logical now. I better shut down that computer and get a drink now (it's time for it in Germany) ;-)

Thanks!


DataMapper 1.6.0 - El Forum - 02-13-2009

[eluser]Fabrício Marchezini[/eluser]
set_value() helper misbehaves when DataMapper is loaded

I noticed that the set_value() helper wasn't working as expected on an application I'm developing. It always returned the value from the $default parameter, even when there were a posted value. Then, I tried to isolate the problem.

I created a controller just to test this behavior:

Code:
class Test extends Controller {
    
    function index()
    {
        $this->load->helper('form');
        
        $data['name'] = 'Foo';
        
        $this->load->view('test', $data);
    }
}

And a view that contains only this code inside the &lt;body&gt; element:

Code:
&lt;?= form_open('test') ?&gt;
<p>&lt;?= form_input('name', set_value('name', $name)) ?&gt;</p>
<p>&lt;?= form_submit('submit', 'Submit') ?&gt;</p>
&lt;?= form_close() ?&gt;

The first time the view is displayed, it shows de default $name value ('Foo'), as expected. But if I change the field to something else, like 'Bar' for instance, and submit the form, it displays 'Foo' again instead of 'Bar'.

When I disable DataMapper in config/autoload.php, set_value() works as expected. My conclusion is that DataMapper is causing set_value() to misbehave in some way. Or am I making something wrong here?


DataMapper 1.6.0 - El Forum - 02-13-2009

[eluser]OverZealous[/eluser]
I don't use that function, and I'm not sure why this should matter, but you might try autoloading the form_validation library BEFORE autoloading the DataMapper library in your CodeIgniter Autoload config.

It's the only connection I can find between set_value and DataMapper. (Why is a method [set_value] that can be so simple so complex? It boggles...)

Update
After digging into Form_Validation a bit more, I'm not sure you can use Form_Validation alongside DataMapper, because they do almost the same thing. What is happening, I believe, is that set_value sees that Form_Validation is already loaded, and therefore reverts to using that.

Instead, you'll need to write your own helper to handle set_value. It's a very simple function:
Code:
function set_value($field, $default = '') {
    return isset($_POST[$field]) ? $_POST[$field] : $default;
}

If you are using DataMapper for the information, you can skip the set_value stuff altogether. Just pass the object itself in, even if it is new. (You could potentially set default values on a new object, if you need).
Code:
// controller
$u = new User();
if(isset($this->input->post('id'))) {
    // attempt to save
} else {
    // set defaults
    $u->favorite_color = 'Blue';
}
$this->load->view('edit_user', array('user' => $u);

//...

// view
&lt;?= form_input('name', set_value('name', $u->name)) ?&gt;



DataMapper 1.6.0 - El Forum - 02-13-2009

[eluser]Fabrício Marchezini[/eluser]
Phil, thanks for the quick reply.

Although I didn't do it in my example, I actually use DataMapper as you pointed: setting default values in objects. Even so, sometimes I need to use the set_value helper. I've already written a replacemet for set_value() in MY_form_helper.php, but It would be nice if I could use the native one.


DataMapper 1.6.0 - El Forum - 02-13-2009

[eluser]OverZealous[/eluser]
The problem is the native one. It assumes that if Form_Validation is loaded, you are using it in the form.

There is no way for DataMapper to remove that assumption - and DataMapper uses Form_Validation to validate the objects, so Form_Validation is always loaded.


DataMapper 1.6.0 - El Forum - 02-14-2009

[eluser]dobomode[/eluser]
I was having troubles saving new objects in the db. It was inserting the row, but not updating the id. As a result, I was able to save the objects, but any subsequent save's that referenced those objects (like trying to save a relation) failed.

I narrowed down the issue to the DataMapper function save():

On line 610:

Code:
// Complete auto transaction
                    $this->_auto_trans_complete('save (insert)');

                    // Assign new ID
                    $this->id = $this->db->insert_id();

... needs to be changed to:

Code:
// Assign new ID
                    $this->id = $this->db->insert_id();

                    // Complete auto transaction
                    $this->_auto_trans_complete('save (insert)');

The last inserted id was requested after the completion of the transaction which made the id = 0.

This is a silly bug that unfortunately took me nearly 4 hours to track down, *ugh*!


DataMapper 1.6.0 - El Forum - 02-14-2009

[eluser]OverZealous[/eluser]
What database are you using? I have been using the last id for a long time, as, I'm sure, have many others, without issue.


DataMapper 1.6.0 - El Forum - 02-14-2009

[eluser]dobomode[/eluser]
I am using PHP 5.2.6 with MySQL 5.1.31 on a Mac OS X Leopard 10.5.6 machine.
In datamapper.php, I have $config['auto_transaction'] = TRUE;