dflydev/dflydev-dot-access-data

Question: Wildcards

Carpenter0100 opened this issue · 2 comments

Hi,
Is it possible to use wildcards?
Sth. like this: "array.value.*.array.value"

Thank you

No, unfortunately this library doesn't directly support searching with wildcards. But it shouldn't be too hard to implement something like that yourself :)

For example, you could split that path by the * to first get all the values at array.value, and then iterate through those to see if any match the rest of the path.

I doubt this library would add native support for wildcards since virtually all operations are designed to operate on a single fixed path (not multiple paths at once).

One operation that could support wildcard without changing the whole design is the remove.

This is really useful for the scope which I'm using the library:
remove specific keys before serialization of data for a comparison before/after.

I've written a small extension to the remove:

    /**
     * {@inheritdoc}
     */
    public function remove(string $key): void
    {
        $currentValue =& $this->data;
        $keyPath = self::keyToPathArray($key);

        $endKey = array_pop($keyPath);
        foreach ($keyPath as $currentKey) {
            if ($currentKey === '*') { /** @todo Add is_iterable($currentValue) in the condition? */
                foreach (array_keys($currentValue) as $concreteKey) {
                    // Replace first occurrence of .*. with the concrete key
                    // https://stackoverflow.com/questions/1252693/using-str-replace-so-that-it-only-acts-on-the-first-match
                    $this->remove(implode(sprintf('.%s.', $concreteKey), explode('.*.', $key, 2)));
                }
            }

            if (!isset($currentValue[$currentKey])) {
                return;
            }
            $currentValue =& $currentValue[$currentKey];
        }
        unset($currentValue[$endKey]);
    }

In my scenario this is enough, but for your library you should adapt the code for:

  • Multiple separators e.g. use for the recursion
     $this->remove(
         preg_replace(
             sprintf('[%1$s]\*[%1$s]', implode('', self::DELIMITERS)), // If '-' would be a delimiter, need to be last
             sprintf('.%s.', $concreteKey),
             $key,
             1
         )
     );
  • Keys beginning with wildcard
  • Keys ending with wildcard (which makes no sense .. but you never know)
  • Custom wildcard character
  • etc.