How do I return JSON Arrays instead of objects using FuelPHP's ORM and Controller_Rest

StackOverflow https://stackoverflow.com/questions/17033685

  •  31-05-2022
  •  | 
  •  

Question

Controller_Something extends Controller_Rest {
  public function get_something() {    
    $query = Model_Something::query()->related('hasMany')->get();
    return $this->response($query);
  }
}

Returns:

{
  stuff: here,
  looks: good,
  hasMany: {
    151251: {
      id: 151251,
      other: stuff
    }
  }
}

I want the relations as arrays:

{
  stuff: here,
  looks: good,
  hasMany: [
    {
      id: 151251,
      other: stuff
    }
  ]
}

This happens because the ORM returns related result arrays with keys corresponding to the record's PKEY, and JSON interprets this as an Object. I want these arrays to go through array_values() or something, so the JSON result will use Array.

Currently I am doing this to "solve" the problem:

$res = Format::forge($result_set)->to_array();
$res['hasMany'] = array_values($res['hasMany']);
return $this->response($res);

But this is only useful to one or two levels, where I know the data will be.

If there are relations that are not guaranteed, I don't what to have to error-check every potential subset of a complex Model.

I just want all the one-to-many arrays to be keyed sequentially instead of by the records PKEY.

Was it helpful?

Solution 3

In short: you can't unless you create a hook in Query:hydrate https://github.com/fuel/orm/blob/1.7/develop/classes/query.php#L1083, or shadowing the Query class with some implementation that returns the very same results except for hydrate.

OTHER TIPS

$query = Model_Something::find()->related('hasMany');

returns a query object in < 1.6, an exception in 1.6, and null in 1.6.1+. So I assume you do something else that produces that result.

If you want arrays as a result instead of objects, you need to convert the result. You can do that by calling to_array() on a model object, or by using the Format class to convert an array of model objects to an array: $result = \Format::forge($result)->to_array();

function object_to_array($data){
         $new_data2= array();
         $keys   =   array_keys((array)$data);
         foreach ($keys as $key)
        {
            $value  =   $data[$key];

            if(is_numeric($key))
            {
                $new_data2[]    =   object_to_array($value);

            }elseif(is_string($value) || is_null($value))
            {
                $new_data2[$key]    =   $data[$key];
            }else
            {
                $new_data2[$key]    =   object_to_array($value);
            }

        }

        return $new_data2;
    }
$formattedArray  =   \Format::forge(Model_Product::query()->get())->to_array();

$cleanData=object_to_array($formattedArray);

echo \Format::forge($cleanData)->to_json();

This way checks the array key; if key is number and value is object or array clean key

Programmatically it is possible to be done. Following the model below, but for very deep relationships is not interesting by the complexity of the algorithm.

Model:

class Model_Something extends \Orm\Model
{
    ...

    public function relatedAsArray()
    {
        $this->relationsAsArray($this->_data_relations);
    }

    private function relationsAsArray(&$relations)
    {
        foreach ($relations as $key => $relation) {
            foreach ($relation as $fields) {
                foreach ($fields as $field) {
                    if (isset($field->_data_relations)) {
                        $this->relationsAsArray($field->_data_relations);
                    }
                }
            }

            if (is_array($relation)) {
                $relations[$key] = array_values($relation);
            }
        }
    }
}

Call of method:

$something = Model_Something::find($somethingId, array('related' => array('hasMany', 'hasMany.hasOthers')));

$something->relatedAsArray();

The result was exactly like you wanted.

Result:

{
  stuff: here,
  looks: good,
  hasMany: [
    {
      id: 151251,
      other: stuff,
      hasOthers: [
          {
            id: 12312,
            field: other
          }, ...
      ]
    }, ...
  ]
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top