While loop returning duplicate result in php - php

I am working with a JSON file that is nested and I am employing a JSON pull parser for PHP 7 due to the size of the file. I want to extract data and put them in a csv table as thus:
`FOO ID` `NAME` `UHC` `UHCCOMPANY`
`foo_1403039` `bana` `nege`
`foo_1403039` `baan`
`foo_13589` `anab` `neeg` `nege`
`foo_13590` `naab`
`foo_1403220` `suresh ltd`
`foo_1403223` `suresh ltd`
But then if you notice in the table above, the 1st and 2nd data (foo_1403039) under the first column titled FOO ID are duplicated, and I do not want that. Indeed, if I delete the 1st data under the first column, and shift the cell of that column up by one step, the table looks perfect. Similarly, the last two data (suresh ltd) under the under the second column titled NAME are also duplicate.
I do not know what is wrong in my code. Any help will be appreciated. Here is my dummy json file, and this is my php code:
<?php
require_once 'C:/xampp/htdocs/vendor/autoload.php';
use \pcrov\JsonReader\JsonReader;
ini_set("max_execution_time", 0);
$reader = new JsonReader();
$reader->open("myjsonfile.json");
$fo = fopen("mycsv.csv", "w" );
fputs($fo, "companyID1, name, ultimateHoldingCompany, uhcCountry".PHP_EOL);
while($reader->read()) {
if (preg_match('/^foo_/', $reader->name())){
$companyID = $reader->name();
$companyID1 = str_ireplace("foo_","",$companyID);
if ($reader->read("entityName")){
$entityName = $reader->value();
$entityName = str_ireplace(","," ",$entityName);
}
if ($reader->read("ultimateHoldingCompany")){
$uhcName = null;
$uhcCountry = null;
$ultimateHoldingCompany = $reader->value();
if (empty($ultimateHoldingCompany)){
}
else {
$uhcCountry = $ultimateHoldingCompany[0]['country'];
$uhcName = $ultimateHoldingCompany[0]['name'];
$uhcName = str_ireplace(","," ",$uhcName);
}
}
fputs($fo, $companyID1.",".$entityName.",".$uhcName.",".$uhcCountry.PHP_EOL);
}
}
$reader->close();

Related

PHP variable assignment in foreach loop - unknown behavior

This has me completely stumped. I am using a Cakephp 3.9.6 application and tplaner/When library on PHP 7.4 to generate recurring events. Somewhere, the start and end dates are being set as the same date. Here is the section from my EventsController::add method:
$data = $this->request->getData();
$copies = new When();
$copies->freq($data['frequency'])
->interval($data['interval'])
->wkst('MO');
if ($data['frequency'] == 'WEEKLY') {
$copies->byday(implode(',', $data['days']));
}
if (!empty($data['count'])) {
$copies->count($data['count']);
} else {
$copies->until(new DateTime($data['last_date'] . " 23:59:59"));
}
$copies->startDate(new DateTime($event->start->toDateTimeString()))->generateOccurrences();
$newCopies = $copies->occurrences;
$interval = $event->start->diff($event->end);
foreach ($newCopies as $copy) {
Log::debug($copy); //Shows the next date in the series calculated from start date
if ($copy == $event->start) {
continue; //First event already saved in rest of action, do not create another copy
}
$temp = $event->toArray(); //copy entity details to array
$temp['start'] = $copy; //assign new start time
$start = $copy; //thought maybe due to race condition? Copying to new object to modify end time
$temp['end'] = $start->add($interval); //$interval calculated from original event data, added to new start time
Log::debug($temp);
$result = $this->Events->newEntity($temp); //return to new entity
Log::debug($result);
$events[] = $result; //add to array of entities for saveMany()
}
The problem I have is that the new start date in the array/entity are the same as the end date:
Log::debug($copy) outputs the correct new start date
Log::debug($temp) shows the array, but the start and end properties are the same...
you can not do $start=$copy as they will be the same "object" with different references, you actually want to CLONE $copy so it is a separate object. So when you alter one you do not touch the other

PHP Scraper Loops Until Time Limit Exceeded (Using Simple HTML Dom Parser)

