Undefined index error referencing PHP array - php

I'm getting an error whilst trying to iterate some data and I can't figure out what I'm doing wrong. This is the format of the data I have returned from an API request:
Array
(
[search-results] => Array
(
[entry] => Array
(
[0] => Array
(
[author] => Array
(
[0] => Array
(
[authname] => Griffin J.
[surname] => Griffin
[initials] => J.M.
)
[1] => Array
(
[authname] => Williams D.
[surname] => Williams
[initials] => D.H.
)
)
)
[1] => Array
( ...etc...
)
)
)
)
For reference the above data printout is from $eachJson in the code below.
I can only do an API request to get 100 results at a time, so I set up a for loop to perform the search 100 times, then next 100 etc. As there are multiple authors per record, I set up a foreach loop to iterate the authors and this is where I'm getting the error messages:
Notice: Undefined index: author in C:\xampp\htdocs\academic_intelligence\public\ScopusTest.php on line 42
Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\academic_intelligence\public\ScopusTest.php on line 42
Here's the code:
$apiKey = "&apiKey=c2cb86c3a511ed34dd6f03f481c637c1";
$search1 = urlencode("badgers");
$search2 = urlencode(" OR weasels");
$start = 0;
$scopusData = [];
// create an array to represent citation values to ignore, i.e. not interested
// in any publications with less than 4 citations
$ignore = array(0, 1, 2, 3);
// set processing time for browser before timeout
ini_set('max_execution_time', 3600);
// override default PHP memory limit
ini_set('memory_limit', '-1');
// REST HTTP GET Request searching for people associated with keywords (term)
$searchLink = "http://api.elsevier.com/content/search/scopus?query=KEY(" . $search1 . $search2 . ")" . $apiKey . "&sort=citedby-count&count=100&start=" . $start . "&view=complete";
// save results to a variable
$searchResponse = file_get_contents($searchLink);
// convert JSON to PHP variable
$searchJson = json_decode($searchResponse, true);
// get total number of results for query to know when to stop iterating data
$total = $searchJson['search-results']['opensearch:totalResults'];
// iterate data loading next 200 results (max) each time and adding new results to array
for ($i = $start; $i <= $total; $i+=100) {
// REST HTTP GET Request searching for people associated with keywords (term)
$eachLink = "http://api.elsevier.com/content/search/scopus?query=KEY(" . $search1 . $search2 . ")" . $apiKey . "&sort=citedby-count&count=100&start=" . $i . "&view=complete";
// save results to a variable
$eachResponse = file_get_contents($eachLink);
$eachJson = json_decode($eachResponse, true);
foreach ($eachJson['search-results']['entry'] as $record) {
// array to store authors
$authors = [];
foreach ($record['author'] as $thisAuthor) { // **LINE 42**
// push initials and surname to array
array_push($authors, ($thisAuthor['initials'] . $thisAuthor['surname']));
};
// scopus ID
$scopusID = $record['dc:identifier'];
// paper title
$title = $record['dc:title'];
// date
$date = substr($record['prism:coverDate'], 0, 4);
// citations, if less than 4 then break out of iteration
if (!in_array(($cites = $record['citedby-count']), $ignore)) {
$cites = $record['citedby-count'];
} else {
break 2;
}
$thisData = [
"authors" => $authors,
"ID" => $scopusID,
"title" => $title,
"date" => $date,
"cites" => $cites
];
array_push($scopusData, $thisData);
}
};
// need to replace single quotes to avoid char escape
for ($i = 0; $i < count($scopusData); $i++) {
foreach ($scopusData[$i]['authors'] as &$edit) {
$edit = str_replace("'", "", $edit);
};
$scopusData[$i]['title'] = str_replace("'", "", $scopusData[$i]['title']);
};
I've highlighted line 42 which is causing the error. This must be something straightforward but it's been a long day and I can't figure out the problem! I still get the correct data at the end, the final array scopusData includes all the authors taken from that faulty foreach loop so it seems strange that I'm getting the error.

