Importer issue Invalid argument supplied for foreach() - php

I've a CSV files importer so the user can update the categories of the articles for the store they work for.
While the file is being processed, Laravel throws me this error:
Invalid argument supplied for foreach()
This is my Controller code:
public function procesar(ImportarCategoriasArticulos $importador){
list( $ruta,$nombre_excel ) = explode('/', $importador->excel_ruta);
ini_set('memory_limit', -1);
ini_set('max_execution_time', -1);
//dd($importador);
try{
CategoriaArticulos::query()->truncate();
Excel::import(new CategoriasArticulosImportador, public_path().'/storage/uploads/'.$nombre_excel);
$articulos_no_encontrados = CategoriaArticulos::select(['codigo_interno'])->distinct()->whereNull('articulo_id')->get();
if( $articulos_no_encontrados->count() > 0 ){
$importador->articulos_no_encontrados = $articulos_no_encontrados->toJson();
$importador->estatus = 'procesado con error';
$importador->save();
\Alert::error(trans('ERROR: Existen articulos no encontrados.'))->flash();
return redirect('admin/configuracion/importar_categoria_articulos/'.$importador->id);
} else {
Articulo::all()->map( function( $articulo ){
$nuevos_datos = CategoriaArticulos::where('articulo_id', $articulo->id)->first();
$articulo->categoria = $nuevos_datos->categoria;
$articulo->subcategoria = $nuevos_datos->subcategoria;
$articulo->subsubcategoria = $nuevos_datos->subsubcategoria;
$articulo->save();
});
\Artisan::command('key-a:sm:generar-categorias');
$importador->estatus = 'procesado con exito';
$importador->save();
\Alert::success(trans('EXITO: se modificaron las categorias.'))->flash();
return redirect('admin/configuracion/importar_categoria_articulos/');
}
} catch (\Exception $e){
\Alert::error(trans($e->getMessage()))->flash();
return redirect('admin/configuracion/importar_categoria_articulos/');
}
}
Could you please help me find what is wrong? I've done importers before but this time seems impossible to me.
Thanks in advance.

Related

ArgumentCountError: Too few arguments to function IPS\Theme\class_game_front_admincp::dashboard()

