I have this code and no code before it that refers to any variables seen below. Yet I still can't find why I'm getting the error: "First argument should be an array in..."
$array = array("element here for reason");
function sortdata()
{
$File = fopen("Names.txt", "r");
//put each file line into an array element
while(!feof($File))
{
array_push($array, fgets($File));
}
}
$array is out of scope to the function. You can bring it into scope using global.
$array = ..;
function sortdata() {
global $array;
...
}
sortdata();
Alternatively, you can pass it by reference into the function.
$array = ..;
function sortdata(&$array) {
...
}
sortdata($array);
You use variable $array inside function body. In this case this is local variable and it automatically sets to string.
For work with your global variable $array you should use instruction global in your function.
function sortdata() {
global $array;
/* there your code for work with $array */
}
The issue with the code is that you are not passing the $array variable into the function. Aside from that, it would be more efficient to use the shortcut way to add an item to the array instead of calling array_push since it eliminates the overhead of calling a function.
$array = array("element here for reason");
function sortdata($array)
{
$File = fopen("Names.txt", "r");
//put each file line into an array element
while(!feof($File))
{
$array[] = fgets($File);
}
return $array;
}
You should try to first initialize the array and bring the array within the scope of the function like so:
$array = array();
array_push($array, "element here for reason");
function sortdata()
{
global $array;
$File = fopen("Names.txt", "r");
//put each file line into an array element
while(!feof($File))
{
array_push($array, fgets($File));
}
}
This give you backward compatibility
function sortdata(array $array = array())
{
$File = fopen("Names.txt", "r");
while(!feof($File))
{
array_push($array, fgets($File));
}
return $array;
}
Related
In PHP, I want to read a ".CSV" file using the following function.
function csv_to_array($filename='a.txt', $header_exist=true, $delimiter="\t")
{
if(!file_exists($filename) || !is_readable($filename))
return FALSE;
$header = NULL;
$data = array();
if (($handle = fopen($filename, 'r')) !== FALSE)
{
while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
{
if($header_exist)
{
if(!$header)
$header = array_map('trim', $row);
else
$data[] = array_combine($header, $row);
}
else
$data[] = $row;
}
fclose($handle);
}
return $data;
}
and I am bit confused about array_map() function. I think it is supposed to map column names to each attribute is that so then how to fetch and display eacg attribute?
Thank you!
Opening a manual page for array_map you can see that:
array_map — Applies the callback to the elements of the given arrays
So, you have a callback, which is trim (a core php function) and an array, which is $row. So, function trim now applied to each element of $row.
So, it is equivalent of:
$header = [];
foreach ($row as $item) {
$header[] = trim($item);
}
In PHP, array_map(function_name, array) function sends each value of array to the function_name() and returns a new array.
In your case, The $header holds the string of column names separated by ,'s. This means array_map() function converts them into an array.
Hope you get it.
This is my class,which reads a csv and store the info in some way
<?php
class CSV{
private $data;
function __construct($filename){
$this->data = $this->getDataFromFile($filename);
}
public function __get($property){
if(property_exists($this,$property)){
return $this->$property;
}
}
private function getDataFromFile($filename){
$new_data = array();
$result = array();
if (($handle = fopen($filename,"r")) !== FALSE) {
while (($data = fgetcsv($handle, 10000, ",")) !== FALSE) {
array_push($result, explode(";", $data[0]));;
}
fclose($handle);
}
$header = $result[0];
$in_columns = array();
for ($j = 0 ; $j < count($result[0]); $j++){
$new = array();
for ($i = 1 ; $i < count($result); $i++){
array_push($new, $result[$i][$j]);
}
array_push($in_columns, $new);
}
$idx = 0;
foreach ($header as $title) {
$new_data[$title] = $in_columns[$idx];
$idx++;
}
//var_dump($new_data);//the content of $new_data its correct
$this->data = $new_data;
}
}
?>
but wen I try to use the class
$csv = new CSV('./csv/file.csv');
var_dump($csv->__get('data'));
the last var_dump shows a NULL value ¿What is wrong on the assignation of the value?It looks correct for me ,where cold be the problem??
The problem is that your CSV file ends with a blank line (\n after the last line).
Thus you're working on an empty array, pushing an unitialized variable (null) into the data array.
You're calling $this->getDataFromFile($filename) in constructor and assigning it's value to $this->data.
However... implementation of getDataFromFile() didn't actually return any value, so it's assigning NULL to this property.
You need to change getDataFromFile() to return value OR
get rid of variable assignment in constructor -
$this->data is already set in your method.
Regarding __get() -
it's a magic method. It checks if specified property exists and if so - return it's value. You won't call it this way. Use following code (after making $this->data public):
var_dump($csv->data);
OR prepare accessor for this property which will return this value.
I have been researching fgetcsv() and have the following working code:
$file = fopen($pathToCsv,"r");
$data = array();
while(! feof($file))
{
array_push($data, fgetcsv($file));
}
fclose($file);
However, when I try to adapt this to dynamically accept an unknown number of csv files stored into an array, things cease to work:
$year = $_POST['year'];
$m = "maths".$year;
$sheets = $$m; //an array containing between 5 an 8 paths to csv and other info
$data = array();
function ArrayFromCsv($file, $i) {
while(! feof($file))
{
array_push($data[$i], fgetcsv($file)); //line 15
}
fclose($file);
}
for ($i = 0; $i < count($$m); $i++){
array_push($data, array());
$x = fopen($sheets[$i]['csv'],'r');
ArrayFromCsv($x, $i);
}
I get: Warning: array_push() expects parameter 1 to be array, null given in ... on line 15
I'm not how to research this further. Is there a better way or obvious mistake? I've tried a number of methods.
You dont have access to the global $data variable inside of the function ArrayFromCsv. You either need to use "global $data" inside the function, which is bad, so DON'T
Or you could create a temporary array inside the function, which you return when the function ends and put the returned value from the function into $data[$i]. Also you should not open a file outside of a function and close it inside of a function. That could lead to undefined behaviour someday when your code gets bigger.
function ArrayFromCsv($file, $i) use (&$data) {
while(! feof($file))
{
array_push($data[$i], fgetcsv($file)); //line 15
}
fclose($file);
}
I have a 2 arrays as
$check_string = array("www.salmat.", "www.webcentral.", "abpages.");
and
$files = array("http_www.salmat.com.au_.png", "http_www.webcentral.com.au_.png");
And now i want to check if value of each element in array $check_string matches with atleast part of a string of each element of array $files and if it does not match then i will echo respective values $check_string.
So i am doing with array_filter function
foreach ($check_string as $final_check)
{
function my_search($haystack)
{
global $final_check;
$needle = $final_check;
return(strpos($haystack, $needle));
}
$matches[] = array_filter($files, 'my_search');
if(empty($matches))
{
echo $final_check;
echo "</br>";
}
}
But with this code i get an error
Fatal error: Cannot redeclare my_search() (previously declared in same file)
Can any one suggest any solution
i refereed this and this but cannot get through the solution
Thankyou
function my_search($haystack)
{
global $final_check;
$needle = $final_check;
return(strpos($haystack, $needle));
}
That function needs to be defined outside the loop. And you can just call it again and again in the loop. Currently you are trying to redeclare it on every iteration of the loop.
Not going to suggest further fixes to your code since it's logic is not very good. You can try something like this
$check_string = array("www.salmat.", "www.webcentral.", "abpages.");
$files = array("http_www.salmat.com.au_.png", "http_www.webcentral.com.au_.png");
foreach($check_string as $check)
{
$found=FALSE;
foreach($files as $file)
{
if(stristr($file,$check)!==FALSE)
$found=TRUE;
}
if(!$found)
echo $check,"\n";
}
Fiddle
Of course you can improve it and use less code but that gives you a direction.
Scenario/Problem Isolation: Lets suppose my program uses MULTIPLE variables. At the program beginning I want to manipulate MANY of the variables AT ONCE through a general function with LITTLE CODE, before then later in the process using only distinctive few variables in specific functions.
Question: How do I pass multiple variables by reference to a foreach loop? Or is there a better/alternative method for looping through multiple determined variables?
Post(s) related to topic, but didn't solve my issue:
PHP foreach loop on multiple objects?
Background (for those concerned): I have a command line program which uses getopts http://hash-bang.net/2008/12/missing-php-functions-getopts/ to get various arguments, thus I get about 20 variables. I want to run all variables, which contain filepath(s) (about 10) through the "general" function reduceHierarchyDots() at ONCE (instead of calling the function 10 times).
<?php
/// The "general" function:
function reduceHierarchyDots ($file) {
while (preg_match('|./\.{2}/|', $file)) { $file = preg_replace('|/([^/]+)/\.{2}/|', '/', $file, 1); }
$file = preg_replace('|(/(\./)+)|', '/', $file);
$file = preg_replace('|^(\./)+|', '', $file);
return $file;
}
function reduceHierarchyDotsRef (&$file) {
while (preg_match('|./\.{2}/|', $file)) { $file = preg_replace('|/([^/]+)/\.{2}/|', '/', $file, 1); }
$file = preg_replace('|(/(\./)+)|', '/', $file);
$file = preg_replace('|^(\./)+|', '', $file);
}
/// The "many" variables:
$x = "something";
$y = 123;
$y = array ("a", "B", 3);
$a = "/Users/jondoe/Desktop/source/0.txt";
$b = "/Users/jondoe/Desktop/source/../1.txt";
$c = "/Users/jondoe/Desktop/source/../../2.txt";
$arrOne = array (
"v1" => "/some/thing/../1.pdf",
"v2" => "/some/thing/../../2.pdf",
"v3" => "/some/thing/../../../3.pdf"
);
$arrTwo = array (
"./1.doc",
"/so.me/.thing/ends./././2.doc",
"./././3.doc"
);
/// At the beginning I want to run multiple determined variables through a "general" function:
/// Debugging: Variables BEFORE the manipulation:
echo("BEFORE:\n"); var_dump($b, $arrOne["v2"], $arrTwo[2]); echo("\n");
/// Method works, but is long! (1 line/statement per function call)
reduceHierarchyDotsRef($b);
reduceHierarchyDotsRef($arrOne["v2"]);
reduceHierarchyDotsRef($arrTwo[2]);
/// Hence, I'd like to pass all variables by reference at once to a foreach loop:
//// These cause: Parse error: syntax error, unexpected '&':
// foreach ( array($b, $arrOne["v2"], $arrTwo[2] ) as &$file) { $file = reduceHierarchyDots($file); }
// foreach (array(&$b, &$arrOne["v2"], &$arrTwo[2] ) as &$file) { $file = reduceHierarchyDotsRef($file); }
//// These have no effect on the intended variables:
// foreach (array(&$b, &$arrOne["v2"], &$arrTwo[2] ) as $file) { $file = reduceHierarchyDots($file); }
// foreach (array(&$b, &$arrOne["v2"], &$arrTwo[2] ) as $file) { $file = reduceHierarchyDotsRef($file); }
/// Debugging: Variables AFTER the manipulation:
echo("AFTER:\n"); var_dump($b, $arrOne["v2"], $arrTwo[2]);
/// After the "general" function ran over various variables, the more specific actions happen: ...
?>
You could try generating an array of the variable names, then using variable variables:
$x = '/bees/../ham';
$y = 'some/other/path';
$arr = array('x', 'y');
foreach($arr as $item) {
reduceHierarchyDotsRef($$item);
}
not sure if this works with passing by reference, but I see not reason for it not to work.
Pass by reference is defined in the function signature:
function func(&$passByRef);
That's why your code is throwing errors.
See: http://php.net/manual/en/language.references.pass.php