First time I am trying to use the dynamic create_function, and up to now, not much success :-)
My function is this :
function o99_brsa_custom_widgets() {
global $wp_meta_boxes;
global $o99_brsa_options;
for($i=0; $i> count($o99_brsa_options[content]); $i++) {
$widgt_id = 'o99_dashboard_widget_dyn' . $i;
$widgt_name = 'obmek99 widget name' . $i;
$out = $o99_brsa_options[content][$i];
$f = create_function(' $out ',' global $out; echo $out;');
do_the_widgets($widgt_id, $widgt_name, $f);
}
}
The do_the_widgets() action is accepting only a direct echo and prints the content of the widget.
The $o99_brsa_options[content] is a verified array with $i elements (each is content) .
The strange thing is that the $i is working on the $widgt_id and $widgt_name but on the create_function() I get the same value printed in all widgets . ( echo $out )
It seems that I do not know how to pass a simple variable to the new function ( I am using global inside create_function(), but it helps little as for now .
So, what is my mistake / misunderstanding / misuse now :-) ??
create_function was during the stone age , when kaᵠ used pen and paper to write applications, when PeeHaa埽 got a beer because he wrote hello would, The world is better now please use closures
$f = function ($out) {
echo $out;
};
$f("Welcome");
You would thank me one day, But you can only use create_function if you are Gordon (The machine from the past sent here to torment us) he wrote this
$fn = create_function(
'$x',
'return $x; } $foo = 42; function foo($int) { return $int; '
);
See Live Demo
Related
I'Ve made a few test on global vs function parameter and the difference is futile.
But as i was testing stuff, i found that $GLOBALS is about 10% slower. than using function parameter or global keyword. Anyone care to explain why?
I wish to understand further the mechanism behind PHP. This so i can make better compromise on futur dev. Not that i ever use $GLOBALS except in some exception case.
$md5 = md5(1000000);
function byGlobal() {
global $md5;
$c = 0;
while( md5($c) != $md5 ){
$c++;
}
}
function superGlobal() {
$c = 0;
while( md5($c) != $GLOBALS[ 'md5' ] ){
$c++;
}
}
function asParam($md5) {
$c = 0;
while( md5($c) != $md5 ){
$c++;
}
}
$time3 = microtime(true);
asParam($md5);
echo (microtime(true) - $time3);
echo "<br/>";
$time1 = microtime(true);
byGlobal();
echo (microtime(true) - $time1);
echo "<br/>";
$time2 = microtime(true);
superGlobal();
echo (microtime(true) - $time2);
echo "<br/>";
I'm not arguing about function vs global or good practice. I really just wonder why so much difference. Ran the test 20 times and results are pretty much all consistent.
i move the calls up and down in the code to avoid caching influence.
I'm doing a million md5 iteration on each call so the server works a
load.
Time results are cosistent with other hashing function (tested sha1, crc32) and they are all in the same +10% slower)
Ran on a VM with PHP 5.4.16 on CentOs7.
1st run
as param : 0.8601s
as global : 0.8262s
as $GLOBALS : 0.9463s (more than 10% slower)
2nd run
as param : 0.8100s
as global : 0.8058s
as $GLOBALS : 0.9624s (more than 10% slower again)
Related studies : (mainely debate about global best practice, nothing about $GLOBALS vs global performance.
The advantage / disadvantage between global variables and function parameters in PHP?
php global variable overhead in a framework
Does using global create any overhead?
EDIT: New version, I made a mistake in the first one.
I've rewritten your tests, so it does test the things you want:
<?php
$value = 6235;
function byGlobal() {
global $value;
return $value++;
}
function superGlobal() {
return $GLOBALS['value']++;
}
function asParam($parameter) {
return $parameter++;
}
$time = microtime(true);
for ($i = 0;$i < 10000000;$i++) $value = asParam($value);
echo 'asParam: '.(microtime(true)-$time).'<br/>';
$time = microtime(true);
for ($i = 0;$i < 10000000;$i++) $value = byGlobal();
echo 'byGlobal: '.(microtime(true)-$time).'<br/>';
$time = microtime(true);
for ($i = 0;$i < 10000000;$i++) $value = superGlobal();
echo 'superGlobal: '.(microtime(true)-$time).'<br/>';
Example results for PHP 7.0.17 on CentOs7:
asParam: 0.43703699111938
byGlobal: 0.55213189125061
superGlobal: 0.70462608337402
and
asParam: 0.4569981098175
byGlobal: 0.55681920051575
superGlobal: 0.76146912574768
So, the superGlobal is the slowest, but not by that much. I guess the reason is that it is an array.
What I take away from this is that PHP is fast! I would not worry about the small differences in these tiny time slices. Having readable code is far more important. I my experiences the slowest thing in a website are the database queries.
My host suddenly changed something , and now my sites ( most wp - around 100 ) are getting the infamous error Invalid opcode 153/1/8
The line(s) responsible for it :
$f = function() use ($out) {
echo $out;
};
After 2 minutes of research it appears that the culprit is eAccelerator , which does not support anonymous functions
Both the following questions blamed the error on eAccelerator as well :
Invalide OpCode and php sort function,
https://stackoverflow.com/a/12085901/1244126
Fun fact : the same code was already before a subject of my own 2 questions here on SE and here , where I encountered a problem while using
anonymous functions with older PHP versions ( < 5.3 ) with create_function
$f = create_function(' $out ',' global $out; echo $out;');
So, my question is : how can I change my code in a manner that will avoid the eAccelerator bug AND will work on all php versions . ( it is unlikely that I can convince my host to change something on it´s side )
EDIT I :
For sake of clarity ( although might be slightly irrelevant - the the question is how to have a cross-compatible anonymous functions ) - I am posting the whole relevant code ...
if ( count( $content_widget ) > 0 ) { // avoid error when no widget...
$i=0;
foreach ( $content_widget as $wid ){
$out = null;
$i++;
$widg_id = 'o99_dashboard_widget_dyn_' . $i;
$widg_name = 'widget name - ' . $i;
$out = $wid;
// $f = create_function('$out','global $out;echo $out;');
// $f = create_function('', 'global $out; echo $out ;');
$f = function() use ($out) {
echo $out;
};
// function() use ($out) // NOPE
// $f = $f($out); // NOPE again
wp_add_dashboard_widget($widg_id, $widg_name, $f);
// $i++;
}
}
It is just a simple code to dynamically create dashboard widgets in wp admin area..
It seems that they are using call_user_func
So, you could create new object and pass callable array.
class s {
private $_out = null;
public function __construct($out){
$this->_out = $out;
}
public function a(){
echo $this->_out;
}
}
$function = array(new S('my out'), 'a');
var_dump(is_callable($function));
call_user_func($function);
The shortest way to echo out stuff in views in PHP - when not using template engines - is, afaik, this one:
<?php if (!empty($x)) echo $x; ?>
For a deeper explanaition why using !empty is a good choice please look here.
Is it possible to write this without writing the variable name twice (like in other languages), something like
!echo $x;
or
echo? $x;
echo #$x;
It's not exactly the right way to do it, but it is shorter.
it reduces the need to check if $x exists since # silences the error thrown when $x == null;
edit
echo empty($x) ? "" : $x;
is a shorter way, which is not really that much shorter nor does it solve your problem.
guess the other answers offer a better solution by addressing to make a short function for it.
Built in? No.
However - you could write your own wrapper function to do it:
$x = 'foobar';
myecho($x); // foobar
function myecho($x) {
echo !empty($x) ? $x : '';
}
This fits the bill of "only writing the variable once", but doesn't give you as much flexibility as the echo command does because this is a function that is using echo, so you can't do something like: myecho($x . ', '. $y) (the argument is now always defined and not empty once it hits myecho())
Easy approach would be to define an helper function so:
function mEcho($someVariable) {
if(!empty($someVariable) echo $someVariable;
}
I'm not sure though if that's what you intended.
Yes, you can write a function:
function echoIfNotEmpty($val) {
if (!empty($val)) {
echo $val;
}
}
Usage:
echoIfNotEmpty($x);
Sure you can shorten the function name.
If you don't know, if the var is intialized you can also do:
function echoIfNotEmpty(&$val = null) {
if (!empty($val)) {
echo $val;
}
}
Most times we want do prefix and append something
function echoIfNotEmpty(&$val = null, $prefix = '', $suffix = '') {
if (!empty($val)) {
echo $prefix . $val . $suffix;
}
}
echoIfNotEmpty($x, '<strong>', '</strong>');
So I have fields that are generated dynamically in a different page and then their results should posted to story.php page. fields is going to be : *noun1 *noun2 *noun3 and story is going to be : somebody is doing *noun1 etc. What I want to do is to replace *noun1 in the story with the *noun, I have posted from the previous page ( I have *noun1 posted from the previous page ) but the code below is not working :
$fields = $_POST['fields'];
$story = $_POST['story'];
$fieldsArray = split(' ', $fields);
for ($i = 0; $i < count($fieldsArray); $i++) {
${$fieldsArray[$i]} = $_POST[$fieldsArray[$i]];
}
// replace words in story with input
for ($i = 0; $i < count($story); $i++) {
$thisWord = $story[$i];
if ($thisWord[0] == '*')
$story[$i] = ${$thisWord.substring(1)};
}
$tokensArray = split(' ',$tokens);
echo $story;
Your problem is likely that you are trying to echo $story, which I gather is an array. You might have better luck with the following:
$storyString = '';
for ($i = 0; $i < count($story); $i++)
{
$storyString .= $story[i] . ' ';
}
echo $storyString;
echo can't print an array, but you can echo strings to your heart's content.
You almost certainly don't want variable variables (e.g. ${$fieldsArray[$i]}). Also, $thisWord.substring(1) looks like you're trying to invoke a method, but that's not what it does; . is for string concatenation. In PHP, strings aren't objects. Use the substr function to get a substring.
preg_replace_callback can replace all your code, but its use of higher order functions might be too much to get into right now. For example,
function sequence($arr) {
return function() {
static $i=0
$val = $arr[$i++];
$i %= count($arr);
return $val;
}
}
echo preg_replace_callback('/\*\w+/', sequence(array('Dog', 'man')), "*Man bites *dog.");
will produce "Dog bites man." Code sample requires PHP 5.3 for anonymous functions.
function getTemplate($tpl if ($vars) echo ", $vars";)...function
Is this possible somehow?
The above wont work.
Thanks
Optional arguments with default values
It looks like you want an optional argument, which you can accomplish by defining a default value in the function definition:
function getTemplate($tpl, $vars=null)
{
}
You can call this function as getTemplate($foo) or getTemplate($foo,$bar). See the PHP manual page on function arguments for more details.
Variable numbers of arguments
It's also possible to write functions which take a variable number of arguments, but you need to use func_num_args, func_get_arg and func_get_args functions to get at them. Here's an example from the manual
<?php
function foo()
{
$numargs = func_num_args();
echo "Number of arguments: $numargs<br />\n";
if ($numargs >= 2) {
echo "Second argument is: " . func_get_arg(1) . "<br />\n";
}
$arg_list = func_get_args();
for ($i = 0; $i < $numargs; $i++) {
echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
}
}
foo(1, 2, 3);
?>
Calling a function with a variable number of parameters
To round off this answer even more, suppose you'd build an array of 1..n values and wanted to pass it to the foo() function defined above? You'd use call_user_func_array
$values=(1,2,3,4);
call_user_func_array('foo', $values);
This is the equivalent of calling
foo(1,2,3,4);
What's so bad about
function getTemplate($tpl, $vars=null) {}
?
if ($vars) { getTemplate($tpl, $vars); }
else {{ getTemplate($tpl, null); }
(semi-pseudo code)
Or:
getTemplate($tpl, ($vars)?$vars:null); // not sure
getTemplate($tpl, (!empty($vars))?$vars:null);
Also, if you would like a technique similar to echo:
$code = "getTemplate($pl";
if ( $vars ) { $code = $code . ", $vars);"; }
else { $code = $code . ");"; }
$ret = eval($code);
Although this is usually considered bad practice (never say never).
Please note that all code sent to eval will be executed directly. So don't put user input in an eval() call.