It seems some people hate global variables, but if you can explain how to code without them, I'm all ears.
Otherwise, I have a few options and I'm curious which is the best long-term. Consider that I have a variable that won't change for the duration. It's a static global. I can use:
$_SESSION['var'] = constantval;
define('var', constantval);
var = constantval;
and the one I'm really curious about:
function my_constants($which)
{
switch ($which) {
case 'var':
return 'constantval';
}
}
In that last one, the goal is to keep variable out of global scope to save memory at the sacrifice of some processor cost. Is the memory saved worth the cycles? Is there a noteworthy difference between the various other types of global declaration?
Global variables are not considered a bad practice because of memory usage or processor cost. It's because of the problems that allowing any part of your program to modify them may cause. With the time, it becomes hard to understand which parts of the program read or write to your global variables.
Alternatives to globals (singetons).
It will give you a fine grained access control:
E.g.:
class ConfigParamSingelton {
private var $value;
private static $mInstance = null;
public function getValue() {
return $this->value;
}
public function getInstance() {
if(self::$mInstance == null) {
self::$mInstance = new ConfigParamSingelton();
}
return self::$mInstance;
}
So now you can either:
protected function setValue($val) { // is immuteable by clients of the object
$this->value = $val;
}
or
public function setValue($val) {// is muteable
$this->value = $val;
}
Well, this are singletons. You don't need globals in this case.
Related
Which approach is considered best practice?
Declare and check null...
class Foo {
$bar = null;
function test() {
return $this->bar != null;
}
}
Or, isset(...)...
class Foo {
function test() {
return isset($this->bar);
}
}
It makes a lot more sense to declare all the properties your class has, and check what their values are. It gives you a clear sense of what the class can do and what values it may have, rather than guessing every step of the way what property some other function may be looking for sometime later.
class Foo {
protected $bar = null;
public function test() {
return $this->bar !== null;
}
}
Note the !== check here; if you'd just use != the condition would be true for a number of other values besides just null.
It really is the exact same thing as any other variables in your code: you should always initialise any and all variables your code will work with, and then just worry about their values. isset should be used exclusively for cases where you have no control over the existence of a variable, e.g. as is the case for user input. For any other situation where you have perfect control over the existence or non-existence of your variable, opt for explicitly initialising them.
I need a single value of a unique type, similar to C#'s DBNull.Value.
I'm experimenting with how I might implement this in PHP. Here's what I've come up with so far:
class Wild {
public static $value;
private function __construct() {}
}
call_user_func(function () {
$r = new ReflectionClass(Wild::class);
Wild::$value = $r->newInstanceWithoutConstructor();
});
Now I can access my singleton easily via Wild::$value. The problem is that anyone can re-assign Wild::$value to something else at any time, and that would break the entire API. Is there any way to prevent this?
N.B. The constructor is private to prevent accidental instantiation. The closure is prevent $r from leaking out because it's in global scope.
class Wild {
private function __construct() {}
public static function value() {
static $value;
if($value === null) $value = new self;
return $value;
}
}
It's not quite the same, but it's probably less hacky than using reflection anyway.
I have a loop which will make calls to the function. Variables are defined (and reassigned on each iteration) in the first loop which are required for the function to function.
Loop:
if ($something) {
while (!$recordSet->EOF) {
$variable1 = TRUE;
$variable2 = FALSE;
...
function1()
}
}
Function:
function function1() {
if ($variable1 && !$variable2) {
...
}
}
The variables will have boolean values, and the environment is limited to PHP 4.
I'm currently considering using global $variable1; in the while loop and function1, but I know globals are almost always frowned upon.
Usually I'd use define("variable1","a value"), but the values will be changed multiple times.
Any suggestions, or is global defining the best solution in this case?
Thanks.
EDIT: Totally forgot to mention. This file is actually a spaghetti legacy code, and function1 is called in a hundred different places, all with varying bits of information. Otherwise, I would have used arguments.
In the main scope, define global $variable1 and global $varible2.
Also do it in the function.
But this is the worst solution. You will confuse, if these variables changes somewhere else.
The best way I think is to refactore your code, and pass varables as parameters.
The other solution could be create a class for these 2 variables, and set/get them statically.
class variablesPlaceHolder {
private static $variable1;
private static $variable2;
public static function getVariable1() {
return self::$variable1;
}
public static function getVariable2() {
return self::$variable2;
}
public static function setVariable1($variable1) {
self::$variable1 = $variable1;
}
public static function setVariable2($variable2) {
self::$variable2 = $variable2;
}
}
And the include this class in file, where you want to use them, and call variablesPlaceHolder::setVariable1(anyValue) variablesPlaceHolder::getVariable1()
Can I have two methods sharing the same name, but with different arguments?
One would be public static and would take 2 arguments, the other one just public and takes only one argument
example
class product{
protected
$product_id;
public function __construct($product_id){
$this->product_id = $product_id;
}
public static function getPrice($product_id, $currency){
...
}
public function getPrice($currency){
...
}
}
No. PHP does not support classic overloading. (It does implement something else that is called overloading.)
You can get the same result by using func_get_args() and it's related functions though:
function ech()
{
$a = func_get_args();
for( $t=0;$t<count($a); $t++ )
{
echo $a[$t];
}
}
I'm just giving you the super lazy option:
function __call($name, $args) {
$name = $name . "_" . implode("_", array_map("gettype", $args)));
return call_user_func_array(array($this, $name), $args);
}
That would for example invoke the real function name getPrice_string_array for two parameters of that type. That's sort of what languages with real method signature overloading support would do behind the scenes.
Even lazier would be just counting the arguments:
function __callStatic($name, $args) {
$name = $name . "_" . count($args);
return call_user_func_array(array($this, $name), $args);
}
That would invoke getPrice_1 for 1 argument, or getPrice_2 for, you guessed it, two arguments. This might already suffice for most use cases. Of course you can combine both alternatives, or make it more clever by search for all alternative real method names.
If you want to keep your API pretty and user-friendly implementing such elaborate workarounds is acceptable. Very much so.
PHP currently doesn't support overloading in known way, but you can still achieve your goal by using magic methods.
From PHP5 manual: overloading.
You could, kind of...
I consider it very much "hack" solutions, but you could make a single function and assign a standard value, that wouldn't otherwise be okay to use, to the parameters as needed. Then if you do not pass the function a certain parameter, it will be set to fx "-1".
public function getPrice($product_id = "-1", $currency) {
if($product_id = "-1") {
//do something
}else {
//do something
}
}
Or if you really need one method to be static, you can make a method that evaluates which method to call and call that instead of your getPrice:
public function whichGetPrice($product_id = "-1", $currency) {
if($product !== "-1") {
getStaticPrice($product_id, $currency);
}else {
getPrice($currency);
}
}
Like I said, very much "hack" solutions. It's not exactly pretty, nor a way people would expect you to do it. So I wouldn't necessarily recommend it, but it can help you do what you want.
In JavaScript, you can use Lazy Function Definitions to optimize the 2nd - Nth call to a function by performing the expensive one-time operations only on the first call to the function.
I'd like to do the same sort of thing in PHP 5, but redefining a function is not allowed, nor is overloading a function.
Effectively what I'd like to do is like the following, only optimized so the 2nd - Nth calls (say 25-100) don't need to re-check if they are the first call.
$called = false;
function foo($param_1){
global $called;
if($called == false){
doExpensiveStuff($param_1);
$called = true;
}
echo '<b>'.$param_1.'</b>';
}
PS I've thought about using an include_once() or require_once() as the first line in the function to execute the external code just once, but I've heard that these too are expensive.
Any Ideas? or is there a better way to tackle this?
Use a local static var:
function foo() {
static $called = false;
if ($called == false) {
$called = true;
expensive_stuff();
}
}
Avoid using a global for this. It clutters the global namespace and makes the function less encapsulated. If other places besides the innards of the function need to know if it's been called, then it'd be worth it to put this function inside a class like Alan Storm indicated.
Have you actually profiled this code? I'm doubtful that an extra boolean test is going to have any measurable impact on page rendering time.
you can do conditional function definiton.
if( !function_exists('baz') )
{
function baz( $args ){
echo $args;
}
}
But at present, a function becomes a brick when defined.
You can use create_function, but I would suggest you DONT because it is slow, uses lots of memory, doesn't get free()'d untill php exits, and is a security hole as big as eval().
Wait till PHP5.3, where we have "closures" http://wiki.php.net/rfc/closures
Then you'll be permitted to do
if( !isset( $baz ) )
{
$baz = function( $args )
{
echo $args;
}
}
$baz('hello');
$baz = function( $args )
{
echo $args + "world";
}
$baz('hello');
Upon further reading, this is the effect you want.
$fname = 'f_first';
function f_first( $even )
{
global $fname;
doExpensiveStuff();
$fname = 'f_others';
$fname( $even );
/* code */
}
function f_others( $odd )
{
print "<b>".$odd."</b>";
}
foreach( $blah as $i=>$v )
{
$fname($v);
}
It'll do what you want, but the call might be a bit more expensive than a normal function call.
In PHP5.3 This should be valid too:
$func = function( $x ) use ( $func )
{
doexpensive();
$func = function( $y )
{
print "<b>".$y."</b>";
}
$func($x);
}
foreach( range(1..200) as $i=>$v )
{
$func( $v );
}
( Personally, I think of course that all these neat tricks are going to be epically slower than your earlier comparison of 2 positive bits. ;) )
If you're really concerned about getting the best speed everywhere
$data = // some array structure
doslowthing();
foreach( $data as $i => $v )
{
// code here
}
You may not be able to do that however, but you've not given enough scope to clarify. If you can do that however, then well, simple answers are often the best :)
Please don't use include() or include_once(), unless you don't care if the include() fails. If you're including code, then you care. Always use require_once().
If you do wind up finding that an extra boolean test is going to be too expensive, you can set a variable to the name of a function and call it:
$func = "foo";
function foo()
{
global $func;
$func = "bar";
echo "expensive stuff";
};
function bar()
{
echo "do nothing, i guess";
};
for($i=0; $i<5; $i++)
{
$func();
}
Give that a shot
PHP doesn't have lexical scope, so you can't do what you want with a function. However, PHP has classes, which conceptually works in exactly the same way for this purpose.
In javascript, you would do:
var cache = null;
function doStuff() {
if (cache == null) {
cache = doExpensiveStuff();
}
return cache;
}
With classes (In PHP), you would do:
class StuffDoer {
function doStuff() {
if ($this->cache == null) {
$this->cache = $this->doExpensiveStuff();
}
return $this->cache;
}
}
Yes, class-based oop is more verbose than functional programming, but performance-wise they should be about similar.
All that aside, PHP 5.3 will probably get lexical scope/closure support, so when that comes out you can write in a more fluent functional-programming style. See the PHP rfc-wiki for a detailed description of this feature.
How about using local static variables?
function doStuff($param1) {
static $called = false;
if (!$called) {
doExpensiveStuff($param1);
$called = true;
}
// do the rest
}
If you need to do expensive stuff only once for given parameter value, you could use an array buffer:
function doStuff($param1) {
static $buffer = array();
if (!array_key_exists($param1, $buffer)) {
doExpensiveStuff($param1);
$buffer[$param1] = true;
}
// do the rest
}
Local static variables are persistent across function calls. They remember the value after return.
Any reason you're commited to a functional style pattern? Despite having anonymous functions and plans for closure, PHP really isn't a functional language. It seems like a class and object would be the better solution here.
Class SomeClass{
protected $whatever_called;
function __construct(){
$this->called = false;
}
public function whatever(){
if(!$this->whatever_called){
//expensive stuff
$this->whatever_called = true;
}
//rest of the function
}
}
If you wanted to get fancy you could use the magic methods to avoid having to predefine the called booleans. If you don't want to instantiate an object, go static.