I am attempting to scrape the price of the same product from two different websites. While it pulls the correct results and prints out what I want, when the I run the script I get this error after the results are correctly printed:
Fatal error: Maximum execution time of 120 seconds exceeded in [...] on line 144
And this is my code:
<?php
//Adds in the simple HTML DOM parser
include ('simple_html_dom.php');
//Defines the Target URL to Scrape
$cbdUrl = "https://cbdstore.co.za/product/africanpure-everyday-cbd-1000mg-30ml/";
$apUrl = "https://africanpure.co/product/everyday-cbd-oil-1000mg-30ml/";
//Defines 'html' as the scraped content from the URL above
$cbdHtml = file_get_html($cbdUrl);
$apHtml = file_get_html($apUrl);
//Creating an array to store all the 'price' classes text from the page
$cbdPrices = array();
//Fetching all the '.amount' and storying them in the array as plain text.
foreach($cbdHtml->find('div.summary.entry-summary p.price') as $cbdElement)
{
foreach($cbdElement->find('.amount') as $cbdAmt)
{
$cbdPrices [] = $cbdAmt->plaintext;
}
}
//Repeating for AfricanPure
$apPrices = array();
foreach($apHtml->find('div.summary-inner div.basel-scroll-content p.price') as $apElement)
{
foreach($apElement->find('.amount') as $apAmt)
{
$apPrices [] = $apAmt->plaintext;
}
}
// Writes out CBD Store Price
echo 'CBD Store has the Everday CBD Oil for: ' . $cbdPrices[0];
// Writes out AP Price
echo 'African Pure has the Everday CBD Oil for: ' . $apPrices[0];
?>
It looks like you are only interested in one price for each ($cbdPrices[0]) and not an array of prices, so try breaking out of the loops after getting the first price.
foreach($cbdHtml->find('div.summary.entry-summary p.price') as $cbdElement)
{
foreach($cbdElement->find('.amount') as $cbdAmt)
{
$cbdPrices [] = $cbdAmt->plaintext;
break;
}
}
And do the same on the other one. You could also probably not make the variable an array in the first place?

How to count JSON response and output how many lines there are

Hello fellow developers,
I have been trying to manipulate the output and display the total amount of workers there are instead of outputting the workers name as a string.
Bellow you will find the data that i am receiving and further down i will explain how i would like to handle the JSON response.
{
"result":
{
"addr":"ADDRESS_HERE",
"workers":
[
["worker1080",{},2,1,"200000",0,22],
["worker1080",{"a":"899.4"},3,1,"512",0,24]
],
"algo":-1
},
"method":"stats.provider.workers"
}
So basically as you can see from the above response that there are 2 workers named "worker1080" active on that address.
The bellow php code is how i retrieve the data and output only the names of the workers:
<?php
$btcwallet = get_btc_addy();
if (isset($cur_addy)) {
$method4 = new methods();
$worker_stats = new urls();
$get_data = file_get_contents(utf8_encode($worker_stats->nice_url.$method4->m4.$cur_addy));
$get_json = json_decode($get_data, true);
foreach ($get_json['result']['workers'] as $v) {
$i = 0;
print $v[$i++]."<br />";
}
}
?>
$get_json is the variable that decodes the data from $get_data and displays the worker names and increments every time a worker is added or online.
now i currently have 2 workers online as shown in the JSON response.
it outputs:
worker1080
worker1080
which is perfect although if i try using a foreach statement and try to display the the total amount of workers online it should display 2 instead of the names, it has to also increment for each worker that the json repsonse outputs.
EG: i have 2 workers online now, but in an hour i will connect 10 more it would display the following:
worker1080
worker1080
worker1070
worker1070
worker1080ti
worker1080ti
workerASIC
workerASIC
workerASIC
workerCPU
workerCPU
workerCPU
Now i try to use the following to display the total:
count($v[$i++]);
and i have tried using a foreach within the foreach, and both count and the foreach both will either display "0" by all the workers or "1"
bellow is an example of the output.
0
0
0
0
0
How would i go about counting each line in the output and display the total number of workers ?
Thanks #symcbean for the solution.
<?php
$btcwallet = get_btc_addy();
if (isset($cur_addy)) {
$method4 = new methods();
$worker_stats = new urls();
$get_data = file_get_contents(utf8_encode($worker_stats->nice_url.$method4->m4.$cur_addy));
$get_json = json_decode($get_data, true);
print count($get_json['result']['workers'])."<br />"; // <-- solution *removed foreach and $i incrementation as its not needed for count
}
?>
it now displays the correct number of workers :)

Extracting a precise value from a Json array with PHP (like a MySQL db)

