Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Add a post event trigger in the renderEntity method of the Hal plugin #46

Closed
pietervogelaar opened this issue Jun 30, 2014 · 5 comments
Closed

Comments

@pietervogelaar
Copy link

The renderEntity method of the \ZF\Hal\Plugin\Hal plugin triggers an event on the first line of that method. It would be very nice if an event is also triggered add the bottom of that method, just before the entity is returned.

That way I can modifiy some data in the array before it's returned.

/**
     * Render an individual entity
     *
     * Creates a hash representation of the Entity. The entity is first
     * converted to an array, and its associated links are injected as the
     * "_links" member. If any members of the entity are themselves
     * Entity objects, they are extracted into an "_embedded" hash.
     *
     * @param  Entity $halEntity
     * @return array
     */
    public function renderEntity(Entity $halEntity, $renderEntity = true)
    {
        $this->getEventManager()->trigger(__FUNCTION__, $this, array('entity' => $halEntity));

        //...

        // Add something like this:
        $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array('entity' => $entity));

        return $entity;
}
@weierophinney
Copy link
Member

Question: why can you not modify the entity during the original event?

We pass the ZF\Hal\Entity instance to the renderEntity event, which means you have the option of adding, removing, or modifying any links, as well as even modifying the composed object/array. The rest of the method is around creating a serialization of the Entity.

As such, you can do your modifications already within the event... unless I'm missing something. Can you elaborate on what you're trying to do, please?

@pietervogelaar
Copy link
Author

For certain properties of a Doctrine entity I add a custom hydrator strategy called "HiddenStrategy". This strategy converts the value of the property to "_ HIDDEN _".

At the moment I have the class extended with this method:

/**
     * {@inheritDoc}
     *
     * Extends the parent to remove properties with the value __HIDDEN__.
     */
    public function renderEntity(Entity $halEntity, $renderEntity = true)
    {
        $entityArray = parent::renderEntity($halEntity, $renderEntity);
        foreach ($entityArray as $property => $value) {
            if ($value === '__HIDDEN__') {
                unset($entityArray[$property]);
            }
        }

        return $entityArray;
    }

I unset the keys that have _ HIDDEN _ as value. Because this is the latest place before output. At the moment there is only a trigger at the beginning of the method. But there the HAL entity still holds a Doctrine entity and strategies are not applied yet. So at the end of the method I have a nice array that I can modify just before output.

@weierophinney
Copy link
Member

Why not have your hydrator simply not return those properties, instead of marking them as __HIDDEN__?

@pietervogelaar
Copy link
Author

How would I do that? The hydrator strategies work on a specific field. I don't want to create a custom hydrator class for every rest service. It's a breeze to just use the default phpro abstract hydrator and configure strategies for the hydrator in the module.config.php file of some API module.

My current class is:

<?php

namespace Application\Stdlib\Hydrator\Strategy;

use Zend\Stdlib\Hydrator\Strategy\StrategyInterface;

class HiddenStrategy implements StrategyInterface
{
    /**
     * Converts the given value so that it can be extracted by the hydrator.
     *
     * @param mixed   $value The original value.
     * @param object $object (optional) The original object for context.
     * @return mixed Returns the value that should be extracted.
     */
    public function extract($value)
    {
        $value = '__HIDDEN__';

        return $value;
    }

    /**
     * Converts the given value so that it can be hydrated by the hydrator.
     *
     * @param mixed $value The original value.
     * @param array  $data (optional) The original data for context.
     * @return mixed Returns the value that should be hydrated.
     */
    public function hydrate($value)
    {
        return $value;
    }
}

If I return nothing in the extract method the property will still be available, but will just have a NULL value.

@weierophinney
Copy link
Member

This is now available on the develop branch; you can pin composer to use zf-hal with versions ~1.1-dev@dev or dev-develop@dev in order to test. See #79 for details.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants