Problem/Motivation

The EntityMetadataWrapper is really helpful but it is a relatively painful to call entity_metadata_wrapper each time we need it.
Plus, developpers should not have to instanciate it multiple times nor pass it to all their functions as arguments to avoid performances issues.

Proposed resolution

I propose to include a getter in the Entity base class which will build the wrapper on-demand then serve it to the developper.
The EntityMetadataWrapper instance would be easily accessible without needing to be instanciated many times.

Remaining tasks

Create a getter in the Entity class.

API changes

New Entity::wrapper public method, returning an EntityMetadataWrapper class.

Current usage :

<?php
// In each function needing it it creates a new EntityMetadataWrapper class.
$wrapper = entity_metadata_wrapper($entity->entityType(), $entity);
?>

With this new method :

<?php
// Uses always the same EntityMetadataWrapper class because it is stored in the Entity item.
$wrapper = $entity->wrapper();
?>
Files: 
CommentFileSizeAuthor
#8 entity-add_entity_metadata_wrapper_getter-2039601-8.patch958 bytesDuaelFr
PASSED: [[SimpleTest]]: [MySQL] 409 pass(es).
[ View ]
#8 interdiff.txt415 bytesDuaelFr
#2 entity-add_entity_metadata_wrapper_getter-2039601-2.patch866 bytesDuaelFr
PASSED: [[SimpleTest]]: [MySQL] 374 pass(es).
[ View ]
#1 entity-add_entity_metadata_wrapper_getter-2039601-1.patch743 bytesDuaelFr
PASSED: [[SimpleTest]]: [MySQL] 374 pass(es).
[ View ]

Comments

Assigned:DuaelFr» Unassigned
Status:Active» Needs review
StatusFileSize
new743 bytes
PASSED: [[SimpleTest]]: [MySQL] 374 pass(es).
[ View ]

Remaining tasks

Create a getter in the Entity class.

This patch is part of the #1day1patch initiative.

StatusFileSize
new866 bytes
PASSED: [[SimpleTest]]: [MySQL] 374 pass(es).
[ View ]

Improved comment on the wrapper() method.

Status:Needs review» Reviewed & tested by the community

Works for me, and quite useful. Small & clean patch.

Status:Reviewed & tested by the community» Needs work

I like the idea, problem is just that the wrapper could be changed to hold another entity. Let's better create a new wrapper for each method call.

I am really sorry fago but I don't understand what you mean.

The wrapper is stored in the Entity so I don't understand how and why it could hold another Entity. Each Entity could have its own wrapper without problem.

I am afraid that developpers would misuse this method if we create a new wrapper on each call.
It is so easy to do something like this :

<?php
echo $entity->wrapper()->field_foo->value() . $entity->wrapper()->field_bar->value();
?>

With the above code it would cause no performance loss but if we create a new wrapper each time how to inform developpers that they have to do womething like the following ?

<?php
$wrapper
= $entity->wrapper();
echo
$wrapper->field_foo->value() . $wrapper->field_bar->value();
?>

I think what fago means is this :

<?php
$wrapper
= $entity->wrapper();
$wrapper->set($another_entity);
?>

and then, $entity->wrapper() holds the entity_metadata_wrapper of $another_entity.

Please correct is I'm mistaken

#6 gets it

Status:Needs work» Needs review
StatusFileSize
new415 bytes
new958 bytes
PASSED: [[SimpleTest]]: [MySQL] 409 pass(es).
[ View ]

I found the time to improve this.
I hope it won't be too bad regarding to performances.

> + elseif ($this->wrapper->value() !== $this) {

I doubt that comparing two objects is particularly good for performance.
However, at this stage we know that the current entity object and the wrapped entity object are of the same entity type (because AFAIK you can only do $wrapper->set() with a entity of the type the wrapper is already set to). So we could just compare IDs by calling the ID getter function on the $wrapper and on $this.

Take a closer look at the official documentation. "==" would not be a good idea because it would compare each property of the two objects recursively but "===" (and "!==") compare the instances of the object so it is just a quick reference check.

The comparison on IDs is as unsafe as not comparing at all because you can always clone an object then alter it. You would get two objects sharing the same ID but not the same values.

I really think that we cannot do better that this condition.

Ah right, got it. (http://php.net/manual/en/language.oop5.object-comparison.php for reference.)

Though I would be inclined to say that if you clone an entity, change properties of the clone, and then put the cloned entity into the wrapper that you got from the original... then your code is totally messed up and insane and badly needs a rewrite ;)

I think the same for the use case exposed in #6 :)