I am trying to create a template system for a web site I am working on. I am trying to use preg_replace to call a function to process data that is surrounded by certain tags. For example, process('date') would return today's date, and is put in the code as $date$. I am using preg_replace to find the strings I need to modify, but I can not call the function - PHP seems to think that the function is a property instead.
This is the code I am using:
$view = preg_replace("/\$_([a-zA-Z0-9_]+)_\$/e", "$this->process('\\1')", $view);
This is the error I get:
Notice: Undefined property: ClassName::$process in /location/ClassName.class.php on line X
I hope I explained this sufficiently. How do I get preg_replace to execute process as a method, instead of trying to display it as a property?
I would suggest using preg_replace_callback instead of preg_replace seeing as preg_replace_callback is designed for what you are actually trying to do. A possible issue you could be having is scope/function accessibility. If your code that is calling preg_replace doesn't have access to the function you are trying to call, then you could be getting this error since PHP can't find the function and might be defaulting to treating it as an parameter. If the function isn't in the same file as this preg_replace, try putting it there to see if it changes anything.
Related
Is there any way to easily fix this issue or do I really need to rewrite all the legacy code?
PHP Fatal error: Call-time pass-by-reference has been removed in ... on line 30
This happens everywhere as variables are passed into functions as references throughout the code.
You should be denoting the call by reference in the function definition, not the actual call. Since PHP started showing the deprecation errors in version 5.3, I would say it would be a good idea to rewrite the code.
From the documentation:
There is no reference sign on a function call - only on function definitions. Function definitions alone are enough to correctly pass the argument by reference. As of PHP 5.3.0, you will get a warning saying that "call-time pass-by-reference" is deprecated when you use & in foo(&$a);.
For example, instead of using:
// Wrong way!
myFunc(&$arg); # Deprecated pass-by-reference argument
function myFunc($arg) { }
Use:
// Right way!
myFunc($var); # pass-by-value argument
function myFunc(&$arg) { }
For anyone who, like me, reads this because they need to update a giant legacy project to 5.6: as the answers here point out, there is no quick fix: you really do need to find each occurrence of the problem manually, and fix it.
The most convenient way I found to find all problematic lines in a project (short of using a full-blown static code analyzer, which is very accurate but I don't know any that take you to the correct position in the editor right away) was using Visual Studio Code, which has a nice PHP linter built in, and its search feature which allows searching by Regex. (Of course, you can use any IDE/Code editor for this that does PHP linting and Regex searches.)
Using this regex:
^(?!.*function).*(\&\$)
it is possible to search project-wide for the occurrence of &$ only in lines that are not a function definition.
This still turns up a lot of false positives, but it does make the job easier.
VSCode's search results browser makes walking through and finding the offending lines super easy: you just click through each result, and look out for those that the linter underlines red. Those you need to fix.
PHP and references are somewhat unintuitive. If used appropriately references in the right places can provide large performance improvements or avoid very ugly workarounds and unusual code.
The following will produce an error:
function f(&$v){$v = true;}
f(&$v);
function f($v){$v = true;}
f(&$v);
None of these have to fail as they could follow the rules below but have no doubt been removed or disabled to prevent a lot of legacy confusion.
If they did work, both involve a redundant conversion to reference and the second also involves a redundant conversion back to a scoped contained variable.
The second one used to be possible allowing a reference to be passed to code that wasn't intended to work with references. This is extremely ugly for maintainability.
This will do nothing:
function f($v){$v = true;}
$r = &$v;
f($r);
More specifically, it turns the reference back into a normal variable as you have not asked for a reference.
This will work:
function f(&$v){$v = true;}
f($v);
This sees that you are passing a non-reference but want a reference so turns it into a reference.
What this means is that you can't pass a reference to a function where a reference is not explicitly asked for making it one of the few areas where PHP is strict on passing types or in this case more of a meta type.
If you need more dynamic behaviour this will work:
function f(&$v){$v = true;}
$v = array(false,false,false);
$r = &$v[1];
f($r);
Here it sees that you want a reference and already have a reference so leaves it alone. It may also chain the reference but I doubt this.
I am trying to make my own template engine, (Don't ask why!)
And will try making:
{{#Form::input("name")}}
In my rendering system i'll make this eval code:
preg_match_all('/\{\{\#(.*?)\}\}/is',$data,$output);
$out="";
foreach ( $output[1] as $variables):
$find = '{{#' . $variables . '}}';
$data = str_replace($find, eval($variables), $data);
endforeach;
But i am getting this error
Parse error: syntax error, unexpected $end in /home/psafari/public_html/slt/classes/template.class.php(43) : eval()'d code on line 1
It should run "Form::input('something')" as specificed in the template engine. What am i doing wrong?
Despite the already uber-relevant comments against building a new templating engine, I'd suggest breaking the string found. Taking your example of {{#Form::input("name")}}, you'd have {{#CLASS_NAME::FUNCTION_NAME(params)}}. So using regex you could break the found string (as you already do), create an instance of or reference the class detected, then call the method parsed using a dynamic call (and obviously fail/error if either is not found).
As for the parameters, you could avoid qualifiers (quotes in this case) and break on every comma, or use the qualifiers and parse it differently via regex again. Your call. For each parameter parsed and found, they'd be added to the function call. In order to avoid eval, and given the fact PHP does not support a random number of arguments (such as Python does with args and kwargs), having an array as the single parameter for the functions you'll use on the template files.
You could also have sort of an 'interface' function that accepts a certain number of parameters that then receives the function (or class + function names), counts the number of parameters it finds and finally relays the call to the actual underlying function based on the correct number of parameters found. Though the more you add the more obscure the processing becomes - assuming users of your templating engine will be able to define new template methods, it's a very bad idea to use this second route (as you'd have to support up to N parameters on these interface functions).
YES. I searched google for any answers.
I am learning php. I am trying to send email using some php code that has this eval line.
eval("job();");
But getting error:
eval()'d code on line 1
Any advice?
Don't use eval(). It's evil.
Assuming job is a function, you can call job() directly.
job();
If job() returns a value, you can assign it to use later, as needed.
$variable = job();
Either call the function directly (if you know the name - judging by your snippet, you do) or, if you don't know what function needs to be called (it depends on a variable value or something, try using call_user_func or similar functions.Also make sure the function exists with function_exists, for example
There's a whole bunch of functions, built into PHP that allows you not to use eval... just spend some time browsing through the docs
I have the following code, that works for smarty 2.x
{assign var=somename value=jsFunction($frontItemKey);}
but smarty v3 throws an error:
unknown function "jsFunction"
How can I fix this?
Thanks!
What are you trying to achieve, to assign a string "jsFunction($frontItemKey)" to a variable? Or to put there the return value of some function?
In first case, which seems more possible, I think you just need should handle it as a string, because Smarty is definitely trying to call a function by that name and can't find it.
If you want a string like "jsFunction(VALUE)" where value is the $frontItemKey value, you should concatenate it.
In second case, if Smarty2 puts some value there, I would first check your Smarty2 source code, probably somebody changed it and added this function. Take a look at the Smarty libs folder.
I'm just starting to learn PHP and am using the W3 Schools tut. In the error handling section there is this code:
<?php
function customError($errno,$errstr) {
echo '<b>Error:</b> [$errno] $errstr<br />';
}
set_error_handler('customError');
echo($test);
?>
Why is the customError() function being passed as a string? Is this a mistake in the tut?
Also, why isnt $test defined?
Why is the customError() function being passed as a string?
For the same reason that usort or ob_start take strings for function specifiers. PHP just needs the name of the function. A function name not enclosed in quotes with either try being executed as a constant or (if followed by parenthesis) will be executed and the result passed to the function.
Because of the way PHP parses documents for execution, you have to work within the means of the language (use strings instead of "pointers" to function calls).
Also, why isnt $test defined?
This is a purposeful call to trigger an error. They are trying to get you to work with an undefined variable so an error occurs and the code you just wrote (with the custom handling) catches the error.
No, it's not an error. It's not so common, but some standard PHP functions accept functions name as parameter when you have to pass a function for same reason. set-error-handler is one of these function.
If you are curios about that, you can read here:
http://it2.php.net/manual/en/language.pseudo-types.php#language.types.callback(dead link)
The set_error_handler method takes a string as its first parameter -> http://php.net/manual/en/function.set-error-handler.php this is the function invoked for errors
The echo($test) causes an error to be thrown thus invoking the customError function
Because customError is not actually being passed as a string, per se, but rather its name is being passed as a string to PHP. See http://php.net/manual/en/function.set-error-handler.php , it allows you to specify a custom error handler function to PHP.