another (probably) easy question for you.
As I wrote many times, I'm not a programmer but thanks to you I was able to build an interesting site for my uses.
So again thx.
This is my new problem:
I have a site that recover json data from a file and store it locally once a day (this is the code - I post it so it can be useful to anyone):
// START
findList();
function findList() {
$serverName = strtolower($_POST["Server"]); // GET SERVER FROM FORM POST
$localCoutryList = ("json/$serverName/countries.json"); // LOCAL LOCATIONS OF FILE
$urlCountryList = strtolower("url.from.where.I.get.Json.file.$serverName/countries.json"); // ONLINE LOCATION OF FILE
if (file_exists($localCoutryList)) { // FILE EXIST
$fileLastMod = date("Y/m/d",filemtime($localCoutryList)); // IF FILE LAST MOD = FILE DATE TIME
$now = date('Y/m/d', time()); // NOW
if ($now != $fileLastMod) { // IF NOW != FILE LAST MOD (date)
createList($serverName,$localCoutryList,$urlCountryList); // GO AND CREATE FILE
} else { // IF NOW = FILE LAST MOD (date)
jsonList($serverName,$localCoutryList,$urlCountryList); // CALL JSON DATA FROM FILE
}} else { // FILE DOESN'T EXIST
createList($serverName,$localCoutryList,$urlCountryList); // CALL CREATE FILE
}};
function createList($serverName,$localCoutryList,$urlCountryList) {
file_put_contents($localCountryList, file_get_contents($urlCountryList)); // CREATE FILE
jsonList($serverName); // CALL JSON DATA FROM FILE
};
function jsonList($serverName,$localCoutryList,$urlCountryList) { // JSON DATA FROM FILE
$jsonLoopCountry = file_get_contents($localCoutryList); // GET CONTENT OF THE LOCAL FILE
$outLoopCountry = json_decode($jsonLoopCountry, true); // DECODE JSON FILE
$countryList = $outLoopCountry['country']; // ACCESS TO JSON OBJECT
foreach ($countryList as $dataCountry) { // FOR EACH "COUNTRY" IN JSON DECODED OBJECT
// SET VARS FOR ALL THE COUNTRIES
$iscountryID = ($dataCountry['id']); // TEST
$countryCurrency = ($dataCountry['curr']); // TEST
$countryName = ($dataCountry['name']);} // TEST
echo "<br>total country list: ".count($countryList); // THIS RETURN TOTAL ELEMENTS IN THE ARRAY
[...]
The kind of Json data I'm working with is structured as it follows:
{"country":[{"id":130,"curr":"AFN","name":"Afghanistan"},{"id":55,"curr":"ALL","name":"Albania"},{"id":64,"curr":"DZD","name":"Algeria"},{"id":65,"curr":"AOA","name":"Angola"},{"id":24,"curr":"ARS","name":"Argentina"}...
So I can say that
$outLoopCountry = json_decode($jsonLoopCountry, true); // DECODE JSON FILE
creates the JSON ARRAY right? (Because JSON array starts with {"something":[{"..."...)
if it was [{"a":"answer","b":"answer",...} ... it would have a been a JSON Object right?
So to access to the array I uses
$countryList = $outLoopCountry['country']; // ACCESS TO JSON OBJECT
right?
So I understood that arrays are a fast useful ways to store relational data and access to it right?
So the question is how to make a precise search inside the array, so to make it works like a Query MySQLi, like "SEARCH INSIDE ARRAY WHERE id == 7" and have as a result "== ITALY" (ex.).
The way exist for sure, but with whole exmples I found on the net, I was able to fix one to make it works.
Thx again.
Alberto

mongoDB wont allow me to update

Ok this issue is driving me nutts, I thought that _id was meant to be ObjectID while the first time it inserts it does it correctly when I try to update it using the _id it does not work.
here is my code
//Save Data
function savedata($data){
$collection = $this->db->retail_logs;
$this->data = $data;
if($this->data['_id'] == NULL || $this->data['_id'] == "")
{
$this->data['_id'] = new MongoId();
}
else
{
$this->data['_id'] = ObjectID($this->data['_id']);
}
try {
$collection->update(
array("_id"=>$this->data['_id']),
$this->data, // new lead document to insert
array("upsert" => true, "safe" => true)
);
print $this->data['_id'];
} catch (Exception $e) {
print "we are not able to update";
}
}
i have tried to do the followinf
if($this->data['_id'] == NULL || $this->data['_id'] == "")
{
$this->data['_id'] = new MongoId();
}
else
{
$this->data['_id'] = ObjectID($this->data['_id']);
}
but that seems not to help.
What Is happening is it inserts the first time correctly with ObjectID(idnumber)
then when it goes to update is removes the ObjectID() and inserts a new lead with the same idnumber as before
so it looks like "IDNUMBER"
Your original code is close, but if you want to make a string _id the correct ObjectID type, use:
$this->data['_id'] = new MongoId($this->data['_id']);
Checking the Outcome of an Update Request
A non-upsert update may or may not modify an existing object. An upsert will either modify an existing object or insert a new object. The client may determine if its most recent message on a connection updated an existing object by subsequently issuing a getlasterror command ( db.runCommand( "getlasterror" ) ). If the result of the getlasterror command contains an updatedExisting field, the last message on the connection was an update request. If the updatedExisting field's value is true, that update request caused an existing object to be updated; if updatedExisting is false, no existing object was updated. An "upserted" field will contain the new _id value if an insert is performed (new as of 1.5.4)
Can you run the command as suggested by Mongo Docs and let us know the result of the command
Reference: Mongo Updating

Categories