Welcome Guest, Not a member yet? Register   Sign In
DataMapper 1.6.0

[eluser]Neovive[/eluser]
@stensi: Excellent work on the DataMapper library. Since DM is PHP5 only, have a look at the latest KohanaPHP ORM class in the 2.3 trunk for some examples of ORM optimizations. Some optimizations were recently implemented to reduce the number of queries when working with related tables. DataMapper is a definitely a great extension to CI.

[eluser]phme[/eluser]
Datamapper seems great work indeed.
Too bad for me you're using tight specs such as relationship tables. I understand that it makes things easier to develop, but I can't change my database structure for this project. In my sense, an ORM should map the database structure, not the reverse, but anyway, keep the good work, I'll sure use Datamapper on another project.

[eluser]ntheorist[/eluser]
@phme

it think your right in essence that it makes it more flexible and therefore more practical when applying it to existing databases. Really though, the only addition DM might need to allow for non-5nf set-ups is a join_keys function. That way you could (if desired) run joins based on columns instead of join tables. I'm working on a function like this now, because some meta information i like to store with content shouldn't need a dozen tables to support it.

imo, enforcing a specific database setup helps in that a lot of costly processes like running and analyzing tables can be forgone by assuming a strict db structure. And if you ever wish to think about scalability and performance, then any inefficiency in data retrieval will be scaled likewise.

[eluser]phme[/eluser]
@cc, thanks for the reply, I'd love to see this function if you're happy with it.

I'm not sure I agree on your second paragraph: I'm not a ORM developer, but I'd guess that having an arbitrary rule for joins vs. one that is explicitly defined by the user (as in your join_keys function, I'd think) does not create much overhead. Same goes with the way foreign keys are named, and for that matter, the tables names themselves. But I might be totally wrong.

Conversely, a basic 1-n relationship represented through a relationship table is not normal (in the normalization sense): afaik, the fifth normal form is meant only for n-n relationships. This way does add some overhead -- usually negligible, I agree.

The worst (not uncommon) case I see is the first basic relational structure example one is usually exposed to: the 'customers'-'products'-'orders' case, here translates in five tables and a sale action performs three writes on the database, since there is no mechanism to retrieve specifics of the 'orders' table from the system.

Granted, when we build web applications, we're usually more concerned by reads than writes, and the join does not take much longer, but I still find it a tad shocking.

That said, I'm totally incapable of writing an ORM, even less so one that performs well, as I'm sure DM does, so I really should not even dare open my mouth Smile

[eluser]sankai[/eluser]
I try to use the DM1.4.5 with the HMVC(ME).

The HMVC change the directory structure and got the error 'file isn't exist'
on line 194 in dataMapper.php

Is Maybe be fix on next version?

[eluser]dedavai[/eluser]
First of all, thank you stensi for the wonderful tool. I've been experimenting a bit with DataMapper 1.4.5 runing on CI 1.7 and have 2 issues.

First, let's say we have the database following schema:

Code:
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(40) collate utf8_unicode_ci NOT NULL,
  `type` enum('admin','user') collate utf8_unicode_ci NOT NULL
);

CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(40) collate utf8_unicode_ci NOT NULL,
  `subject` longtext collate utf8_unicode_ci NOT NULL
);

CREATE TABLE IF NOT EXISTS `posts_users` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `post_id` int(10) unsigned NOT NULL auto_increment,
  `user_id` int(10) unsigned NOT NULL auto_increment,
);

INSERT INTO `users` (`id`, `name`, `type`) VALUES (1, 'John Doe', 'admin');
INSERT INTO `users` (`id`, `name`, `type`) VALUES (2, 'Billy Jean', 'user');

INSERT INTO `posts` (`id`, `title`, `subject`) VALUES (600, 'Post 1 title', 'Post 1 subject');

INSERT INTO `posts_users` (`id`, `post_id`, `user_id`) VALUES (20, 600, 1);

Now when we try this:

Code:
$user = new User();
$user->where('id', 1)->get();// get user by id 1
$user->post->get();// get related posts
echo $user->post->id;// PROBLEM - echoes 1 (user_id) instead of 600 (post_id)!

The problem is that $user->post->id returns the $user->id value instead of the $post->id value.


The second issue is getting id doesn't work correctly on newly saved objects:

