MySQL statements eZ Publish - howto?

Author Message

Clemens T

Thursday 11 December 2008 2:54:17 am

Below, this code seems to be very slow, is there anyway to upgrade performance? For example instead of looping through all the attributes getting directly to the one attribute? But I don't know how...

		$objectAttributes =& $object->ContentObjectAttributes();
		foreach($objectAttributes as $objectAttribute)
		{
			//Fetch the object's attribute 'groups' (which is the related objects attribute)
			$name =& $objectAttribute->contentClassAttributeIdentifier();
			//eZDebug::writeNotice("ObjectAttributeName: $name","Workflow smInternalPressReleaseType");

			if($name == "groups")
			{
				$content = $objectAttribute->content();
				foreach( $content['relation_list'] as $relation)
				{
					//eZDebug::writeNotice("Relation ContentClassID: $relation["contentclass_identifier']","Workflow smInternalPressReleaseType");
					//filter the pr_groups from the related list
					if($relation["contentclass_identifier"] == "pr_group")
					{
						$contentobject_id = $relation["contentobject_id"];
						eZDebug::writeNotice("contentobject_id: $contentobject_id","Workflow smInternalPressReleaseType");

						$node_id = $relation["node_id"];
						eZDebug::writeNotice("node_id: $node_id","Workflow smInternalPressReleaseType");						
						/*
						 * Fetch all the PR_MAIL class ID=29 objects from the related node
						 */
						$subtreeFetchParams=array(
							'ClassFilterType' => 'include',
							'ClassFilterArray' => array(29),
							'status' => EZ_CONTENT_OBJECT_STATUS_PUBLISHED);
						
						$childNodes =& eZContentObjectTreeNode::subTree($subtreeFetchParams,$node_id);
						eZDebug::writeNotice("childNodes: $childNodes[0]","Workflow smInternalPressReleaseType");	
												
						foreach( $childNodes as $child )
						{								
							eZDebug::writeNotice("child: $child","Workflow smInternalPressReleaseType");	
						
							//Child is of type eZContentObjectTreeNode			
							if($child->hasContentObject())
							{
								//Fetch the eZContentObject of this eZContentObjectTreeNode
								$childContentObject =& $child->object();

								//Fetch the contentObjectAttributes
								$childAttributes = $childContentObject->ContentObjectAttributes();
								
								eZDebug::writeNotice("childAttributes: $childAttributes[0]","Workflow smInternalPressReleaseType");	
								eZDebug::writeNotice(print_r($childAttributes));
							
								foreach($childAttributes as $childAttribute)
								{
									//Fetch the object's attribute 'groups' (which is the related objects attribute)
									$childAttributename =& $childAttribute->contentClassAttributeIdentifier();									
									eZDebug::writeNotice("childAttributeName: $childAttributename","Workflow smInternalPressReleaseType");		
						
									//only fetch the e-mailaddress
									if($childAttributename=="email")
									{
										eZDebug::writeNotice("childAttributeName: $childAttribute->content()","Workflow smInternalPressReleaseType");			
										$emailsOfReceivers[] = $childAttribute->content();
									}
								}//foreach childattributes
							} //child->hasContentObject
			
						}//foreach childnodes
					}//if relation_list == pr_group
				}//foreach relation_list
			}//if name=="groups"
		}

Thanks as always!

André R.

Thursday 11 December 2008 4:04:55 am

custom sql..

On the "$node_id = $relation["node_id"];" line, get the path_string for the node so you can use it in where statment of your custom sql to get the email attributes, also use class id and class attribute id instead of identifiers in the sql where / join statments.
You can get this with eZContentObjectTreeNode::classAttributeIDByIdentifier and ::classIDByIdentifier before the loops.

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Clemens T

Thursday 11 December 2008 5:42:29 am

Thanks Andre, I've considered that option... but I believe it could make my code fail in the future, so that's why I've done the following changes (change foreach for a array key lookup). It's much faster now!

		//Reject if this object does not have a valid main node
		if(is_null($mainNodeID))
			return EZ_WORKFLOW_TYPE_STATUS_REJECTED;			
		
		$dataMap = $object->dataMap(); 

		if(array_key_exists( 'groups', $dataMap ) )
		{		
			$content = $dataMap['groups']->content();
			foreach( $content['relation_list'] as $relation)
			{
				//eZDebug::writeNotice($relation["contentclass_identifier"], "internal");		
				//filter the pr_groups from the related list
				if($relation["contentclass_identifier"] == "pr_group")
				{
					$contentobject_id = $relation["contentobject_id"];
					$node_id = $relation["node_id"];
					/*
					 * Fetch all the PR_MAIL class ID=29 objects from the related node
					 */
					$subtreeFetchParams=array(
						'ClassFilterType' => 'include',
						'ClassFilterArray' => array(29),
						'status' => EZ_CONTENT_OBJECT_STATUS_PUBLISHED);
					
					$childNodes =& eZContentObjectTreeNode::subTree($subtreeFetchParams,$node_id);				
					foreach( $childNodes as $child )
					{								
						//Child is of type eZContentObjectTreeNode			
						if($child->hasContentObject())
						{
							//Fetch the eZContentObject of this eZContentObjectTreeNode
							$childContentObject =& $child->object();
							$childDataMap = $childContentObject->dataMap(); 

							//eZDebug::writeNotice("childDataMap :".print_r($childDataMap, true), "internal");	
							if(array_key_exists( 'email', $childDataMap ) )
							{
								eZDebug::writeNotice("Un-uniqueified emailOfReceiver: ".$childDataMap['email']->content(),"Workflow smInternalPressReleaseType");									
								$emailsOfReceivers[] = $childDataMap['email']->content();
							}//array_key_exists (email)
						} //child->hasContentObject		
					}//foreach childnodes
				}//if relation_list == pr_group				
			}//foreach relation_list
		}//if array key exists (groups)