Are you sure that each record contains an author element?
Maybe you should add an ifset($record['author']) ahead of the foreach() loop.
(re-posted comment as an answer as OP's request)

Related

Reading data from a text file using Strpos & Substr to remove commas between and a while loop to repeat for each row

I'll try and be as clear as I can with what my problem is here, I've been working on this one for a while now and can't seem to get my head around it. Basically, I'm trying to:
Read numbers from a text file & store them in a 2D array
Remove any commas in the text file and store the remaining data in a table format
Using strpos & substr to extract the data, leaving behind unwanted commas
Then using a while loop to repeat this process so every line in the text file is read one at a time until all the lines are read.
At first my code was stating what lines I had errors in and I have since amended but now the php page doesnt seem to load at all. Is there some sort of error within my while loop statement?
Here is the php code I'm currently working with that doesnt seem to be loading:
$fileopen = fopen($file,'r') or die("Sorry, cannot find the file $file");
if($fileopen){
while (($buffer=fgets($fileopen,4096))!==false){
}
if(!feof($fileopen)){
echo "Error:unexpected fgets() fail\n";
}
fclose($fileopen);
}
$filearray = array();
$rows = 0;
$columns = 0;
$fileopen = fopen($file,'r') or die("Sorry, cannot open $file");
while(!feof($fileopen))
{
$line = fgets($fileopen);
$length = strlen($line);
$pos = 0;
$comma = 0;
while($pos < length) {
$comma = strpos($line,",",$comma);
$filearray[$rows][$columns] = substr($line,$pos,$comma);
$pos = $comma +1;
$columns++;
}
$columns = 0;
$rows++;
}
This section is essentially displaying the extracted data from the text file in a table format:
function array_transpose($filearray)
{
array_unshift($filearray, NULL);
return call_user_func_array('array_map', $filearray);
}
echo"<h1></h1>";
echo "<table border = 0 >";
for($row=0; $row<$count; $row++){
print "<tr>";
for($col=0; $col<$count; $col++){
echo "<td>".$array[$row][$col]."</td>";
}
}
echo "</table>";
It was quite the challenge for me to get this one to work, but I managed to do it. I've put comments inside the code to explain what's happening. The reasons it didn't work for you (as I said in the comments) was because you were creating an infinite loop. The $pos integer was always smaller than your $length integer. So the while() loop would never break.
Another issue that you didn't encounter yet was the use of $comma as the length for substr(). Because strpos() returns you the actual position and not the position relative to the offset, this would cause problems. That's why you needed to save the previous position of the delimiter (comma) and substract that from the current position of the delimiter.
Anyway, here is my example code. It's giving you the result that you need. It's up to you to incorporate it into your own code.
<?php
// Initial variables
$result = array();
$key = 0;
// Open the file
$handle = fopen("numbers.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
// First we set the delimiter into a variable
$delimiter = ',';
// Some integers we're going to use for our loop
$pos = 0; // The current position
$comma = 0; // Position of the next comma
$innerkey = 0; // Key used for the 2D result array
$previous = 0; // Previous comma position
$loops = 0; // Number of loops
$nr_commas = substr_count($line, $delimiter); // Number of commas in a single line
while($loops <= $nr_commas) {
// Get the position of the next comma
$comma = strpos($line,$delimiter,$comma);
// Make sure a comma is found
if($comma !== false){
// Put the substring into the result array using $pos as the offset
// and calculating the length by substracting the position of the previous
// comma from the current comma.
$result[$key][$innerkey] = substr($line,$pos,$comma - $previous);
// Add 1 to the previous comma or it will include the current comma in the result
$previous = $comma + 1;
$pos = $comma + 1;
$innerkey++;
$loops++;
$comma++;
} else {
// In case no more commas are found, we still need to add the last integer
$loops++;
$result[$key][$innerkey] = substr($line,strrpos($line,$delimiter)+1);
}
}
$key++;
}
fclose($handle);
} else {
echo "Unable to open the file";
}
echo "<pre>";
print_r($result);
echo "</pre>";
?>
TXT File used:
3,34,2,35,4,234,34,2,53,4
5,4,23,6,67,324,5,34,5
345,67,3,45,6,7
Result:
Array
(
[0] => Array
(
[0] => 3
[1] => 34
[2] => 2
[3] => 35
[4] => 4
[5] => 234
[6] => 34
[7] => 2
[8] => 53
[9] => 4
)
[1] => Array
(
[0] => 5
[1] => 4
[2] => 23
[3] => 6
[4] => 67
[5] => 324
[6] => 5
[7] => 34
[8] => 5
)
[2] => Array
(
[0] => 345
[1] => 67
[2] => 3
[3] => 45
[4] => 6
[5] => 7
)
)

Handle csv with php in for loop and write them back

