2

I'm trying to save multidimensional array values into separate strings and store them in the database. I have the following array: My response data:

[
  {
        "name": "bla bla",
        "creator": "bla bla",
        "cost": 200
    }, {
        "name": "bla bla",
        "creator": "bla bla",
        "cost": 200
    },
    {
        "name": "bla bla",
        "creator": "bla bla",
        "cost": 200
     }
  ]

I have tried single foreach loops (like below), this code is currently working but only accepts (save) only the first index. I have almost 10K of data. I need it to return results for each array values.

public function fileImport(Request $request) 
{   
    set_time_limit(6000);
    $array = (new DrugsImport)->toArray($request->file('file'));
    $i = 0;
    foreach ($array as $item) {
        $drugs = new Drug;
        $drugs->user_id = 1;
        $drugs->name = $item[$i]['name'];
        $drugs->cost = $item[$i]['cost'];
        $drugs->save();
        //$name = utf8_decode($item[$i]['naimenovaniya']);
        // $name = $item[$i]['naimenovaniya'];
        // iconv("Windows-1251", "UTF-8", $name);
        $i++;
    }
    return response()->json($drugs);

   //Excel::import(new DrugsImport, $request->file('file')->store('temp'));
   //return back();
}

Currently, this code stores only the first [0] element. The remaining values are not saved. I’ve also tried using a few other ways but in all of the first element stored. I tried also like this:

    foreach ($array as $key => $value) {
    if (is_array($value)) {
        ......
    }
}

I can't find where I'm wrong. Can anyone help? Thank you!

EDITED If i run using var_dump($array):

    array(1) {
        [0] => array(2897) {
                [0] => array(3) {
                    ["name"] => string(36)
                    "bla bla bla" ["cost"] => int(200)
                } [1] => array(3) {
                     ["name"] => string(36)
                    "bla bla bla" ["cost"] => int(200)
                } [2] => array(3) {
                     ["name"] => string(36)
                    "bla bla bla" ["cost"] => int(200)
                } [3] => array(3) {
                     ["name"] => string(36)
                    "bla bla bla" ["cost"] => int(200)
                }
        ....

UPDATED My DrugsImport file:

    class DrugsImport implements ToModel, WithHeadingRow
{
    use Importable;

    /**
    * @param array $row
    *
    * @return \Illuminate\Database\Eloquent\Model|null
    */
    public function model(array $row)
    {
        return new Drug([
            'name '     => $row[0],
            'cost'    => $row[1]
        ]);
    }

}

if I dump $array it returns like that:

array:1 [▼
0 => array:2897 [▼
0 => array:3 [ …3]
1 => array:3 [ …3]
2 => array:3 [ …3]
3 => array:3 [ …3]
4 => array:3 [ …3]
....

Sorry if it's a duplicate question, but none of them worked ...

STA
  • 30,729
  • 8
  • 45
  • 59
  • If `$array` is what you posted first, then `$item[$i]['name']` should throw a warning about undefined index. `$item` will be the sub array so it should only be `$item['name']`. No need for the `$i` at all. – M. Eriksson Sep 10 '20 at 14:45
  • You also have a typo: `['cose']` should be `['cost']` – M. Eriksson Sep 10 '20 at 14:47
  • No if I use `$index['name']` it returne an error `Undefined index: name`. –  Sep 10 '20 at 14:50
  • what do you see if you dump the array before the loop? ```dump($array)``` – MHewison Sep 10 '20 at 14:50
  • Then the array doesn't look like the one you've posted. Here's a demo: https://3v4l.org/LlTXC – M. Eriksson Sep 10 '20 at 14:51
  • If I use without loop, all the array elements are fully visible. If i use loop it return only first [0] element. –  Sep 10 '20 at 14:52
  • We can't help if we don't have the correct info. Before the foreach, do a `print_r($array);` and add the output to your question. – M. Eriksson Sep 10 '20 at 14:54
  • @MagnusEriksson I edited the question, I added dump result. –  Sep 10 '20 at 15:02
  • That doesn't look like the one you've posted. This shows that you have one array that contains one array that contains multiple arrays (3 levels). Try: `foreach ($array[0] as $item)` and still only use `$item['name']` inside the foreach. – M. Eriksson Sep 10 '20 at 15:05
  • Show me the DrugImport file – Encang Cutbray Sep 10 '20 at 15:06
  • @MagnusEriksson thanks, but if I use `foreach ($array[0] as $item)`, it returned only last element of array. –  Sep 10 '20 at 15:08
  • The "new" output looks like it's from the console (outputted through JS)? Can you please do a `var_dump($array)` or `var_dump($array)` to show us how it looks right before the foreach? The arrays you've shown doesn't match the issues you get. – M. Eriksson Sep 10 '20 at 15:20
  • @MagnusEriksson I edited the question with `var_dump()` result. –  Sep 10 '20 at 15:29

2 Answers2

2

you can try like this. let we know if you get an error

// controller fileImport     
public function fileImport(Request $request) 
{   
   $drug = new DrugsImport;
   Excel::import($drug, $request->file('file'));
   return $drug->drugResult;
} 

// Drug Import 
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\ToCollection;
class DrugsImport implements ToCollection, WithHeadingRow
{
      public $drugResult;
      public function collection(Collection $rows)
      {
          $this->drugResult = $rows;
      }
} 
Encang Cutbray
  • 382
  • 1
  • 2
  • 9
  • Thanks, this way works, but I need a different way. I need to do the necessary actions on the values inside the array (Split, trim, etc.). This must be done import in the controller. –  Sep 10 '20 at 15:42
  • what do you mean necessary actions ? i can't understand – Encang Cutbray Sep 10 '20 at 15:45
  • Sorry, my English is not very good, I have to delete some values in the array, I need to edit the values, so it was necessary in the controller. –  Sep 10 '20 at 16:04
2

So, there are a few issues with your code.

The format

Your array is an array that contains one array that contains multiple arrays, so if you only do:

foreach ($array as $item)

it will only iterate it once (since $array only contains one array), which is why you only got the first.

If you do

foreach ($array[0] as $item)

and use $item['name'], it will iterate through all items.

Why does it only return the last?

That's because you're overwriting the $drugs variable on each iteration.

If you want to return them all, add them to an array instead. This should do it:

// Define the array where we will add the drugs so we can return them all
$listOfDrugs = [];

foreach ($array[0] as $item) {
    $drug = new Drug;
    $drug->user_id = 1;
    $drug->name = $item['name'];
    $drug->cost = $item['cost'];
    $drug->save();       

    // Add the new drug to the array so it can be returned after the loop
    $listOfDrugs[] = $drug;
}

// Now return the array with all the drugs
return response()->json($listOfDrugs);
M. Eriksson
  • 13,450
  • 4
  • 29
  • 40