Clemens T

Monday 15 December 2008 4:02:41 pm

The peformance increase I got from editing the code didn't contribute enough to make the system stable enough. Could anyone help me build the SQL that this code produces, since it is the first time I'm attempting that. Or just some pointers on how to work with the MySQL database layer eZ Publish offers.

Thanks!

André R.

Wednesday 17 December 2008 9:10:03 am

This might help:

$node_id = $relation["node_id"];
$subtreeFetchParams = array(
        'ClassFilterType' => 'include',
        'ClassFilterArray' => array(29)
        );

$childNodes =& eZContentObjectTreeNode::subTree($subtreeFetchParams, $node_id);                              
foreach( $childNodes as $child )
{                                                               
    $emailAttribute =& $child->object()->fetchAttributesByIdentifier( array('email') );
    $emailsOfReceivers[] = $emailAttribute->content();
      
}//foreach childnodes

Remove the & after = if your on php5.
Note: If you don't need to check permission, then you can also set 'Limitation' => array() on subtreeFetchParams.

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Clemens T

Thursday 18 December 2008 3:54:59 am

Andre,

Thanks again for putting effort in helping me find a solution.

It most certainly increase the speed of the application, the final code:


					$node_id = $relation["node_id"];
					$subtreeFetchParams = array(
						'ClassFilterType' => 'include',
						'ClassFilterArray' => array(29),
						'Limitation' => array(),
					);
					$childNodes =& eZContentObjectTreeNode::subTree($subtreeFetchParams, $node_id);                              					
					foreach( $childNodes as $child )
					{                                                               
					   $chContentObject =& $child->object();
					   $datamap = $chContentObject->dataMap();
					   $emailsOfReceivers[] = $datamap['email']->content();
					}//foreach childnodes

Unfortunately, the $chContentObject had to be stored in between, before I could get the datamap, but this is already a great improvement. Thanks also for introducing the 'Limitation' = array() to me, because I was already logging a dedicated user in via:

		/*
		 * Log the current logged in user, in order to make sure that we are able to log
		 * him/her in after this event is done. Needed because we change users in the middle.
		 */
		$eZUser = eZUser::currentUser();
		$userID = eZUser::currentUserID();
		
		/*
		 * Login the user that is used for sending the press releases 
		 * (and will be able to read the newsitems / images)
		 *
		 * This is needed because this is being executed by a workflow.
		 */
		$loginResult = eZUser::loginUser("x_read","x");
		if(!$loginResult)
		{
			return $module->handleError( EZ_ERROR_KERNEL_ACCESS_DENIED, 'kernel' );
		}

and then logging out and re-setting the currently loggged in user, so this is a great contribution!

Thanks again :),
Clemens

Powered by eZ Publish™ CMS Open Source Web Content Management. Copyright © 1999-2014 eZ Systems AS (except where otherwise noted). All rights reserved.

eZ debug

Timing: Jan 18 2025 19:38:16
Script start
Timing: Jan 18 2025 19:38:16
Module start 'layout'
Timing: Jan 18 2025 19:38:16
Module start 'content'
Timing: Jan 18 2025 19:38:17
Module end 'content'
Timing: Jan 18 2025 19:38:17
Script end

Main resources:

Total runtime1.1051 sec
Peak memory usage4,096.0000 KB
Database Queries66

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0049 589.3516152.6250
Module start 'layout' 0.00490.0029 741.976639.4609
Module start 'content' 0.00781.0959 781.4375596.5313
Module end 'content' 1.10370.0014 1,377.968824.1563
Script end 1.1050  1,402.1250 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00330.2982160.0002
Check MTime0.00140.1237160.0001
Mysql Total
Database connection0.00080.067910.0008
Mysqli_queries1.046594.6958660.0159
Looping result0.00070.0644640.0000
Template Total1.075597.320.5377
Template load0.00200.182420.0010
Template processing1.073497.137220.5367
Template load and register function0.00010.013010.0001
states
state_id_array0.00080.070310.0008
state_identifier_array0.00090.079320.0004
Override
Cache load0.00170.1531330.0001
Sytem overhead
Fetch class attribute can translate value0.00080.070120.0004
Fetch class attribute name0.00190.173970.0003
XML
Image XML parsing0.00070.065320.0004
class_abstraction
Instantiating content class attribute0.00000.001880.0000
General
dbfile0.00070.0650170.0000
String conversion0.00000.000940.0000
Note: percentages do not add up to 100% because some accumulators overlap

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1node/view/full.tplfull/forum_topic.tplextension/sevenx/design/simple/override/templates/full/forum_topic.tplEdit templateOverride template
6content/datatype/view/ezxmltext.tpl<No override>extension/community_design/design/suncana/templates/content/datatype/view/ezxmltext.tplEdit templateOverride template
12content/datatype/view/ezxmltags/paragraph.tpl<No override>extension/ezwebin/design/ezwebin/templates/content/datatype/view/ezxmltags/paragraph.tplEdit templateOverride template
5content/datatype/view/ezxmltags/literal.tpl<No override>extension/community/design/standard/templates/content/datatype/view/ezxmltags/literal.tplEdit templateOverride template
2content/datatype/view/ezimage.tpl<No override>extension/sevenx/design/simple/templates/content/datatype/view/ezimage.tplEdit templateOverride template
3content/datatype/view/ezxmltags/line.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/line.tplEdit templateOverride template
1print_pagelayout.tpl<No override>extension/community/design/community/templates/print_pagelayout.tplEdit templateOverride template
 Number of times templates used: 30
 Number of unique templates used: 7

Time used to render debug report: 0.0001 secs