Welcome Guest, Not a member yet? Register   Sign In
[Deprecated] DMZ 1.5.3 (DataMapper OverZealous Edition)

[eluser]naren_nag[/eluser]
[quote author="OverZealous.com" date="1249516920"]Naren,
Code:
$userObject->authored_knowledge->distinct()->where_related('group', 'id >', 0)->count();
                               ^^^^^^^^^^^^

Should work, not tested. ;-)[/quote]

Doesn't work Smile ... correct me if I'm wrong, but the distinct() will return distinct knowledge ids ... and if I add it after the where_related then it will return distinct group ids.

So I have a users table, a knowledge table and a groups table.

a user creates many knowledge items and each knowledge item gets published to multiple groups. If a knowledge item isn't published its a draft. This query returns the number of groups knowledge items have been published to. So even if a single item has been published to three knowledge items, it will return three, as compared to one.

I've tried a group by as well .. no dice :[

This isn't all that vital .. I am going to have a process running that will update these values in the user table rather than running complex queries over and over again Smile

It's just an interesting problem eh ...

naren

[eluser]OverZealous[/eluser]
@Naren:
First, Distinct works on the object you are querying. In this case, you are querying Knowledge:
Code:
$userObject->authored_knowledge->distinct()->where_related('group', 'id >', 0)->count();
// is the same as
$k = $userObject->authored_knowledge;
$k->distinct()
$k->where_related('group', 'id >', 0)
$k->count();

However, it won't work, as you determined. I did some tests. The correct solution looks like this in SQL:
Code:
SELECT COUNT(DISTINCT knowledges.id)
FROM knowledges
LEFT OUTER JOIN users as authors ON knowledges.author_id = authors.id
LEFT OUTER JOIN groups_knowledges ON groups_knowledges.knowledge_id = knowledges.id
LEFT OUTER JOIN groups ON groups_knowledges.group_id = groups.id
WHERE authors.id = 1
    AND groups.id > 0

Currently there is no way to call COUNT(DISTINCT) (which is only supported on certain databases anyway).

The best workaround I can see for now is this:
Code:
$k = $userObject->authored_knowledge->distinct()->select('id')->where_related('group', 'id >', 0)->get();
$count = count($k->all);

Which works pretty well, because you only query the ids. It's not nearly as efficient, admittedly. I'll look at implementing a count_distinct($column) in the future.

[eluser]mcnux[/eluser]
Could someone please advise me how I can create a transaction to span multiple updates on multiple models. Here's an example of what I'm trying to achieve:

Code:
$model1->trans_start();

$model1->save();
$model2->save();

die();

$model1->trans_complete();

In reality I would obviously handle failures from the saves but I was expecting the rollback to occur as the script dies before the transaction is committed. I can get this to work when auto_transaction is set to false but I would like to have this ability even with it on (or at least be able to turn off auto_transaction at runtime to enable me to perform the transaction).

Please advise. Thanks.

[eluser]OverZealous[/eluser]
@mcnux
What's not working? That's exactly how you do it (well, except I think you should always call show_error instead of die).

I prefer using trans_begin, trans_commit, and trans_rollback explicitly, because I can control the transaction better that way.

@everyone
I'm testing something, and I would like your feedback. It turns out that it is very easy to implement iterators for PHP classes. What this means is I can modify DMZ so that you can write code like this:
Code:
$objects = new Object();
$objects->get();
// Notice: no ->all necessary
foreach($objects as $object) {
    // do whatever
}

It's a very painless thing to add, but it does have the risk of breaking code. If you ever purposefully looped over a DMZ object to check it's values, that will no longer work. However, it will probably save a lot of headaches, since even I forget to add ->all about once every 10 loops I write!

You can download a version of 1.4.1 with this feature enabled here. See if it breaks anything. I haven't committed myself to the change yet.

---------------

Finally, a tidbit I just learned today: if you haven't enabled a PHP accelerator, I highly recommend you try one.

I just installed eAccellerator (a simple "yum install php-eaccellerator" followed by "service httpd restart"), and I am amazed at how much better my pages are performing. CI and DMZ are great candidates for this, because they do load up quite a bit of code. I think the gains from this are actually greater than anything normal caching could provide. :-)