i'm struggling with a php code that must open more than 1 csv, handle its content and write back on a different way that was initially.
So, i have all csv's on rows, and i wanna parse them and split them in columns on 2 rows.
The code looks like:
$currentDirOtherCSV = __DIR__ . "/uploads/" . $ftp_location . "partial_crawler_data/";
$files_other_CSV = scandir($partial_crawler_data, 1);
for($i = 0; $i < count($files_other_CSV) - 2; $i++){
$csvFileToOpen = file($currentDirOtherCSV . $files_other_CSV[$i]);
$screamingDataFirst = [];
foreach ($csvFileToOpen as $line) {
$screamingDataFirst[] = str_getcsv($line);
}
// remove header from csv
array_shift($screamingDataFirst);
array_shift($screamingDataFirst);
// handle array to export it on 2 rows
$theExportArray = [[],[]];
for($j = 0; $j < count($screamingDataFirst); $j++){
if(!array_key_exists('1', $screamingDataFirst[$j])) {
$screamingDataFirst[$j][1] = "";
}
}
foreach ($screamingDataFirst as $key => $row){
$theExportArray[0][$key] = $row[0];
$theExportArray[1][$key] = $row[1];
}
print_r($theExportArray);
// edit csv file remote
$new_csv_data = fopen($currentDirOtherCSV . $files_other_CSV[$i], "w");
foreach($theExportArray as $row){
fputcsv($new_csv_data, $row, ";");
}
fclose($new_csv_data);
}
The csv looks like:
"Page Titles - Duplicate"
"Address","Title 1"
"http://www.seloo.ro/index.php?route=product/product&path=60&product_id=123","Scaun tapitat Alb"
"http://www.seloo.ro/index.php?route=product/product&path=60&product_id=122","Scaun tapitat Alb"
"http://www.seloo.ro/index.php?route=product/product&path=60&product_id=121","Scaun tapitat Alb"
"http://www.seloo.ro/index.php?route=product/product&path=60&product_id=127","Scaun tapitat Alb"
so i get this array by parsing it:
Array
(
[0] => Array
(
[0] => http://www.seloo.ro/index.php?route=product/product&path=60&product_id=123
[1] => http://www.seloo.ro/index.php?route=product/product&path=60&product_id=122
[2] => http://www.seloo.ro/index.php?route=product/product&path=60&product_id=121
[3] => http://www.seloo.ro/index.php?route=product/product&path=60&product_id=127
)
[1] => Array
(
[0] => Scaun tapitat Alb
[1] => Scaun tapitat Alb
[2] => Scaun tapitat Alb
[3] => Scaun tapitat Alb
)
)
EDIT
That must be:
http://www.seloo.ro/index.php?route=product/product&product_id=95;http://www.seloo.ro/index.php?route=product/product&path=59&product_id=95;http://www.seloo.ro/index.php?route=product/product&product_id=94;
"Masa New vision";"Masa flori lila";"Masa flori lila";
Problem:
I thought that if i open the file, handle it, push it back modified in the csv and close (fclose) then do it again untill no csv, will handle them 1 by one...
But it only write in a single csv, rest of them arent touched
Am i missing something?
UPDATE
The script works fine.
The problem was that i have tried to update the unuploaded files on the server.
Script was faster than upload.
Thank you all and sorry, i should check that earlier

Manipulating multiple arrays to output a table of unique values

I have 5 different arrays which I need to use to generate a table showing the info. This table cannot have duplicates. This is in a way a fairly easy task, but what I am looking for is the most elegant solution - one that doesn't require lots of for loops, array merging etc etc.
The table needs to output information for photo printing. And should look a bit like this:
Not like this:
The arrays look like this:
//img arr:
$img_arr = array(array('002_chrysanthemum', '6x4'), array('002_chrysanthemum', '9x6'));
//size arr:
$size_arr = array('6x4', '9x6');
//finish arr:
$finish_arr = array('glossy', 'glossy');
//qty arr:
$qty_arr = array(2, 3);
//media arr:
$media_arr = array('std', 'std');
Thanks.
EDIT - Typo with finish / qty arr pointed out, changed, thanks.
Group your images into an array indexed first by image name and second by its size.
Loop through each size to render the column headers, then loop through each grouped image to render the rows.
$img_arr = array(array('002_chrysanthemum', '6x4'), array('002_chrysanthemum', '9x6'));
$size_arr = array('6x4', '9x6');
$finish_arr = array('glossy', 'glossy');
$qty_arr = array(2, 3);
$media_arr = array('std', 'std');
$images = array();
foreach($img_arr as $key => $img) {
$images[$img[0]][$img[1]] = array(
'finish' => $finish_arr[$key],
'qty' => $qty_arr[$key],
'media' => $media_arr[$key],
);
}
print "<table>";
print "<tr><th></th>";
foreach($size_arr as $size) {
print "<th>$size</th>";
}
print "</tr>";
foreach($images as $name => $image) {
print "<tr><td>$name</td>";
foreach($size_arr as $size) {
print "<td>" . $image[$size]['qty']
. '#' . $image[$size]['finish']
. ' ' . $image[$size]['media'] . "</td>";
}
print "</tr>";
}
print "</table>";
$img_arr = array('002_chrysanthemum', '002_chrysanthemum');
$size_arr = array('6x4', '9x6');
$finish_arr = array('glossy', 'glossy');
$qty_arr = array(2, 3);
$media_arr = array('std', 'std');
Could be combined into one sensible array like:
foreach($img_arr as $k=>$img) {
foreach($size_arr as $size) {
$prints[$img][$size]['finish'] = $finish_arr[$k];
$prints[$img][$size]['qty'] = $qty_arr[$k];
$prints[$img][$size]['media'] = $media_arr[$k];
}
}
The result, which is based on the idea that image array is the x-axis and sizes are the y-axis and all other arrays are properties based on position to the y-axis. So then:
print_r($prints);
returns
Array (
[002_chrysanthemum] => Array
(
[6x4] => Array
(
[finish] => glossy
[qty] => 3
[media] => std
)
[9x6] => Array
(
[finish] => glossy
[qty] => 3
[media] => std
)
)
)
Which is the very elegant and simple data collection that you want to transform into a table, which it can be now that it is normalized.

