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
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.