Code:
$a = new User();
$a->name = "Jim Beam";
$a->type = "user";
$a->save();// OK here - saves the object to the database with a new id
echo $a->id;// PROBLEM - echoes NULL!

I believe this is an issue with $db->insert_id not being saved correctly. Has anyone else encountered these issues?

[eluser]stensi[/eluser]
Hi dedavai. What type of Database are you using? Also, what version of PHP are you running this under?

I was unsuccessful in trying to reproduce your issue. In both situations I received the correct ID.


And just a quick update for all, the next version of DataMapper wont be long now. There's a lot of performance improvements as well some great new functionality on the way!

[eluser]ntheorist[/eluser]
@stensi

Super excited to see the new update! i've been working out ways to improve performance as well. Thought i'd just toss out a few ideas i'm working out and see if you think any are good.

One thing i found is that running isset($array[$value]) is up to 10x faster than in_array($value, $array), so on construction i'm having all arrays converted to string index, and then using isset to check for values. Also i'm finding it handy in getting a specific field from the validation or relation arrays, as opposed to looping each time.

Also, i had replaced the changed_existing methods. I have the constructor creating a stdClass called 'stored', which just creates a copy of the values during a successful get or save.
That way to tell if a value as changed you just check
($this->{$field} == $this->stored->{field) you could use str_comp() too, i suppose. Also it doesn't require additional queries.

I made a few changes to the _to_object() method too, esp with some additional join functions. one change seems to help a lot, especially when creating dynamic forms. i just set
Code:
$index = intval($item->id);
$items[$index] = $item;
so you can access a specific record in the all array with $this->all[$id], or even easily check if an id exists with isset($this->all[$id])

anyway, hope to see the new release soon, thanks for all the hard work Tongue

CC

[eluser]stensi[/eluser]
I'll look at including those changes in the coming version since they're all very good ideas, thanks! :-)

UPDATE: On closer look at the benefits of isset vs in_array, I've found that the performance difference is small enough as to be negligible. So, where it improves functionality, such as with giving the all list access by id and so on, I'll switch to associative arrays and use isset but otherwise I'll leave it as in_array since it provides for cleaner code.

[eluser]ntheorist[/eluser]
cool, thanks! I'll post some more as i figure this stuff out if you like. Here's one more quick handy function i added, which copies over confirm (non-existing) fields automatically, when needed. Also in the config file i added $auto_copy_confirm = TRUE|FALSE, which calls it on a successful get()
Code:
public function copy_confirm_fields()
{
    foreach($this->validation as $field => $data)
    {
        $rules = isset($data['rules']) ? $data['rules'] : array();
            
        if( isset($rules['matches']) )
        {
            $match_field = $rules['matches'];
                
            if( ! empty($this->{$match_field}) )
            {
                $match_field = $rules['matches'];
                $this->{$field} = $this->{$match_field};
                $this->stored->{$field} = $this->{$match_field};
            }
        }
    }
}

I'm working on several other things with DM, too. Like i mentioned in a previous post, i'm sorta working out a framework to use with datamapper. So far I have a Datamapperlist, Datamapperform and Datamapperobject library set going. The object lib is an extender of DM, and those models are loaded into the list and form libraries, which automatically handle what they're supposed to do. for example

Code:
$user = new User();

// Call where/join methods..

$list = new DataMapperList($user);

$list->get(); // sets order_by and limit/offset automatically, as set/stored in session vars

echo $list->get_pager();
echo $list->get_table(); // returns a sortable table of results, with formatted data & other options

// or alternatively..

$list->load_view($view_file);
$list->get_list(); // returns sortable list with each result mapped to $view_file

As far as the form library, i think i may move all the validation functions into that, although that's sort of getting away from what DM intended to be, but i suppose i'm trying to get DM to be 'pure' Database functionality and let the extensions and other libs to do the extra work only when needed. I dunno if that's the best way, but it's new territory for me so i'm giving it a shot. I also want to make a DataMapperUtility library, which can create join tables, edit relationships, or convert foreign key fields to join tables etc. I'll post some more on them later when its all finished up.

edit: yeah i realize the boost in performance is small, and isset can be messier. I mainly just wanted to be able to access data directly without having to always run loops and stumbled upon the isset thing, so i figured why not use it if i converted the arrays anyway. :-P

cheers,

CC




Theme © iAndrew 2016 - Forum software by © MyBB