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;
}
}
Related
I have a "Array to string conversion" notice for this line when i upgrade from 5.6 to 7.1 :
$template = $this->$functions[$i]($name, $value);
how i could resolve it in order to work with php7.1 ?
UPDATE :
protected function getobjectTemplate($name, $value)
{
$template = false;
$functions = [
'getObjectFormClientTemplate',
'getObjectFormTemplate',
'getObjectAirformTemplate',
'getTypeAirformTemplate',
'getAirfileTemplate',
'getTextAirformTemplate',
];
$i = 0;
while (!$template) {
$template = $this->$functions[$i]($name, $value);
++$i;
}
return $template;
}
here the call of the method getobjectTemplate
$template = $this->getobjectTemplate($name, $value);
This can be one of the solutions. First store the function name in a variable and then use it.
while (!$template) {
$temp=$functions[$i];
$template = $this->$temp($name,$values);
++$i;
}
I am not sure if this is the most elegant solution but it would work:
protected function getobjectTemplate($name, $value)
{
$template = false;
$functions = [
'getObjectFormClientTemplate',
'getObjectFormTemplate',
'getObjectAirformTemplate',
'getTypeAirformTemplate',
'getAirfileTemplate',
'getTextAirformTemplate',
];
$i = 0;
while (!$template) {
$func = [ $this, $functions[$i] ];
$template = $func($name, $value);
++$i;
}
return $template;
}
I would probably also go ahead and remove the while (!template) condition as it has the potential to make your code enter into an infinite loop. Probably use a better condition like $i < count($functions) or even better with something like:
$i = 0;
$funcCount = count($functions);
while(!$template && $i < $funcCount){
# ...
++$i;
}
Also, you are returning only the last value from all the functions being called via return $template. If you only have to return the last value, why not call only the required function and not have a loop. Not sure, if having a loop is the best approach. Would help if you provided more details of your code.
I have created for code to check if its palindrome. Now if the string is not a palindrome I want it to be reversed.Can it be done using one conditional loop?
My php code:
class user{
public function __construct() {
if ($this->String_Rev()) {
echo 'Yes, palindrome';
} else {
echo 'not palindrome';
}
}
public function String_Rev() {
$str = "abba";
$i = 0;
while ($str[$i] == $str[strlen($str) - ($i + 1)]) {//Incrementing and decrementing the values in the string at the same time/
$i++;
if ($i > strlen($str)/ 2) {//If the i goes ahead of half of its string then return true and stop its execution.
return 1;
}
}
return 0;
}
}
$obj = new user();
Strings in PHP are not arrays, but you can select the character index of a string just like an array key, which makes the following possible:
<?php
$string = 'foobar';
$string_array = array();
//make an actual array of the characters first
//if you want this to be an object, do this part in your constructor,
//and assign this variable to an object property to work with.
for ($i=0; $i < strlen($string); $i++)
{
$string_array[$i] = $string[$i];
}
echo implode( $string_array ); //prints 'foobar'
echo '<br>' . PHP_EOL;
echo implode( array_reverse( $string_array ) ); //prints 'raboof'
You could easily simplify your palindrome logic by doing this:
//in your case, this would probably be it's own method,
//using the aforementioned class property made in the constructor
$is_palindrome = implode( $string_array ) === implode( array_reverse( $string_array ) );
I am using a recursive function in php. The function travers through an array and inputs some values of the array in a new array. I am using array_push() to enter values in the new array and I have also tried to do it without using array_push. This is the part of the function that calls the recursive function
if ($this->input->post('id') != '') {
$id = $this->input->post('id');
global $array_ins;
$k=0;
$data['condition_array'] = $this->array_check($id, $menus['parents'], $k);
// trial
echo "<pre>";
print_r($menus['parents']);
print_r($data['condition_array']);die;
// trial
}
and this here is the recursive function
function array_check($val, $array_main, $k) {
// echo $val . "<br>";
$array_ins[$k] = $val;
echo $k . "<br>";
$k++;
// $array_ins = array_push($array_ins, $val);
echo "<pre>";
print_r($array_ins);
if ($array_main[$val] != '') {
for ($i = 0; $i < sizeof($array_main[$val]); $i++) {
$this->array_check($array_main[$val][$i], $array_main, $k);
}
// $k++;
}
I've been trying to fix this erorr for quite some time with no luck . I would really appreciate any help possible .
thanks in advance
Move the global $array_ins; statement into the function.
Pass the variable $array_ins as a parameter to function
function array_check($val, $array_main, $k,$array_ins) {
}
and call the function
$this->array_check($id, $menus['parents'], $k,$array_ins);
or
function array_check($val, $array_main, $k) {
global $array_ins;
}
usage of global is not recommended in php check it here Are global variables in PHP considered bad practice? If so, why?
The global keyword should be used inside of functions so that the variable will refer to the value in the outer scope.
<?php
$a = 1;
$b = 2;
function Sum()
{
global $a, $b;
$b = $a + $b;
}
Sum();
echo $b; // 3
I have strict error reporting. I have to use isset and it make me to write long, repetitive chains of variables in PHP. I have sometimes to write code like this:
if (isset($my_object->an_array[$a_variable])):
$other_variable = $my_object->an_array[$a_variable];
else:
$other_variable = false;
endif;
or
if (isset($my_object->an_array[$a_variable])):
return $my_object->an_array[$a_variable];
endif;
Sometimes it is longer and more complicated. It isn't readable and take too much time to type. I'd like to get rid of it.
The question
Is there a way to write $my_object->an_array[$a_variable] only once?
You can write functions to encapsulate repetitive code:
function get_variable(array $array, $variable_name, $default_value=FALSE){
if( isset($array[$variable_name]) ){
return $array[$variable_name];
}else{
return $default_value;
}
}
Tweak to your needs.
In the end I have found two solutions.
I. There is operator # in PHP. It is very dangerous, tough.
http://www.php.net/manual/en/language.operators.errorcontrol.php
However, it is acceptable in my situation.
This is not a fatal error.
The value of undefined variable is defined as null. I'm fine with testing for this or using implicit conversions.
I can use $php_errormsg in extreme situations.
The code example:
$tmp = $false_object->property->property; #Throw notice
$tmp = $false_array['a_field']['a_field']; #Throw notice
$tmp = #$false_object->property->property; #Quiet
$tmp = #$false_array['a_field']['a_field']; #Quiet
echo $php_errormsg; #I can print that notice
The downside is I don't receive information about lack of quotes in brackets.
$a = array('e'=>false);
$tmp = $a[e]; #Throw notice
$tmp = #$a[e]; #Quiet
echo $php_errormsg; #This variable still works
II. It is possible to use operator &.
The value of undefined variable will be NULL too.
The $php_errormsg variable doesn't work for undefined variables.
I get notice for lack of quotes in brackets, though.
The code example:
$tmp = $false_object->property->property; #Throw notice
$tmp = $false_array['a_field']['a_field']; #Throw notice
$tmp = &$false_object->property->property; #Quiet
$tmp = &$false_array['a_field']['a_field']; #Quiet
var_dump($tmp); #NULL;
The lack of quotes problem:
$array = array('a_field'=>true);
$tmp = $array[a_field]; #Throw notice
$tmp = #$array[a_field]; #Quiet
$tmp = &$array[a_field]; #Throw notice
function check($var)
{
if(isset[$var])
return $var;
else
return "";
}
Then each time you need to do checking call like:
$other_b = check($b);
I doubt you will get any suggestions that you will consider satisfactory. The best I can suggest is this, and I would add that I consider it quite ugly:
function ifset ($var) {
return is_null($var) ? false : $var;
}
Having defined this function, you can call it like this:
$other_variable = ifset(#$my_object->an_array[$a_variable]);
Note that you need the error suppression operator here, because otherwise you'll get an undefined variable notice if the variable indeed doesn't exist. (The reason why you don't need it for isset() is that isset() is really a special parser token rather than an ordinary function.)
now i get the same problem. i must check it and then get it ,it's so ugrly.
so i write the function like this
function get_val($arr,$key,$default_val=false){
if(!is_array($arr)) return $default_val;
$idx = explode('>>',$key);
$tmp = $arr;
$catched = true;
foreach($idx as $index) {
if(!isset($tmp[$index])){
$catched = false;
break;
}else{
$tmp = $tmp[$index];
}
}
if($catched) $default_val = $tmp;
return $default_val;
}
//for example
$arr = array('k1'=>array('k2'=>array(1,'k22'=>22,'k23'=>array('k3'=>1))));
get_val($arr,'k1>>k2>>k23>>k3');
A method to extract those variables would probably be better in your case, then:
class MyObject
{
private $an_array;
public function __construct()
{
$this->an_array = array();
}
public function get( $key )
{
if(isset($this->an_array[$key]))
return $this->an_array[$key];
return false; //or empty string
}
public function set( $key, $value )
{
$this->an_array[$key] = $value;
}
}
That way, you can do it like this:
$my_object->get($a_variable]);
I use these little helper functions to access properties of (multidimensional) arrays/objects without writing repetitive isset() statements. They might not be the fastest running solution, but they are very comfortable:
// AI(data,1,default) === data[1] or default
function AI( $a, $i, $d=null ){
if( is_array ($a)){ if( array_key_exists( $i, $a )) return $a[ $i ]; return $d; }
if( is_object($a)){ if( property_exists( $a, $i )) return $a -> $i; return $d; }
return $d;
}
// AII(data,1,2,3) === data[1][2][3] or null
function AII( $o ){
$a = func_get_args();
$al = func_num_args();
for( $i=1; $i < $al; $i++ ){
$k = $a[$i];
if( is_array ($o) && array_key_exists($k,$o)) $o =& $o[ $k ];
else if( is_object($o) && property_exists ($o,$k)) $o =& $o -> $k;
else return null; // nothing to access
}
return $o;
}
// AIID(data,1,2,3,default) == data[1][2][3] or default
function AIID( $o ){
$a = func_get_args();
$default = end( $a );
$al = count( $a ) - 1;
for( $i=1; $i < $al; $i++ ){
$k = $a[$i];
if( is_array ($o) && array_key_exists($k,$o)) $o =& $o[ $k ];
else if( is_object($o) && property_exists ($o,$k)) $o =& $o -> $k;
else return $default;
}
return $o;
}
// AAID(data,[1,2,3],default) == data[1][2][3] or default
function AAID( $o, $a, $default = null ){
foreach( $a as $k ){
if( is_array ($o) && array_key_exists($k,$o)) $o =& $o[ $k ];
else if( is_object($o) && property_exists ($o,$k)) $o =& $o -> $k;
else return $default;
}
return $o;
}
How Can I get the string that present the variable in function argument?
example
function dbg($param){
return "param";
}
$var="Hello World";
echo dgb($var);
output: var
$arr=array();
echo dgb($arr);
output: arr
It is NOT possible to do what you ask reliably.
The closest you can come up to doing that is to do a debug_backtrace() to check which file called the function then tokenize the source of that file to find the reference.
Again, this will not work reliably. It will fail if you have multiple calls on one line. Truthfully, it isn't work the trouble. You are writing the code anyway, you know which variable you are passing.
function dbg($var) {
$bt = debug_backtrace();
$file = $bt[0]['file'];
$line = $bt[0]['line'];
$source = file_get_contents($file);
$tmpTokens = token_get_all($source);
$tokens = array ();
foreach ($tmpTokens as $token) {
if (is_array($token) && $token[0] !== T_INLINE_HTML && $token[0] !== T_WHITESPACE) {
$tokens[] = $token;
}
}
unset($tmpTokens);
$countTokens = count($tokens);
for ($i = 0; $i < $countTokens; $i++) {
if ($tokens[$i][3] > $line || $i === $countTokens - 1) {
$x = $i - (($tokens[$i][3] > $line) ? 1 : 0);
for ($x; $x >= 0; $x--) {
if ($tokens[$x][0] === T_STRING && $tokens[$x][1] === __FUNCTION__) {
if ($x !== $countTokens - 1 && $tokens[$x + 1][0] === T_VARIABLE) {
return $tokens[$x + 1][1];
}
}
}
}
}
return null;
}
printing a variable, you're doing it wrong.
the right ways is like this:
function dbg($param){
return $param;
}
$var="Hello World";
echo dgb($var);
and by the way you're passing an array to a function that only accepts variables. and oh it's a null array all the way worse!
I'm just guessing that you're trying to make a custom debugger which as a nice touch prints the name of the variable you're debugging. Well, that's not really possible. I'd suggest you look at debug_backtrace, which allows you to print the file, line number, function name and arguments of the place where you invoked your dbg function. Unless you use dbg more than once per line that helps you find the information you're looking for, and IMO is a lot more useful anyway.
Alternatively, you can have both the name and value of your variable if you call your function like this:
function dbg($var) {
echo 'name: ' . key($var) . ', value: ' . current($var);
}
$foo = 'bar';
dbg(compact('foo'));
You question doesnt make much sense, you may want to reword it.
It sounds like you want to use the $param in the function in which case you can just do something link echo $param;