Alternative for eval() -PHP - php

i am trying to implement URL mapping in PHP. I have a json file which stores the url and functions which is to execute when that link is requested. I was using eval() but then i came across this
Kepp the following Quote in mind:
If eval() is the answer, you're almost certainly asking the wrong
question. -- Rasmus Lerdorf, BDFL of PHP
now i am thinking is their any other(better) way to do it.
My json file looks like this.
{
"bw/":"main()",
"bw/login":"login()"
}
and my loadPage function look like this.
function loadPage($url){ //$url = 'bw/'
$str = file_get_contents('urls.json');
$this->link = json_decode($str, true);
$url = ltrim($url,"/");
$key = $this->link[$url];
eval("$key;");
}
EDIT:
i defined $this->link in my code

A slight tweak to your JSON to allow you to call the function dynamically would make it easier, just remove the brackets so it would look like...
{
"bw/":"main",
"bw/login":"login"
}
and then call it using...
function loadPage($url){ //$url = 'bw/'
$url = ltrim($url,"/");
$key = $this->link[$url];
$key();
}

A little better way is changing eval() to:
if (function_exists($key)) {
return $key();
}
return default();
and you might create a function "default" to show an error 404 or default page when function doesn't exists.

Related

How can I call $content = str_replace PHP function

Long short, I have a function that is responsible for executing specific data from my database, but the problem is I can't use that function. To be more clear:
This is the function
function ReplaceHTMLCode_Database($content){
$content = str_replace('{SELECT_CHAR}',GetPlayerSelect(),$content);
}
function GetPlayerSelect(){
$QUERY = mysqli_fetch_array(mysqli_query( ConnectiShopDb(),
"SELECT * from ".ISHOP_MYSQL_DB.".select_char where account_id=('".$_SESSION['ISHOP_SESSION_ID']."')"
));
if($QUERY['pid_id']){
return GetPlayerInfo($QUERY['pid_id'],'name').
"(".GetPlayerRaceByJob(GetPlayerInfo($QUERY['pid_id'],'job')).")";
} else {
return "{NO_CHARACTER_LABEL}";
}
}
I hope that I'm not being vague, But I tried selected="selected">{"SELECT_CHAR"}</option> in my PHP form that is supposed to be displaying this function and it's just being displayed as $SELECT_CHAR. I'm aware that this may be part of WordPress code since
I googled how to use ReplaceHTMLCode_Database and figured out it's pretty much something to do with WP, but I'm not using WordPress or any different CMS. Any help is so much appreciated!
Your function isn't returning or changing the variable. It would need to either do this:
function ReplaceHTMLCode_Database(&$content){
$content = str_replace('{SELECT_CHAR}',GetPlayerSelect(),$content);
}
This takes the variable by reference and changes it. You could then use it like so:
ReplaceHTMLCode_Database($content);
Otherwise, you could do this:
function ReplaceHTMLCode_Database($content){
return str_replace('{SELECT_CHAR}',GetPlayerSelect(),$content);
}
Which returns a new value that you could assign somewhere, like this:
$content = ReplaceHTMLCode_Database($content);
Your ReplaceHTMLCode_Database doesn't return anything. Could it be a simple
function ReplaceHTMLCode_Database($content){
return str_replace('{SELECT_CHAR}',GetPlayerSelect(),$content);
}
Please give some information about what the function should do.

Is it possible to get the statements within a method in PHP?

