Jan Siepmann
Jan Siepmann

Reputation: 39

How access array with specials characters in array key

I tried to wrap my mind round how to decompose a value of an array where the key is a string containing special characters.

<f:debug> output of parent

parent.child. does give the five entries that I don't need :-)

parent.child.http://... doesn't work, I think because if the special characters.

Is there a way to escape that array index string?

Any hints would be appreciated.

Upvotes: 1

Views: 467

Answers (4)

Jan Siepmann
Jan Siepmann

Reputation: 39

Georg Ringer's suggestion got me on the right track. I added a custom Viewhelper to to acccess the custom rss tags via SimplePIE. It takes the namespace and that tag I need and return the desired values.

Thank you all very much for your help.

Upvotes: 0

biesior
biesior

Reputation: 55798

In your question, you hide the most important thing - the key value. However as we can see it's a URL with a domain name it's quite obvious it contains a dot inside, which is the problem.

Literally, the Fluid tries to access the array structure like it was nested one level deeper, so instead of

$array['http://example.com/path/to/your/script'] it tries to access
$array['http://example']['com/path/to/your/script'].

You don't mention what is the clue of using such complicated keys for your array, anyway you need to get rid of the special chars to make it work.

One way is converting that structure in your controller, before assigning to the view. It's a simple foreach(), so I won't write it, but you need to get a structure like (pseudo code)

$array = [
    'xml_base' => '',
    'children' => [
        'http_domain_com_path_to_your_script' = [
             'url' => 'http://example.com/path/to/your/script',
             'other' => 'attr',
        ],
        'http_another_com_path_to_your_script' = [
             'url' => 'http://another.com/path/to/your/script',
             'other' => 'attr',
        ],
    ]
]

and access it as parent.children.http_domain_com_path_to_your_script

or even convert it to the non-associative array

$array = [
    'xml_base' => '',
    'children' => [
        [
            'url' => 'http://example.com/path/to/your/script',
            'other' => 'attr',
        ],
        [
            'url' => 'http://another.com/path/to/your/script'
            'other' => 'attr',
        ],
    ]
]

So you can access it by numeric values like parent.children.0

Finally, you can also check Georg's solution, which allows accessing such keys, anyway didn't test ever, and personally I prefer way with simplified keys.

Upvotes: 0

Wolffc
Wolffc

Reputation: 1250

Another option would be to prepare your data in the controller to a more "suitable" format.

Upvotes: 1

Georg Ringer
Georg Ringer

Reputation: 7939

I suggest using a custom ViewHelper. One example is kind of just copy paste + adjusting the namespace, from powermail: https://github.com/einpraegsam/powermail/blob/develop/Classes/ViewHelpers/Misc/VariableInVariableViewHelper.php

<?php
declare(strict_types=1);
namespace In2code\Powermail\ViewHelpers\Misc;

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Reflection\Exception\PropertyNotAccessibleException;
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
use TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperInterface;

/**
 * Class VariableInVariableViewHelper
 */
class VariableInVariableViewHelper extends AbstractViewHelper implements ViewHelperInterface
{
    use CompileWithRenderStatic;

    /**
     * Initialize arguments.
     */
    public function initializeArguments()
    {
        parent::initializeArguments();
        $this->registerArgument('obj', 'mixed', 'Object', true);
        $this->registerArgument('prop', 'string', 'Property', true);
    }

    /**
     * Solution for {outer.{inner}} call in fluid
     *
     * @param array $arguments
     * @param \Closure $renderChildrenClosure
     * @param RenderingContextInterface $renderingContext
     *
     * @return mixed
     * @throws PropertyNotAccessibleException
     */
    public static function renderStatic(
        array $arguments,
        \Closure $renderChildrenClosure,
        RenderingContextInterface $renderingContext
    ) {
        $obj = $arguments['obj'];
        $prop = $arguments['prop'];
        if (is_array($obj) && array_key_exists($prop, $obj)) {
            return $obj[$prop];
        }
        if (is_object($obj)) {
            return ObjectAccess::getProperty($obj, GeneralUtility::underscoredToLowerCamelCase($prop));
        }
        return null;
    }
}

Upvotes: 1

Related Questions