graphql icon indicating copy to clipboard operation
graphql copied to clipboard

Adding an Array to Arguments Adds as String

Open iveoles opened this issue 9 months ago • 1 comments

Any assistance on adding arrays of values are arguments? I'm getting extra string values which is then causing the queries to fail.

$baseQuery = (new \GraphQL\Actions\Query($class, [
            'nearVector' => [
                'vector'    => "test",
                'certainty' => 0.7,
            ],
            'limit'      => $limit,
        ]))
            ->root()
            ->query();

Outputs the following

{
    Task(nearVector: { "vector" : "test", "certainty" : 0.7 } limit: 100)
}

Whereas it should be

{
    Task(nearVector: { vector : "test", certainty : 0.7 } limit: 100)
}

iveoles avatar Apr 29 '25 13:04 iveoles

Created a fix that works for me, but likely needs proper testing for wider use-cases. I need to update the GraphQL\Entities\Argument class.

<?php


namespace GraphQL\Entities;


use GraphQL\Contracts\Entities\ArgumentInterface;
use GraphQL\Traits\IsStringableTrait;

class Argument implements ArgumentInterface
{
    use IsStringableTrait;

    protected ?string $key;

    /**
     * @var mixed
     */
    protected $value;

    public function __construct($value, ?string $key = null)
    {
        $this->key   = $key;
        $this->value = $value;
    }

    public function getKey(): ?string
    {
        return $this->key;
    }

    public function getValue()
    {
        return $this->value;
    }

    public function toString(): string
    {

        if (is_numeric($this->key) || empty($this->key)) {
            if (is_string($this->value)) {
                return $this->value;
            }

            return json_encode($this->value);
        } elseif (is_object($this->value) && enum_exists(get_class($this->value))) {
            return $this->key.': '.$this->value->name;
        } elseif (is_array($this->value)) {
            return $this->key.': '.$this->js_object_literal($this->value);
        }

        return $this->key.': '.json_encode($this->value);
    }

    public function js_object_literal($data): string
    {
        if (is_array($data)) {
            // Check if it's a sequential array (like a JS array)
            $isList = array_keys($data) === range(0, count($data) - 1);
            if ($isList) {
                $items = array_map([$this, 'js_object_literal'], $data);

                return '['.implode(',', $items).']';
            } else {
                $pairs = [];
                foreach ($data as $key => $value) {
                    $pairs[] = $key.':'.$this->js_object_literal($value);
                }

                return '{'.implode(',', $pairs).'}';
            }
        } elseif (is_string($data)) {
            return '"'.addslashes($data).'"';
        } elseif (is_bool($data)) {
            return $data ? 'true' : 'false';
        } elseif (is_null($data)) {
            return 'null';
        } else {
            return (string) $data;
        }
    }

}

iveoles avatar Apr 29 '25 14:04 iveoles