PHP Array question?

Hope you are fine. My question :
In MYSQL i have a table with this type of field
Field Name: TAGS
Value : xavier,celine,marise,leon,john,cathy,polux,maurice
In PHP i do this
$xwords = array();
function array_rpush(&$arr, $item)
{
$arr = array_pad($arr, -(count($arr) + 1), $item);
}
$tags = requete("SELECT tags FROM tbl_tags LIMIT 1;");
while($dtags = mysql_fetch_assoc($tags)){
$words .= array_rpush($xwords, $dtags['tags']);
}
// MY ARRAY XWORDS FOR DEBUG
//
// Array ( [0] => xavier, celine, marise, leon, john, cathy, polux, maurice
//
My script need to find the first letter of each word in this list and check if he match with A / B / C (i create an A-Z index page)
// COUNT $XWORDS VALUE
$total = count($xwords);
// total =1
for($i=0; $i < $total; $i++)
{
$wtags = explode(",",$xwords[$i]);
// wtags = Array ( [0] => xavier [1] => celine [2] => marise... )
while (list($idx,$val) = each($wtags)) {
echo $val{0}."<br>";
echo substr($val,0,1)."<br>";
}
}
echo $val{0}."<br>"; OR echo substr($val,0,1)."<br>" give me just x and nothing after (while give me only the first letter for the first record in array... amazing :))
Perhaps you can help me find a solution. Thanks
The problem with your code is that it generates:
Array ( [0] => "xavier" [1] => " celine" [2] => " marise"... )
So $val[0] = " ". Try to trim($val):
$val = trim($val);
print $val[0];
$sum = array();
foreach($wtags as $tag){
$tag = trim($tag);
empty($sum[$tag{0}]) ? // if we don't have a $sum element for this letter
$sum[$tag{0}] = 1 : // we initialize it
$sum[$tag{0}]++; // else, we sum 1 element to the count.
//$tag{0} is the first letter.
}
// the array $sum has the total of tags under each letter
//
// $sum[x] = 1
// $sum[c] = 2
// $sum[m] = 2
// $sum[l] = 1
// $sum[j] = 1
// $sum[p] = 1

Array not populating correctly

I am using the following code to populate an array:
$number = count ($quantitys);
$count = "0";
while ($count < $number) {
$ref[$count] = postcodeUnknown ($prefix, $postcodes[$count]);
$count = $count +1;
}
postcodeUnknown returns the first row from a mysql query, using a table prefix and an element from an array named postcodes. $postcodes contains strings that should return a different row each time though the loop.
Which I'd expect to create an array similar to:
Array ([0] =>
Array ([0] => some data [1] => more data)
[1] =>
Array ([0] => second row [1] => even more...)
)
But it's not. Instead it's creating a strange array containing the first results over and over until the condition is met, eg:
simplified result of print_r($ref);
Array (
[0] => Array ([0] => some data [1] => more data)
)
Array(
[0] => Array (
[0] => the first arrays content...
[1] => ...repeated over again until the loop ends
)
)
And I'm at a loss to understand why. Anyone know better than me.
Try
$number = count ($quantitys);
$count = "0";
while ($count < $number) {
$ref1[$count] = postcodeUnknown ($prefix, $postcodes[$count]);
$ref2[] = postcodeUnknown ($prefix, $postcodes[$count]);
$ref3[$count][] = postcodeUnknown ($prefix, $postcodes[$count]);
$count = $count +1;
}
echo "<pre>";
print_r($ref1);
print_r($ref2);
print_r($ref3);
echo "</pre>";
Try that to see if any of those get an output you are looking for.
Uh, add a print to postcodeUnknown and check if its actually passing different postcodes or the same thing all the time?
ie
function postcodeUnkown($a,$b){
echo var_dump($a).var_dump($b);
//the rest
}
Also, why two different variables? ($quantitys and $postcodes).
Also, you might want to replace the while loop with for:
for($i=0;$i<$number;$i++){
$ref[$i] = postcodeUnknown ($prefix, $postcodes[$i]);
}
your variable count should not be a string, try this
$number = count ($quantitys);
$count = 0;
while ($count < $number) {
$ref[$count] = postcodeUnknown ($prefix, $postcodes[$count]);
$count = $count +1;
}

Categories