0

I have a JSON array in an array:

{
 layouts: [
    {
      w: 6,
      h: 4,
      x: 0,
      y: 0,
      i: "n0",
      minW: 1.5,
      minH: 1,
      maxH: 1000,
      moved: false,
      static: false,
      widget: "Clock"
    },
    {
      w: 2,
      h: 2,
      x: 0,
      y: 4,
      i: "n1",
      minW: 1,
      minH: 1,
      maxH: 1000,
      moved: false,
      static: false,
      widget: "Weather"
     }
  ]
}

I need to store each widget layout in a database. When I'm trying to execute the query It returns an error that the values are empty. I tried some examples from here but they don't work for me.

function:

public function store(Request $request)
{

    $JSON = json_decode($request);

    foreach (array($JSON) as $data) {

        $i = 0;

        $w = $data[$i]['w'];
        $h = $data[$i]['h'];
        $x = $data[$i]['x'];
        $y = $data[$i]['y'];
        $i = $data[$i]['i'];
        $minW = $data[$i]['minW'];
        $minH = $data[$i]['minH'];
        $maxH = $data[$i]['maxH'];
        $moved = $data[$i]['moved'];
        $static = $data[$i]['static'];
        $type = $data[$i]['type'];

        DB::table('widgets')->insert(
            ['w' => $w,
             'h' => $h,
             'x' => $x,
             'y' => $y,
             'i' => $i,
             'minW' => $minW,
             'minH' => $minH,
             'maxH' => $maxH,
             'moved' => $moved,
             'static' => $static,
             'type_widget' => $type]
        );

        $i++;

    }

    return response()->json(201);
}

Could anyone tell me what is the correct way to loop through the data to save it?

Baspa
  • 1,099
  • 1
  • 18
  • 49

3 Answers3

3

You need to use json_decode($array, true) the second argument (true) indicates that the input string needs to be converted to an associative array, resulting in the correct parsing of your JSON.

You can also extract the JSON directly from the Request with $request->all(). I would recommend this approach as this is a lot easier and the array will always be correctly parsed. Decoding the Request object could result in a different array formatting than you originally submitted (contain data of the Request object itself in addition to your data).

Sven Hakvoort
  • 3,543
  • 2
  • 17
  • 34
  • When i'm trying to use getBody() it says: Method Illuminate\Http\Request::getBody does not exist. Do I have to add something extra to the code in order to use it? – Baspa Oct 10 '18 at 12:31
  • @Baspa, sorry I accidentaly used the wrong `Request` class from another php library I use xD. I updated my answer with the correct method – Sven Hakvoort Oct 10 '18 at 12:37
  • No problem thanks for updating your answer. Should I write it like this $array = $request-all() before decoding it? – Baspa Oct 10 '18 at 12:40
  • @Baspa, you can do that if you prefer it for readability but it is not required :) also dont forget to add the `>` after `-` so it is like this: `->` ;) – Sven Hakvoort Oct 10 '18 at 12:42
  • I added the code but now it says: json_decode() expects parameter 1 to be string, array given. Any idea on how to fix this? – Baspa Oct 10 '18 at 12:42
  • `$request->all()` also returns an array :) so JSON decode is not necessary anymore. I updated my answer for this @Baspa – Sven Hakvoort Oct 10 '18 at 12:45
  • Thanks for your answer! I'm getting a new error now: Undefined offset: 0. I will try to fix it I think your answer solved my problem – Baspa Oct 10 '18 at 12:46
1

When you succeed with Sven Hakvoorts answer, here is a shorter version of your foreach

$i = 0;
$data = json_decode($request, true);
while (isset($data['layouts'][$i])) {
    DB::table('widgets')->insert($data['layouts'][$i]);
    $i++;
}

Even shorter (and best way):

foreach ($data['layouts'] as $row) {
    DB::table('widgets')->insert($row);
}

I think you will have to rename just one column to make this short code work: type_widget to type, this way your fields and column names are equal which results in a lot shorter code as you can see.

sietse85
  • 1,488
  • 1
  • 10
  • 26
  • Thanks for the shorter version of the foreach. I tried your code but it says: array_keys() expects parameter 1 to be array, null given. I changed type_widget to type. – Baspa Oct 10 '18 at 12:22
  • You could shorten it even more to `DB::table('widgets')->insert($data);` – Nigel Ren Oct 10 '18 at 12:30
  • It says: ::insert() must be of the type array, null given @NigelRen – Baspa Oct 10 '18 at 12:33
  • Seems like $data isn't an array but how is that possible – Baspa Oct 10 '18 at 12:36
  • I think $data is just the one record of data. – Nigel Ren Oct 10 '18 at 12:53
  • When I try your code it doesn't upload anything to the database but I don't get any error messages anymore – Baspa Oct 10 '18 at 13:11
  • It looks like this: array(1) { ["layouts"]=> array(3) { [0]=> array(11) { ["w"]=> int(2) ["h"]=> int(2) ["x"]=> int(0) ["y"]=> int(0) ["i"]=> string(2) "n2" ["minW"]=> int(1) ["minH"]=> int(1) ["maxH"]=> int(1000) ["moved"]=> bool(false) ["static"]=> bool(false) ["widget"]=> string(5) "Photo" } } }. So the keys are equal to my db column names. @sietse85 – Baspa Oct 10 '18 at 14:43
  • That did it. But somewhere it's still not good because I get the following error. Column not found: 1054 Unknown column '0' in 'field list' (SQL: insert into `widgets` (`0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `13`, `14`, `15`, `16`, `17`, `18`, `19`, `20`, `21`) values (w, h, x, y, i, minW, minH, maxH, moved, static, widget, 2, 2, 0, 0, n2, 1, 1, 1000, 0, 0, Photo))". Do I have to use a foreach- or for-loop to loop through the array instead of a while-loop or does that not matter? – Baspa Oct 10 '18 at 17:13
  • oh btw did you edit in my latest change? `DB::table('widgets')->insert($data['layouts'][$i]);` – sietse85 Oct 10 '18 at 17:25
  • Thank you very much for you help, it's done! Changed the last bit and now it's working perfectly. – Baspa Oct 10 '18 at 17:53
0

1.

$JSON = json_decode($request);

change it to

$JSON = json_decode($request,true);

2. remove $i=0 from foreach loop and place it at befor foreach loop

sangamesh
  • 21
  • 4