function mainFunction() {
functionA(5, "blah");
functionB("ok", "whatever");
}
How to write a function GetFunctions that returns the functions within mainFunction?
How to call them with the parameters given in mainFunction?
How to call them as follows?
foreach (GetFunctions(mainFunction) as $function) {
print "Calling function $function: ";
call($functionA); // called with parameters(5, "blah")
}
Working in PHP 5.2.8
EDIT: OK, here's a more complete explanation. I tried to keep it simple to make it easy to understand, but apparently that wasn't a good idea.
The goal is to call each assertion within a given static method. I am writing a testing framework. Each assertion returns true or false.
I am calling the methods as follows.
$methods = get_class_methods('LibraryTests');
foreach ($methods as $method) {
if ( StartsWith($method, 'Test') ) {
print "calling: " . $method . ": ";
call_user_func('LibraryTests::' . $method);
}
}
The above code calls each method within the class, but I want to call each assertion individually and track the result (true/false). CallAssertion is supposed to call each assertion (such as TestUnit::AssertEqual(GetFormattedHour(5), "5 PM");). This is the method that I am asking about.
Here is the class:
class LibraryTests extends TestUnit {
static $success = 0;
static $failure = 0;
static $total = 0;
static function CallAssertion($assertion) {
self::$total += 1;
if ($assertion) { self::$success += 1; }
else { self::$failure += 1; }
}
static function TestGetFormattedHour() {
TestUnit::AssertEqual(GetFormattedHour(5), "5 PM");
TestUnit::AssertEqual(GetFormattedHour(16), "4 PM");
}
So, the question is, how to write CallAssertion?
You can't.
Instead, create a class and use reflection to get its methods.
Regardless, you'll want to figure out why this is necessary and see if there is an entirely different approach you can use.
(If this is for debugging purposes, you can use debug_backtrace to inspect but its purpose is not for calling functions as you have described in your question.)
Hmm, what problem are you actually trying to solve. To me it sounds like you're trying to inspect the call stack at runtime. If so, I'd suggest just using debug_backtrace() (src).
I wouldn't suggest using that function in production as much though, as it's a rather heavy hit on your code.
One possibility would be to do a file_get_contents on the PHP file that contains main_function, then go through it to parse out main_function and the functions it calls. Of course, I don't know your situation so that might not work.
You can do this with:
http://php.net/manual/en/function.token-get-all.php
Probably a bad idea, but good luck!

Is it possible for PHP to write additional PHP functions like a Lisp macro?

I'm writing a unit testing platform and I want to be able to dynamically generate a function based off of each function in the web service I am testing. The dynamic function would be generated with default(correct) values for each argument in the web service and allow them to be easily traded out with incorrect values for error testing.
$arrayOfDefVals = array(123, 'foo');
testFunctionGenerator('function1', $arrayOfDefVals);
//resulting php code:
function1Test($expectedOutput, $arg1=123, $arg2='foo')
{
try
{
$out = function1($arg1, $arg2);
if($expectedOutput === $out)
return true;
else
return $out;
}
catch ($e)
{
return $e;
}
}
This would allow me to quickly and cleanly pass one bad argument, or any number of bad arguments, at a time to test all of the error catching in the web service.
My main question is:
Is this even possible with php?
If it's not possible, is there an alternative?
EDIT: I'm not looking for a unit test, I'm trying to learn by doing. I'm not looking for advice on this code example, it's just a quick example of what I would like to do. I just want to know if it's possible.
I would not try that first as PHP has not build-in macro support. But probably something in that direction:
function function1($param1, $param2)
{
return sprintf("param1: %d, param2: '%s'\n", $param1, $param2);
}
/* Macro: basically a port of your macro as a function */
$testFunctionGenerator = function($callback, array $defVals = array())
{
$defVals = array_values($defVals); // list, not hash
return function() use ($callback, $defVals)
{
$callArgs = func_get_args();
$expectedOutput = array_shift($callArgs);
$callArgs += $defVals;
return $expectedOutput == call_user_func_array($callback, $callArgs);
};
};
/* Use */
$arrayOfDefVals = array(123, 'foo');
$function1Test = $testFunctionGenerator('function1', $arrayOfDefVals);
var_dump($function1Test("param1: 456, param2: 'foo'\n", 456)); # bool(true)
Probably this is helpful, see Anonymous functions­Docs, func_get_args­Docs, the Union array operator­Docs and call_user_func_array­Docs.
Well, for starters, you can set default parameters in functions:
function function1Test($expectedOutput, $testArg1=123, $testArg2='foo') {
...
}
Beyond that, I'm not really sure what you're trying to achieve with this "function generator"...
Read about call_user_func and func_get_args
This example from the manual should get you on the right track:
<?php
call_user_func(function($arg) { print "[$arg]\n"; }, 'test'); /* As of PHP 5.3.0 */
?>
If it's a function you have file access to (i.e., it's not a part of the PHP standard library and you have permissions to read from the file), you could do something like this:
Assume we have a function like this located in some file. The file will have to be included (i.e., the function will have to be in PHP's internal symbol table):
function my_original_function($param1, $param2)
{
echo "$param1 $param2 \n";
}
Use the ReflectionFunction class to get details about that function and where it's defined: http://us2.php.net/manual/en/class.reflectionfunction.php.
$reflection = new ReflectionFunction('my_original_function');
Next, you can use the reflection instance to get the path to that file, the first/last line number of the function, and the parameters to the function:
$file_path = $reflection->getFileName();
$start_line = $reflection->getStartLine();
$end_line = $reflection->getEndLine();
$params = $reflection->getParameters();
Using these, you could:
read the function out of the file into a string
rewrite the first line to change the function name, using the known function name as a reference
rewrite the first line to alter the parameter defaults, using $params as a reference
write the altered function string to a file
include the file
Voila! You now have the new function available.
Depending on what it is you're actually trying to accomplish, you could also potentially just use ReflectionFunction::getClosure() to get an closure copy of the function, assign it to whatever variable you want, and define the parameters there. See: http://us.php.net/manual/en/functions.anonymous.php. Or you could instantiate multiple ReflectionFunctions and call ReflectionFunction::invoke()/invokeArgs() with the parameter set you want. See: http://us2.php.net/manual/en/reflectionfunction.invokeargs.php or http://us2.php.net/manual/en/reflectionfunction.invoke.php

Making Smarty supporting multiple languages

first of all, let me tell ya, that I'm from Germany. So my English will not be very well. Please forgive me. =P
I'm about to develop a multilingual website with PHP5. In order to seperate the presentation layer from the business logic, I'm using the SmartyTemplateEngine (v3.0.8). To make it multilingual I had to edit this SmartyPlugin sometimes. But finally it is working for me. I'm using it that way:
{lang}language.string{/lang}.
In the language file I have:
language.string = <![CDATA[Hello world!]]> (So it says Hello world!)
Works fine. But I want to expend the script a bit further. I want to pass a variable to the language string. Something like this:
{lang s=$userName}language.string{/lang}
In the language file I want to have:
language.string = <![CDATA[Hello %s!]]> (So it says Hello username!)
I tried to find my solution with Google, but I didn't find something good. As far as I'm not a professional in PHP, I'm not capable of editing it myself. I hope somebody can help me with that. It is bothering me quite a while...
Greets,
Basti
Well, I'm not using this plugin, but had to do the same thing. I figuered out that for my needs the following was the best solution:
In an XML file I define my strings (this example is xml/en/content.xml):
<translations>
<translation id="hello_world"><![CDATA[Hello ##username##!]]></translation>
<translation id="how_are_you"><![CDATA[How are you?]]></translation>
</translations>
In my Localizer class I initialize these translations and save them in an array. The translate function gets the ID string from smarty, searches for the id in its translations and for any ##string## text. These ##...## will be replaced with variables already assigned to smarty.
class Localizer {
private static $translations = array();
public static function init($language) {
$temp_content = simplexml_load_file('xml/' . $language . '/content.xml');
foreach ($temp_content as $key => $value){
self::$translations[(string)$value['id']] = (string)$value;
}
}
public static function translate($params, $name, $smarty) {
$translation = '';
if( ! is_null($name) && array_key_exists($name, self::$translations)) {
// get variables in translation text
$translation = self::$translations[$name];
preg_match_all('/##([^#]+)##/i', $translation, $vars, PREG_SET_ORDER);
// replace with assigned smarty values
foreach($vars as $var) {
$translation = str_replace($var[0], $smarty->getTemplateVars($var[1]), $translation);
}
}
return $translation;
}
}
Now you have to tell smarty which function it should use. This could be your index.php:
include('Localizer.class.php');
Localizer::init('en');
$smarty->registerPlugin('block', 'translate', array('Localizer', 'translate'), true);
To use the translations, first, I assign the username:
$smarty->assign('username', $username);
In the template file:
{translate}hello_world{/translate}
Hope this helps, greetings from austria :)

How to get the data in comments

as follow:
<?php
/*
* #I'm data
*/
function demo() {}
how to get "I'm data"?
thx
Well, if you are accessing it via the demo() function...
// #I'm Data
function demo(){
$script = file(__FILE__);
$comment = $script[__LINE__ - 5]; // 4 lines above, and 1 for arrays
$temp = explode("#", $comment);
return $temp[1];
}
If your code is inside a class, the correct way is to use reflection:
http://www.php.net/manual/en/reflectionclass.getdoccomment.php
There's no obvious way to do it -- your script is blissfully unaware of its own comments.
However, you could probably hack it by having your script read itself as data, and then parse out whatever you're looking for:
<?php
$my_own_source = file_get_contents(__FILE__);
//some code to pull out exactly what you want here.

Categories