Welcome Guest, Not a member yet? Register   Sign In
CI + DataMapper + sort relationships
#1

[eluser]chrisloki[/eluser]
Hi guys,

I'm quite new in the "CI" world, though I have some experience with frameworks.

I'm using DataMapper ORM with CI in order to do some tasks, and I have to do something I couldn't achieve with.
Imagine two models, A and B. A has a has_many relationship to B:

function A extends DataMapper {
var $has_many = array("B");
}

I created the intermediate table A_B, and the relationship is working fine.
I can sort the list of B's by any field, but I need to rearrange it in other order.
By example, i have an category and it has a list of posts. How could I sort the lists of posts?

With (the ORM) Hibernate in Java, I can crate in the intermediate table a new field (I usually call it element_position) which I use to set the position/order, and there I do some like this:

A_id | B_id | element_position
1 | 1 | 0
1 | 2 | 2
1 | 3 | 1


Does anyone have an idea of how to implement this with DataMapper?

[]s!
#2

[eluser]BrianDHall[/eluser]
Datamapper is built in top of ActiveRecord, so you can do:

Code:
$a = new A();

$a->where('id', 1)->b->order_by('post', 'ASC")->get();

In Overzealous Extension check the _template.php file in your models directory. For each model you can use a default sort order:

Code:
// --------------------------------------------------------------------
    // Default Ordering
    //   Uncomment this to always sort by 'name', then by
    //   id descending (unless overridden)
    // --------------------------------------------------------------------
    
    // var $default_order_by = array('name', 'id' => 'desc');
    
    // --------------------------------------------------------------------

I think that should handle what you are looking for.
#3

[eluser]chrisloki[/eluser]
Brian, thanks for the help. I'll take a look at this _template.php, but at a first glance it is not what I'm looking for.

Imagine that the user can order a list (B, in this case) the way he wants: he can move the first item to the last position, or swap two itens from the B's list.
The usage of this, in my case, is a part of a website where each user can have a list of items and he can manage the order of this list, the way que wants.

Anyway, thanks for answering and the care Smile
#4

[eluser]BrianDHall[/eluser]
Oooo, do you want custom sort ordering, I see.

In that case you need another table column, and you need some way to manipulate it. You can use default sort order to sort by this display_order field.

Then, however you have to have some sort of interface and logic for setting and changing such things. There is nothing in MySQL that supports this sort of functionality outside of a special field, so Datamapper can't really do much about it.

What I do is use this field and then allow the user to assign values to things in simple text fields. I didn't want fancy javascripting so a person can either just be happy assigning a bunch of things to the default value of say, 50 - then if they want something below everything else they set it to a higher number, and if they want it higher they set it to a lower number.

You could also do a "move up" selection form, then have your model control the logic of "this is number 5 and needs moved up, so set field number 4 to field 5 and then set this field to 4...". The fancy whizz-bang feature would be a javascripted list that allows selections to be moved up and down, or even dragged and drop would be cool. Then when you click submit it submits IDs in the order they appear - then you have your model go through and assign the display_order based on order of the reordered list, and there you go.

I've been intending to build a feature like this myself, just haven't needed it badly enough to want to go to the trouble of a more robust, end-user friendly system as it is just for my admins and me to use.
#5

[eluser]chrisloki[/eluser]
That's exactly what I need.

How I said, if I could manipulate de intermediate table (A_B) like Hibernate does (adding another field, in this case element_position), then it would be lot easier.
I would have and table like:


A_id | B_id | element_position
1 | 1 | 0
1 | 2 | 2
1 | 3 | 1
2 | 1 | 2
2 | 2 | 1
2 | 3 | 0

and this table will guarantee integrity of the data.

Doin' what you've said, is possible, but I think it's not the best way: I would have to first get this text field with the desired order (splitting the values) and iterate, and for each value do a select query to get each B in the desired order.

I'll take a look later if I can manage this - I work half part with java+velocity, half parte with PHP.

Thanks again, and sorry for any bad english (this is not my home language)!
#6

[eluser]BrianDHall[/eluser]
That is an interesting way of handling it, and probably is a better way now that you mention it. I haven't heard of anything in PHP (orm or otherwise) that does this, but its an awful good idea.
#7

[eluser]Chad Fulton[/eluser]
I've used a system similar to this to allow easy custom ordering of menu items. In my case, I don't need an intermediate table, since I use a self-referential type relationship (and I'm afraid I've never used DataMapper, so I can't comment on it specifically).

I won't comment on your back-end implementation, since I'm not really sure what you're going for, but I thought I'd suggest that if you're interested in an AJAX front end, you might consider the jQueryUI draggable functionality, which is what I've been using.

A few caveats:
1. It's a big pain to set up nesting with it. When I did it (a few months ago), I sort of had to make it up as I went along, since it's not well documented (even though it's a much-requested feature), and there are a bunch of quirks to work out.

2. jQuery UI is pretty huge by default(200kb), although if you only want the draggable functionality, I think you can get it to be manageable (26kb or so, in addition to the 57kb of jQuery itself, and less if you gzip).
#8

[eluser]chrisloki[/eluser]
@Brian I think I found a solution for this: OverZealous
http://www.overzealous.com/dmz/
it's a new version of DataMapper. With this, it's possible to add extrafields to the table that represents the relationship, what they call Join Fields
http://www.overzealous.com/dmz/pages/joinfields.html

@chad thanks for the tips! Actually, I'm very confortable with javascript UIs (based on Prototype, jQuery and the YUI). I'm going to use the jQuery UI indeed, and the frontend side of the app is not the issue (I'm coming to the backend side of apps now!)

Thanx again, guys, and I'll make a post with my try with the OverZealous!
#9

[eluser]BrianDHall[/eluser]
[quote author="chrisloki" date="1257834751"]@Brian I think I found a solution for this: OverZealous
http://www.overzealous.com/dmz/
it's a new version of DataMapper. With this, it's possible to add extrafields to the table that represents the relationship, what they call Join Fields
http://www.overzealous.com/dmz/pages/joinfields.html
[/quote]

Oooo, I never even thought of join fields! OZ suggested the posibility recently on using them for another project problem I had, but I've yet to delve into them to figure what they are all about.

Hope it solves your problem, and I think many of us would be very interested in how you work it out. I certainly would Smile




Theme © iAndrew 2016 - Forum software by © MyBB