empty array attribute on php object - php

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.

Related

What is the correct syntax for using a PHP class function to supply the value for a variable in the same class?

I am working on a college project that must use a CSV file to create the values for a table. It must have a class and it must have specific class variables (one of them I have already created for testing). Only the variables are specified as having to be part of the class but I think it would be better to pack the function inside the class (unless someone has a different opinion).
Basically, I want to use the class function to create the values for the class variables. Here is my script (refer to the comments for explanation):
<?php
class productRow {
function make_table_row($i) {
$row = 1;
$tablerows = [];
if (($input = fopen("input.csv", "r")) !== FALSE) {
while (($tabledata = fgetcsv($input, 1000, ",")) !== FALSE) { //cycles through the rows of data creating arrays
if ($row == 1) {
$row++;
continue; //skips the first row because it's a header row I don't want on my input
}
$tablerows[] = $tabledata; //uses the roles to populate a multidimensional array
$row++;
}
fclose($input);
return $tablerows[$i]; //uses the $i argument to return one of the row arrays
}
}
var $itemNumber = this->make_table_row($i)[0]; //Line 118: calls make_table_row function to get the first item from the row returned
}
$pr1 = new productRow;
echo $pr1->make_table_row(1); //calls the function from within the class
?>
I get this error: Fatal error: Constant expression contains invalid operations in C:\xampp\htdocs\Tylersite\index.php on line 118
I know the return works because I tested it with print_r, including adding an array number as I did with that variable value to get a specific array value. So I must not be calling that function instance correctly. I've tried various things including removing the $this keyword as I wasn't sure I needed it, but the truth is I don't really know how to do it and I'm having trouble finding documentation on the correct syntax. Does anyone know what to do?
Example using constructor function
class productRow {
var $itemNumber = []; // default value doesn't matter as it will change in __construct
public function __construct($i) {
$this->itemNumber = $this->make_table_row($i)[0];
}
function make_table_row($i) {
$row = 1;
$tablerows = [];
if (($input = fopen("input.csv", "r")) === FALSE) {
// return early - reduces indentation
return;
}
while (($tabledata = fgetcsv($input, 1000, ",")) !== FALSE) { //cycles through the rows of data creating arrays
if ($row == 1) {
$row++;
continue; //skips the first row because it's a header row I don't want on my input
}
$tablerows[] = $tabledata; //uses the roles to populate a multidimensional array
$row++;
}
fclose($input);
return $tablerows[$i]; //uses the $i argument to return one of the row arrays
}
}
$pr1 = new productRow(1);
var_dump($pr1->make_table_row(1));

what is the best way for search in json file in php?

hi i have many data files in json format in a folder.
now i want to search a filed in them .my search word maybe not exist in some of them and may be exist in one of them files.
i have read this function and if not exits in a file i call the function to read another file.
when i echo the result show me and works fine but return not working and no data returned.
function get_shenavari_in_files($search,$type)
{
static $counter =1 ;
$darsadi = 0;
$find = false;
$file_name = get_files_in_dir(); // make an array of file names
$file_number = count($file_name)-$counter ;
$file="files/" .$file_name[$file_number];
$file_data = read_json($file);
for($i = 0 ; $i<count($file_data) ; $i++)
{
if($file_data[$i][$type] == $search )
{
$darsadi = $file_data[$i]['darsadi'] ;
$find = true;
echo $darsadi ; //this works and show the data
return $darsadi; // this is my problem no data return.
break;
}
}
if($find == false)
{
$counter ++;
get_shenavari_in_files($search,$type);
}
}
var_dump(get_shenavari_in_files('Euro','symbol')); //return null
Once you recurse into get_shenavari_in_files, any found value is never returned back to the inital caller, i.e. instead of
if($find == false)
{
...
get_shenavari_in_files($search,$type);
}
you simply need to prepend the function call with a returnstatement
if($find == false)
{
...
return get_shenavari_in_files($search,$type);
}
Having said that, I would try a much simpler (and thereby less error-prone) approach, e.g.:
function get_shenavari_in_files($search, $type) {
$files = glob("files/*.json"); // Get names of all JSON files in a given path
$matches = [];
foreach ($files as $file) {
$data = json_decode(file_get_contents($file), true);
foreach ($data as $row) {
if (array_key_exists($type, $row) && $row[$type] == $search) {
$matches[$file] = $search;
}
}
}
return $matches;
}
This way, you would be able to eliminate the need for a recursive call to get_shenavari_in_files. Also, the function itself would become more performant because it doesn't have to scan the file system over and over again.

I am reading csv file and what array_map() function does in this function?

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.

Creating a function that takes arguments and passes variables

