phplaravellaravel-bladelaravel-livewiredomcrawler

Undefined array key "name" error after submitting a form for 2nd time


i've been recently working on a project using Laravel with livewire with the objective of testing the domCrawler componente. my app gets data about products from a store webpage and retrieves the products information. Im working with an array that is loaded with objects of type product.

Here is the model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    public $name;
    public $price;
    public $storeId;
    public $img;
    public $discount;
    public $discountText;

    public function __construct(array $attributes = []){
        $this->name = $attributes["name"];
        $this->price = $attributes["price"];
        $this->storeId = $attributes["storeId"];
        $this->img = $attributes["img"];
        $this->discount = $attributes["discount"];
        $this->discountText = $attributes["discountText"];
    }


}

the page uses a form with a textinput and a button, the user types a product name and when the search button is pressed it activates the search function of my controller.

heres the blade.php file for the view:

<div >
    <form wire:submit="search">
        <p class="text-green-200 text-2xl">hola</p>
        <label class="text-white">Que producto quiere buscar?</label>
        <input class="" type="text" name="product" wire:model="product">
        <button class="text-green-200 hover:text-red-400" type="submit">Buscar</button>
    </form>
    <button class="text-green-200 hover:text-red-400" wire:click="back">Volver</button>

    @if($searched)
        @foreach($productsAnswer as $product)
            <p class="text-green-200 text-2xl">{{$product -> name}}<p>
        @endforeach
    @endif
</div>

After the submit button is pressed the search function loads the array called $productsAnswer with the product type objects:

<?php

namespace App\Livewire;

use Livewire\Component;
use Livewire\Attributes\Layout;
use Symfony\Component\BrowserKit\HttpBrowser;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\HttpClient\HttpClient;
use App\Models\Product;
use Exception;

use function Livewire\Volt\mount;

#[Layout("layouts.app")]
class Inicio extends Component
{
    public $productsAnswer = array();
    public $product = "";
    public $searched = false;



    public function render()
    {
        return view('livewire.inicio');
    }

    public function search(){
        $this->searched = false;
        $prods = [];
        $coto = [];
        $browser = new HttpBrowser(HttpClient::create()); 
        


        //Coto

        $crawler = $browser->request('GET', 'https://www.cotodigital3.com.ar/sitios/cdigi/browse?_dyncharset=utf-8&Dy=1&Ntt='.$this->product.'&Nty=1&Ntk=&siteScope=ok&_D%3AsiteScope=+&atg_store_searchInput='.$this->product.'&idSucursal=200&_D%3AidSucursal=+&search=Ir&_D%3Asearch=+&_DARGS=%2Fsitios%2Fcartridges%2FSearchBox%2FSearchBox.jsp');
        
        foreach($crawler->filter("[class='clearfix']") as $prod){ array_push($prods, $prod); }
        foreach($crawler->filter("[class='clearfix first']") as $prod){ array_push($prods, $prod); }
        foreach($crawler->filter("[class='clearfix first_max']") as $prod){ array_push($prods, $prod); }


        foreach($prods as $prod){
            $crawlerProd = new Crawler($prod);
            $name = $crawlerProd->filter("[class='descrip_full']")->text();
            $price = $crawlerProd->filter("[class='atg_store_newPrice']")->text();
            $img = $crawlerProd->filter("[class='atg_store_productImage'] > img")->attr('src');
            $discountText = $crawlerProd->filter("[class='info_discount']") -> children() -> text();
            if($discountText == $price){
                $discount = 'No';
                $discountText = 'None';
            }
            else{
                $discount = 'Yes';
                $discountText = strstr($discountText, 'OFERTA');
            }
            
            $newProd = new Product([
                "name"=> $name,
                "price"=> $price,
                "storeId" => 'coto',
                "img" => $img,
                "discount" => $discount,
                "discountText" => $discountText
            ]);
            array_push($coto, $newProd);
        }

        $this -> productsAnswer = $coto;
        $this -> searched = true;
    }
}

The problem is the app works perfectly fine the first time you search for something:

it shows the products name good

But if you try to search something else this happens:

some type of constructor error

i suppose it has something to do with the way i use the array. Maybe it doesnt like being overwritten(?

im out of ideas. I appreciate any help.

I tried to search for a product after a previous successful search.

I expected to see the new array of names show up.

It resulted in a Undefined array key "name" error


Solution

  • Comments posted by Pippo https://stackoverflow.com/users/21380206/pippo And Tim Lewis https://stackoverflow.com/users/3965631/tim-lewis answered my question.

    Resume Deleted the model named product and instead used a simple array:

    $newProd = ([
                "name"=> $name,
                "price"=> $price,
                "storeId" => 'coto',
                "img" => $img,
                "discount" => $discount,
                "discountText" => $discountText
            ]);
    

    and then used a wire:key in the foreach:

    @if($searched)
        @foreach($productsAnswer as $product)
            <div x-init="console.log(item)"><div>
            <p class="text-green-200 text-2xl" wire:key="{{$product['name']}}">{{$product['name']}}<p>
        @endforeach
    @endif
    

    Problem solved.