Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Updated: Comment #8
Problem/Motivation
Is there a hasData() or isEmpty() method available in entity_metadata_wrapper()? I haven't seen one. I'd like to avoid messages similar to the error mentioned in #1928884: Provide more info when EntityMetadataWrapperException is invoked when a field happens to be empty. Right now I have to mix field access [if (field_get_items($entity_type, $entity, $field_name) ...
] in with my metadata access just to avoid that error.
Proposed resolution
Create a new public method called hasProperty to be able to do something like:
if (!$wrapper->hasProperty('field_name')) {...}
Create a new public method called isEmpty to be able to do something like:
if (!$wrapper->field_name->isEmpty()) {...}
Remaining tasks
create the hasProperty public method.create the isEmpty public method.
API changes
Before this issue
$infos = $wrapper->getPropertyInfo();
if (!empty($infos['field_my_field']) || !empty($infos['field_my_other_field'])) {
$my_field = $wrapper->field_my_field->value();
$my_other_field = $wrapper->field_my_other_field->value();
if (!empty($my_field)) {
// Do sth.
}
elseif (!empty($my_other_field)) {
// Do sth else.
}
}
After this issue
if ($wrapper->hasProperty('field_my_field') && !$wrapper->field_my_field->isEmpty()) {
// Do sth.
}
elseif ($wrapper->hasProperty('field_my_other_field') && !$wrapper->field_my_other_field->isEmpty()) {
// Do sth else.
}
Comments
Comment #1
NancyDruThere is a dataAvailable() method, but it is protected so we can't use it.
Comment #2
DuaelFrHere is a patch adding a new isEmpty public method.
I will update the issue summary to help the maintainer to review this.
This patch is part of the #1day1patch initiative.
Comment #3
DuaelFrComment #4
DuaelFrI fixed a tiny mistake in the comment.
Comment #5
NancyDruAwesome! Thanks, Edouard. It works great for me.
Comment #6
DuaelFrI have some issues with this new method. It's name suggests that it returns FALSE if the value exists and is not empty while it returns TRUE if the value does not exist or is empty (instead of throwing an exception). In fact, I never seen it returning TRUE and it continues to throw exceptions when used on a non-existing property or field...
I tried to replace it by the following code but it only fix the first behavior and still not allow to easily check if a field/property exists.
May we create another method allowing to do something like this ?
Or may we change the isEmpty method to have something more like this ?
Comment #7
DuaelFrThis patch introduces an
EntityStructureWrapper::hasChild()
method that checks if the given child exists without throwing an exception.It allows to do things like this :
Comment #8
DuaelFrSorry, I forgot to include the
EntityMetadataWrapper::isEmpty()
as exposed in #6Here is a new patch containing the isEmpty() from #6 and the hadChild() from #7
Comment #8.0
DuaelFrIssue summary update.
Comment #9
NancyDruThanks, Edouard.
As long as we are at it, I ran into one this morning: it would be nice to do $wrapper->id(). In my case I am accessing a node, but I have others where I access a user or a profile. It would be nice to get the entity's id field without having to know what kind of entity it is ($wrapper->nid->value() vs. $wrapper->uid->value()
Comment #10
DuaelFrI think you should use the existing
getIdentifier()
public method.Comment #10.0
DuaelFrUpdated issue summary.
Comment #11
joachim CreditAttribution: joachim commentedI'm not sure hasChild() is the right name for that method. Elsewhere, these are called properties, aren't they? And if, say, I have an entityreference field on users, I get a chain of properties $node_wrapper->author->entityref_to_node... child doesn't seem right when these can double back on themselves and be circular...
Comment #12
DuaelFrHi joachim, thank you for your review.
I am sorry but I don't get the point, probably because of the language barrier.
The purpose of this hasChild() method is to safely check if there is a field or a property named like this on the entity before querying it to avoid having to deal with Exceptions. We could name it hasComponent() if it suits better to the concept.
If you think it could lead to an infinite loop in some cases I may have coded it wrong. I don't remember why I didn't use the getPropertyInfo() method instead of get() but if you think it could be better and safer I can rewrite my patch.
Comment #13
joachim CreditAttribution: joachim commentedMy point was entirely about the method name. hasProperty() would be my suggestion.
And I don't mean there's an infinite loop in the code, not at all!
I meant that with the properties that are references to other entities, you can loop round. Eg:
- node has an 'author' property to the user entity
- you can put an entityref field on users that points to nodes, and this will define a property
So if the field on the user points to a node that the user is the author of, you can go $user_wrapper->node_field->author->value() and you're back where you started. Hence 'child' doesn't seem to really fit.
Comment #14
garphy CreditAttribution: garphy commentedhasProperty() seems like a better fit.
it's close to hasOwnProperty() in ECMAScript-ish dynamic languages.
Comment #15
DuaelFrIsn't it confusing to use "property" in the name of a method that can check the existence of properties and fields?
@joachim: sorry for the misunderstanding about the circular relations.
Comment #16
joachim CreditAttribution: joachim commentedTo Entity API metadata wrappers, everything is a property: $node->title becomes the title property, and a node FieldAPI field field_foo becomes the field_foo property.
Comment #17
DuaelFrHere is a new patch.
Comment #18
DuaelFrComment #19
jimmyko CreditAttribution: jimmyko as a volunteer commentedIt would be a great feature. I don't understand why it is still pending.
Comment #20
mariacha1 CreditAttribution: mariacha1 as a volunteer commentedThe hasProperty() method is identical to the output you can get from simply doing isset() on an unknown property, so I don't think that adds anything.
In other words:
Meanwhile, the isEmpty() property seems to be equivalent to calling empty($property->value()), which doesn't help us much. I do see the exception catching there, but I don't think that actually would trigger unless you were calling this method on an undefined property, which can be tested by calling isset. So:
Equals
However, when you combine the idea behind hasProperty with isEmpty by passing the name to isEmpty, you do get a helpful function that catches exceptions AND tells you whether the property is empty:
Thus
I'm updating the patch to combine the two functions in this way. As well as an interdiff.
Comment #21
joelstein CreditAttribution: joelstein as a volunteer commentedLove this! I wanted a simple way to know if a node that I tried to load with entity_metadata_wrapper() exists, without attempting to load the whole node and all it's fields with
$node->value()
.If the node doesn't exist, I can't access
$node->nid->value()
(it throws an exception), even though the property isset.Which this patch, I can simply say
$node->isEmpty()
and get the information I need in a lightweight fashion.Comment #22
bohemier CreditAttribution: bohemier commentedThese are a real nice addition, a must for code readability
Comment #23
jimmyko CreditAttribution: jimmyko as a volunteer commentedI'm not sure if it is good to use exception to handle this case. But a little bit strange to me.
Comment #24
fagoisEmpty() should translate to $value === NULL, if the property does not exist it is not not-empty, it does not exist. I.e., the passed property name is an invalid parameter and should throw an exception. This needs to be documented via @thrown as well.
Misses a new line before @return.
Comment #25
lhridley CreditAttribution: lhridley at Promet Source commentedRerolling the patch from #20, which will apply endlessly creating Fatal errors for duplicate methods.
Comment #26
osopolarI think this is also related to the issue #1596594: EntityMetadataWrapperException: Parent Data Structure Not Set and maybe if that one is fixed this won't be necessary.
Comment #27
jacob.embree CreditAttribution: jacob.embree at St. Louis Integration commentedI was getting a fatal error about calling
value()
onnull
when usingisEmpty()
on a property that doesn't exist. A quick!empty()
seems like a good fit here.