[eluser]mcnux[/eluser]
[quote author="OverZealous" date="1249580887"]@mcnux
What's not working? That's exactly how you do it (well, except I think you should always call show_error instead of die).

I prefer using trans_begin, trans_commit, and trans_rollback explicitly, because I can control the transaction better that way.
[/quote]
The transaction is not rolling back unless I turn off auto_transaction. I'm guessing this is because the auto commit after the first save essentially commits my wrapping transaction? If it is, I guess the auto transactions would need to check that a transaction hasn't already been started? Or am I missing something?

(P.S. I only used die() to make it clear the script dies Smile)

Quote:@everyone
I'm testing something, and I would like your feedback.
...
Like it. Will download 1.4.1 shortly. How difficult would it be to add a boolean setting to DMZ config to enable/disable this feature?

Quote:Finally, a tidbit I just learned today: if you haven't enabled a PHP accelerator, I highly recommend you try one.
...
Thanks for the heads up. Will check it out.

[eluser]OverZealous[/eluser]
I should have mentioned that - auto transactions basically break transactions. I don't know why stensi included them, or if they even do anything useful. ;-)

The iterator feature has to be part of the core class. So, it's not something I can easily enable or disable completely. However, there is a way to still allow looping over the class itself, but I'm not sure how well it will work.

I'm going to wait on more feedback before deciding to keep the iterator or not. I'd prefer to have it all-or-nothing, to prevent confusion.

[eluser]mcnux[/eluser]
[quote author="OverZealous" date="1249582900"]I should have mentioned that - auto transactions basically break transactions. I don't know why stensi included them, or if they even do anything useful. ;-)
[/quote]
Doh. They are pretty darned useful, as far as I can tell; they appear to wrap every save()/delete() call in a transaction so that if, for example, a relationship fails to save/delete, the transaction rolls back. Having said that, surely when a relationship saves it's going to complete the outer transaction, as it does in my example so maybe it is completely pointless. Will test it out.

Quote:The iterator feature has to be part of the core class. So, it's not something I can easily enable or disable completely. However, there is a way to still allow looping over the class itself, but I'm not sure how well it will work.

I'm going to wait on more feedback before deciding to keep the iterator or not. I'd prefer to have it all-or-nothing, to prevent confusion.
Oh yeah the class has to implement iterator interface, good point. I would be surprised if anyone is looping over their models but think you're wise to be cautious. Tis much more graceful than having to access all every time, imho.

[eluser]tdktank59[/eluser]
Ok so im trying to use your htmlform extension!

heres the code
Code:
$form = array( 'id',
                        'Assign Set of Problems' => 'section',
                        'number_of_records',
                        'employer_type',
                        'work_category',
                        'assign_to',
                        'comment'
                    );

        $u = new User();
        $u->load_extension('htmlform');
        echo $u->render_form($form, 'users/save');

and heres what its spitting out

Quote:number_of_recordsemployer_typework_categoryassign_tocomment
Assign Set of Problems
[Save]

Where [Save] is an actual button. However the inputs are not happening...

config:
Code:
$config['extensions_path'] = 'datamapper';
$config['extensions'] = array('htmlform');

And the views have been copied over. to dmz_htmlform under views

I was for some reason able to get your demo to work however I cannot make it work on my side without the demo...

[EDIT]
Woops... I figured it out right after I posted this... That I need to define the stuff in the model in order for it to work!

[eluser]pdswan[/eluser]
Thanks for the excellent work!

Wanted to let you know there is a typo on line 308 of the latest version of datamapper.php that causes an undefined variable error when trying to load extensions via the $extensions var in models.

Code:
$extentions = $this->extensions;
$this->extensions = array();
DataMapper::_load_extensions($this->extensions, $extensions);
DataMapper::$common[$common_key]['extensions'] = $this->extensions;

should be

Code:
$extensions = $this->extensions;
$this->extensions = array();
DataMapper::_load_extensions($this->extensions, $extensions);
DataMapper::$common[$common_key]['extensions'] = $this->extensions;

[eluser]OverZealous[/eluser]
@pdswan
Ach! Thanks!

I made the change, I'll push it out with the next maintenance release (probably sometime tomorrow, depending on the feedback from the iterator update.)




Theme © iAndrew 2016 - Forum software by © MyBB