I have forum Invision Power Suite and error in app.
ArgumentCountError: Too few arguments to function IPS\Theme\class_game_front_admincp::dashboard(), 9 passed in /home/ltrpplp/www/system/Theme/SandboxedTemplate.php on line 61 and exactly 10 expected in /home/ltrpplp/www/system/Theme/Theme.php(860) : eval()'d code:1440
Main.php:
protected function _dashboard()
{
$Count_Characters = \IPS\game\AdminCP::Dashboard_Count_Characters();
$Count_Groups = \IPS\game\AdminCP::Dashboard_Count_Groups();
$Count_Items = \IPS\game\AdminCP::Dashboard_Count_Items();
$Count_Cars = \IPS\game\AdminCP::Dashboard_Count_Vehicles();
$Count_Doors = \IPS\game\AdminCP::Dashboard_Count_Doors();
$Count_Areas = \IPS\game\AdminCP::Dashboard_Count_Areas();
$Count_Objects = \IPS\game\AdminCP::Dashboard_Count_Objects();
$Count_Pickups = \IPS\game\AdminCP::Dashboard_Count_Pickups();
$Count_Money = \IPS\game\AdminCP::Dashboard_Count_Money();
$Count_MoneyBank = \IPS\game\AdminCP::Dashboard_Count_MoneyBank();
return \IPS\Theme::i()->getTemplate('admincp')->dashboard( $Count_Characters, $Count_Groups, $Count_Items, $Count_Cars, $Count_Doors, $Count_Areas, $Count_Objects, $Count_Pickups, $Count_Money, $Count_MoneyBank );
}
public function Dashboard_Count_MoneyBank()
{
try
{
$result = \IPS\Db::i()->select( 'count(`char_bankcash`)', 'ipb_characters')->first();
}
catch( \UnderflowException $e )
{
\IPS\Output::i()->error( 'no_module_permission', '2C122/1', 403, '' );
}
return $result;
}
And have:
Bank in Cash: 6$
Although I have over $ 10,000 in mysql..
How to fix this? Help me please! :(

PHP 7.4.18 update: Mysqlnd -- Calling stmt_store_result after fetch now throws an error

We have a bunch of websites using a shared MySQLi class.
PHP 7.4 was working with these and no errors were seen to be generated.
Now, PHP Bug #80837 has been fixed with release of PHP 7.4.18
The problem is that this fix means all our websites are throwing this fatal error and I can't see how to fix the error itself.
The Exception:
[06-May-2021 08:04:19 UTC] PHP Fatal error: Uncaught mysqli_sql_exception: Commands out of sync; you can't run this command
now in /usr/local/lib/php/databaseClass.php:169 Stack trace:
#0 /usr/local/lib/php/databaseClass.php(169): mysqli_stmt->store_result()
#1 /usr/local/lib/php/databaseClass.php(897): Database->fetchResult(Object(mysqli_stmt), true)
#2 /home/account/public_html/.../file.php(45): DatabaseObject->getSelect('SELECT (bad_log...', Array, true)
#3 /home/katemawdsley/public_html/start.php(10): include('/home/account...')
#4 {main} thrown in databaseClass.php on line 169
The Database Class 'fetchResult' method:
/***
* For use with MySQLi->dbiLink Object.
* Returns the result as an array of KEY=>VALUE pairs from the Database.
* #param $result mysqli_result object.
* #return array|mixed
***/
private function fetchResult($result)
{
if ($result instanceof \mysqli_stmt) {
$result->store_result(); // This is line 169
$variables = [];
$data = [];
$meta = $result->result_metadata();
//error_log(print_r(debug_backtrace(),true));
while ($field = $meta->fetch_field()) {
$variables[] = &$data[$field->name]; // pass by reference
}
\call_user_func_array([$result, 'bind_result'], $variables);
$i = 0;
while ($result->fetch()) {
$resultsArray[$i] = [];
foreach ($data as $k => $v) {
$resultsArray[$i][$k] = $v;
if ($this->numericIndexes) {
$resultsArray[$i][] = $v;
}
}
unset($k, $v);
$i++;
}
} elseif ($result instanceof \mysqli_result) {
$rowNumber = 0;
while ($row = $result->fetch_assoc()) {
$resultsArray[$rowNumber] = $row;
if ($this->numericIndexes) {
foreach ($row as $numerical) {
$resultsArray[$rowNumber][] = $numerical;
}
unset($numerical);
}
$rowNumber++;
}
$i = 0;
unset($row, $rowNumber);
}
return $resultsArray;
}
The Database Class 'fetchResult' method called from a 'select' method:
/***
* Function for retrieving SQL query data from the Database
* #param $sql string the SQL select query
* #param null $data string|array the data to check in the query with
* #return array|bool|mixed
***/
public function select($sql, $data = null){
/***
* Now prepare the SQL
***/
try {
$query = $this->databaseObject->prepare($sql);
/****
* $query is prepared here....
***/
...
$query->execute();
}
catch (\mysqli_sql_exception $ex) {
$this->exceptionalError($ex);
return false;
}
catch (\Exception $ex) {
$this->exceptionalError($ex);
return false;
}
if (\mb_strtoupper($reduce, "UTF-8") !== "NORETURN") {
if ($query->field_count > 0 ) {
$query->store_result();
}
$this->rowsFound[] = $query->num_rows;
$output = $this->fetchResult($query); // Call to fetch result method
if ($query->field_count > 0) {
$query->free_result();
}
$query->close();
unset($query);
return $output;
}
/***
* NORETURN value so no result to return.
***/
$successValue = $this->rowsAffected[] = $query->affected_rows;
$query->close();
unset($query);
return $successValue;
}
What is the correct work around for how to construct this fetchResult method in light of the update?
(As you can tell we were completely unaware of this previous issue and it didn't appear on any error logs so was a surprise)
You are calling store_result() twice. You can't do that. Once the results have been buffered in PHP, the connection line is free - there are no more results pending to be fetched. Calling store_result() the second time will throw "Out of sync" error.
You call it first here:
if (\mb_strtoupper($reduce, "UTF-8") !== "NORETURN") {
if ($query->field_count > 0 ) {
$query->store_result();
}
and then here
private function fetchResult($result)
{
if ($result instanceof \mysqli_stmt) {
$result->store_result(); // This is line 169
Remove one usage and you should be fine.
I would recommend working with mysqli_result instead. When you call get_result it will buffer the results and give you a familiar object that you can work with. This could simplify your abstraction class significantly.
Here is how I would refactor this class:
public function select($sql, $data = null)
{
/***
* Now prepare the SQL
***/
try {
$query = $this->databaseObject->prepare($sql);
/****
* $query is prepared here....
***/
$query->execute();
} catch (\mysqli_sql_exception $ex) {
$this->exceptionalError($ex);
return false;
} catch (\Exception $ex) {
$this->exceptionalError($ex);
return false;
}
$result = $query->get_result();
if (\mb_strtoupper($reduce, "UTF-8") !== "NORETURN") {
$this->rowsFound[] = $result->num_rows;
if ($result) {
return $this->fetchResult($result); // Call to fetch result method
}
}
/***
* NORETURN value so no result to return.
***/
$successValue = $this->rowsAffected[] = $query->affected_rows;
return $successValue;
}
private function fetchResult(mysqli_result $result)
{
return $result->fetch_all($this->numericIndexes ? MYSQLI_BOTH : MYSQLI_ASSOC);
}

How to optimize api call PHP

I'm working (for fun), with an API (Riot API), and I made something to retrieve match histories (it's in the game). And I've a problem, everything works really fine, but I don't know how to optimize it, what I mean is : I do the call every time the user refresh the page, and it takes loooong looong time. I tried to call it with AJAX, but didn't find a good way, AJAX dont find my objects.
Here is the code :
$match_history = [];
$api = "";
if (!empty($region)) {
try {
$api = new App\Library\RiotAPI\RiotAPI([
App\Library\RiotAPI\RiotAPI::SET_KEY =>
App\Config::API_KEY,
App\Library\RiotAPI\RiotAPI::SET_CACHE_RATELIMIT => true,
App\Library\RiotAPI\RiotAPI::SET_CACHE_CALLS => true,
App\Library\RiotAPI\RiotAPI::SET_REGION =>
App\Library\RiotAPI\Definitions\Region::getRegion($region),
]);
} catch (\Exception $e) {
// die($e->getMessage());
}
}
if ($api) {
// Insert current rank etc...
try {
$summoner = $api-
>getSummonerByName(App\Repository\UserRepository::getInstance()-
>getUserDetail($_SESSION['user']['id'], 'summoner_name'));
} catch (\Exception $e) {
$summoner = null;
}
// Match history
if (!empty($summoner)) {
try {
$matches = $api->getRecentMatchlistByAccount($summoner->accountId);
// For every matches
foreach ($matches as $match) {
$a_match = $api->getMatch($match->gameId);
if ($a_match->gameType === "MATCHED_GAME") {
$gameCreation = date("d-M-Y H:i:s", substr($a_match-
>gameCreation, 0, 10));
if ($gameCreation >= date("d-M-Y",
strtotime($user['created_at']))) {
// Get the participant ID of the customer
foreach ($a_match->participantIdentities as
$participantIdentity) {
if ($participantIdentity->player->currentAccountId
=== $summoner->accountId) {
$participantId = $participantIdentity-
>participantId;
}
}
// Get stats of the participant
foreach ($a_match->participants as $participant) {
if ($participant->participantId === $participantId)
{
$match_history[$match->gameId]['gameCreation'] =
$gameCreation;
$match_history[$match->gameId]['championId'] =
$participant->championId;
$match_history[$match->gameId]['spells']
['spell1'] = $participant->spell1Id;
$match_history[$match->gameId]['spells']
['spell2'] = $participant->spell2Id;
$match_history[$match->gameId]['win'] =
$participant->stats->win;
$match_history[$match->gameId]['kills'] =
$participant->stats->kills;
$match_history[$match->gameId]['deaths'] =
$participant->stats->deaths;
$match_history[$match->gameId]['assists'] =
$participant->stats->assists;
$match_history[$match->gameId]['goldEarned'] =
$participant->stats->goldEarned;
$match_history[$match->gameId]
['totalMinionsKilled'] = $participant->stats->totalMinionsKilled;
$match_history[$match->gameId]['items']['item0']
= $participant->stats->item0;
$match_history[$match->gameId]['items']['item1']
= $participant->stats->item1;
$match_history[$match->gameId]['items']['item2']
= $participant->stats->item2;
$match_history[$match->gameId]['items']['item3']
= $participant->stats->item3;
$match_history[$match->gameId]['items']['item4']
= $participant->stats->item4;
$match_history[$match->gameId]['items']['item5']
= $participant->stats->item5;
$match_history[$match->gameId]['items']['item6']
= $participant->stats->item6;
}
}
}
}
}
} catch (\Exception $e) {
// die($e->getMessage());
}
}
}
I would like to know if there's a way to : - Run it in background, without AJAX or something like : Keep in mind the match_history for X time, and then after X time, do the call again when the user refresh the page.
Thanks for your help!
Best Regards.

Pagination Laravel 4 does not update active page number

I am new to laravel4, I am working basically with SOAP webservices in laravel 4 using Nusoap library.
My problem is with pagination, at controller my code is ast follow
function AjaxProductList()
{
$isAjax = Request::ajax();
if($isAjax)
{
//instantiate the NuSOAP class and define the web service URL:
$client = new nusoap_client('http://stage.ws.greenbook.net/gbwswcf/servicegb.svc?wsdl', 'WSDL');
//check if there were any instantiation errors, and if so stop execution with an error message:
$error = $client->getError();
if ($error) {
die("client construction error: {$error}\n");
}
if(Input::get('term'))
{
Session::put('term', Input::get('term'));
$term = Input::get('term');
}
else
$term = Session::get('term');
if(Input::get('pg_number')!='')
{
Session::put('page_num', Input::get('pg_number'));
$page_num = Input::get('pg_number');
}
else
$page_num = Session::get('page_num');
if(Input::get('per_pg_result') !='')
{
Session::put('result_per_page', Input::get('per_pg_result'));
$result_per_page = Input::get('per_pg_result');
}
else
$result_per_page = Session::get('result_per_page');
$param = 'SearchParam=|category#'.Session::get('type').'|searchterm#'.$term;
//$value = Session::get('key');
$params = array( 'ClientID' => Config::get('globals.ClientID'),
'strPwd' => Config::get('globals.password'),
'Params' => $param ,
'PageNum' =>$page_num,
'NumOfResultsPerPage' =>$result_per_page
);
$client->soap_defencoding = 'UTF-8';
$answer = $client->call('GetResultsV2',$params);
//check if there were any call errors, and if so stop execution with some error messages:
$error = $client->getError();
if ($error) {
echo 'some error occured , please try again later';
die();
}
$ResultNumbers = Common::find_key_array('ResultNumbers',$answer);
$data['SearchParams'] = Common::find_key_array('SearchParams',$answer);
$data['products'] = Common::find_key_array('Product',$answer);
$data['total_result'] = $ResultNumbers['TotalNum'];
$data['paginator'] = **Paginator::make($data['products'],$data['total_result'],$result_per_page)**;
$return["prd_listing_bot"] = View::make('frontend.search.ajax_product_listing',$data)->render();
echo json_encode($return);
exit;
}
else
{
echo 'not allowed';
}
}
here i am using Paginatior class and providing the parameters (returned records,total items,perpage items).
here is my view code:
$paginator->setBaseUrl('search');
echo $paginator->links();
NOW its creating links successfully
My URL structure after clicking 5 is
'http://mydomain/search?page=5'.
and in 'routes.php' i have
Route::any('search', array('uses' => 'SearchController#QuickSearch'));
when the page view is loaded an ajax call is initiated for function AjaxProductList();
when i click on any link in pagination, it fatches data successfully, but not updating the active link. i.e if i click on page number 5 it will fetch the correct data but active link will be still at page "1".
tell me please if i am doing anything wrong?
thanks in advance.
Just solved it by placing
Paginator::setCurrentPage($page_num);
above the line
Paginator::make($data['products'],$data['total_result'],$result_per_page);
Anyway thanks to everyone who participated here.
In the Paginator::make() methos the first parameter is an array of items that are already paginated. Check this example:
$perPage = 15;
$currentPage = Input::get('page', 1) - 1;
$pagedData = array_slice($items, $currentPage * $perPage, $perPage);
$matches = Paginator::make($pagedData, count($items), $perPage);
In this example I use the array_slice methos to get the items of the current page. To get the page in your controller you can use Input::get('page', 1) so if there is no page selected to default would be 1

SimpleXML inserting new line

Have this sample.xml:
<FacturacionAR>
<Factura xsi:type="FacturaAR">
<TipoNota>Boleta de Ventas y Servicios</TipoNota>
<Agencia>LUIL</Agencia>
<NroFactura>5040</NroFactura>
<Cliente>JOHAO SMITH CART</Cliente>
<Ciudad>NUNORK</Ciudad>
<Direccion>CALLE VITAL DE MELLO</Direccion>
<Barrio>JAJJKIU</Barrio>
<Estado>Cancelada</Estado>
</Factura>
</FacturacionAR>
I want to add "Telefono" every time this node is missing, just after "Barrio", so I tried to do in php:
$filename = "sample.xml";
$FacturacionAR = simplexml_load_file($filename,null,true);
function simplexml_insert_after(SimpleXMLElement $sxe, SimpleXMLElement $insert, SimpleXMLElement $target)
{
$target_dom = dom_import_simplexml($target);
$target_dom->formatOutput = true;
$target_dom->preserveWhiteSpace = false;
$insert_dom = $target_dom->ownerDocument->importNode(dom_import_simplexml($insert), true);
if ($target_dom->nextSibling) {
$result = $target_dom->parentNode->insertBefore($insert_dom, $target_dom->nextSibling);
$target_dom->parentNode->insertBefore($target_dom->ownerDocument->createTextNode("\n"), $result);
return $result;
} else {
return $target_dom->parentNode->appendChild($insert_dom);
}
}
foreach ($FacturacionAR->Factura as $Factura) {
if (!isset($Factura->Telefono)) {
$meta2 = new SimpleXMLElement("<Telefono/>");
$target = current($FacturacionAR->xpath('//Barrio[last()]'));
simplexml_insert_after($FacturacionLocalizaAR, $meta2, $target);
}
}
The expected result is:
<Barrio>JAJJKIU</Barrio>
<Telefono></Telefono>
But when I run the php script, this error appears:
PHP Catchable fatal error: Argument 3 passed to simplexml_insert_after() must be an instance of SimpleXMLElement, boolean given
Any ideas?
OK. Upgrading to PHP 5.5.3 solved my problem.

Categories