I am creating a script that will locate a field in a text file and get the value that I need.
First used the file() function to load my txt into an array by line.
Then I use explode() to create an array for the strings on a selected line.
I assign labels to the array's to describe a $Key and a $Value.
$line = file($myFile);
$arg = 3
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
This works fine but that is a lot of code to have to do over and over again for everything I want to get out of the txt file. So I wanted to create a function that I could call with an argument that would return the value of $key and $val. And this is where I am failing:
<?php
/**
* #author Jason Moore
* #copyright 2014
*/
global $line;
$key = '';
$val = '';
$myFile = "player.txt";
$line = file($myFile); //file in to an array
$arg = 3;
$Character_Name = 3
function get_plr_data2($arg){
global $key;
global $val;
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
return;
}
get_plr_data2($Character_Name);
echo "This character's ",$key,' is ',$val;
?>
I thought that I covered the scope with setting the values in the main and then setting them a global within the function. I feel like I am close but I am just missing something.
I feel like there should be something like return $key,$val; but that doesn't work. I could return an Array but then I would end up typing just as much code to the the info out of the array.
I am missing something with the function and the function argument to. I would like to pass and argument example : get_plr_data2($Character_Name); the argument identifies the line that we are getting the data from.
Any help with this would be more than appreciated.
::Updated::
Thanks to the answers I got past passing the Array.
But my problem is depending on the arguments I put in get_plr_data2($arg) the number of values differ.
I figured that I could just set the Max of num values I could get but this doesn't work at all of course because I end up with undefined offsets instead.
$a = $cdata[0];$b = $cdata[1];$c = $cdata[2];
$d = $cdata[3];$e = $cdata[4];$f = $cdata[5];
$g = $cdata[6];$h = $cdata[7];$i = $cdata[8];
$j = $cdata[9];$k = $cdata[10];$l = $cdata[11];
return array($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l);
Now I am thinking that I can use the count function myCount = count($c); to either amend or add more values creating the offsets I need. Or a better option is if there was a way I could generate the return array(), so that it would could the number of values given for array and return all the values needed. I think that maybe I am just making this a whole lot more difficult than it is.
Thanks again for all the help and suggestions
function get_plr_data2($arg){
$myFile = "player.txt";
$line = file($myFile); //file in to an array
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
return array($key,$val);
}
Using:
list($key,$val) = get_plr_data2(SOME_ARG);
you can do this in 2 way
you can return both values in an array
function get_plr_data2($arg){
/* do what you have to do */
$output=array();
$output['key'] =$key;
$output['value']= $value;
return $output;
}
and use the array in your main function
you can use reference so that you can return multiple values
function get_plr_data2($arg,&$key,&$val){
/* do job */
}
//use the function as
$key='';
$val='';
get_plr_data2($arg,$key,$val);
what ever you do to $key in function it will affect the main functions $key
I was over thinking it. Thanks for all they help guys. this is what I finally came up with thanks to your guidance:
<?php
$ch_file = "Thor";
$ch_name = 3;
$ch_lvl = 4;
$ch_clss = 15;
list($a,$b)= get_char($ch_file,$ch_name);//
Echo $a,': ',$b; // Out Puts values from the $cdata array.
function get_char($file,$data){
$myFile = $file.".txt";
$line = file($myFile);
$cdata = preg_split('/\s+/', trim($line[$data]));
return $cdata;
}
Brand new to this community, thanks for all the patience.

PHP Notice: Undefined property: Tpl::$lbName

I have a class Tpl to mount template with this function (template.php)
function Set($var, $value){
$this->$var = $value;
}
A php file that call the function, example (form.php):
$t->Set("lbAddress","Address");
And a html file with the template with tags (template.html)
<tr><td>[lbAdress]</td></tr>
To print the html I have this function (template.php) - the notice points to this function
function Show_Temp($ident = ""){
// create array
$arr = file($this->file);
if( $ident == "" ){
$c = 0;
$len = count($arr);
while( $c < $len ){
$temp = str_replace("[", "$" . "this->", $arr[$c]);
$temp = str_replace("]", "", $temp);
$temp = addslashes($temp);
eval("\$x = \"$temp\";");
echo $x;
$c++;
}
} else {
$c = 0;
$len = count($arr);
$tag = "*=> " . $ident;
while( $c < $len ){
if( trim($arr[$c]) == $tag ){
$c++;
while( (substr(#$arr[$c], 0 ,3) != "*=>" ) && ($c < $len) ){
$temp = str_replace("[", "$" . "this->", $arr[$c]);
$temp = str_replace("]", "", $temp);
$temp = addslashes($temp);
eval("\$x= \"$temp\";"); //this is the line 200
echo $x;
$c++;
}
$c = $len;
}
$c++;
}
}
}
If the template .html have a line [lbName] and I don't have the line $t->Set("lbName","Name"); at the php code, I receive the error PHP Notice: Undefined property: Tpl::$lbName in ../template.php(200) : eval()'d code on line 1. The solution that I found is add lines like $t->Set("lbName","");, but if I have 50 tags in HTML that I don't use in PHP, I have to add all 50 $t->Set("tag_name","");. The error occurred after migrate to the PHP 5.
Can someone help me? Thanks
Perhaps a better way still would be not to rely on dynamic evaluation through eval (it's generally best to avoid eval where possible), but to replace [lbName] with the value stored in the object directly as and when needed. If you can replace [lbName] with $this->lbName, surely you can also replace it with the value of lBName that you've looked up on-the-fly?
To answer your original question, however:
If I understand correctly, you're setting the values like this:
$t->Set('foo', 'bar');
And – effectively – getting them like this:
$t->foo;
If so, you could implement a __get method to intercept the property references and provide your own logic for retrieving the value; e.g.:
public function __get($key)
{
// You can adapt this logic to suit your needs.
if (isset($this->$key))
{
return $this->$key;
}
else
{
return null;
}
}
In this case, you'd probably be better off using an associative array as the backing store, and then using __get and __set to access it; e.g.:
class Template
{
private $values = array();
public function __get($key)
{
if (array_key_exists[$key, $this->values])
{
return $this->values[$key];
}
else
{
return null;
}
}
public function __set($key, $value)
{
$this->values[$key] = $value;
}
}

Categories