Proper usage of constants in PHP - php

So I have recently learned about constants in PHP. fortunately there is not really anything to learn on them, they appear to be just an entity which stores value of something, just like a variable.
The only different that I can see (Correct me if I am wrong) is that a constant cannot be assigned a new value (that is it?). Which makes sense asthetically for example if you are making a config file with configurations that should not be changed.
But surely it brings other benefits/usage than just using a variable anyway?
In what situations should I be choosing to use constants?

If you find yourself setting a variable for convenience and never changing it during a script, the chances are you should be using a constant instead. Constants are like variables except that once they are defined they cannot be undefined or changed - they are constant as the name suggests. In many languages, constants are faster than variables and so are recommended, but this is not the case as much in PHP - although they are perhaps a small amount faster, the primary advantage to using constants is the fact that they do not have a dollar sign at the front, and so are visibly different from variables. Furthermore, constants are automatically global across your entire script, unlike variables.
To set a constant, use the define() function - it takes two parameters, with the first being the name of the constant to set, and the second being the value to which you wish to set it. For example, this following line of code sets the variable CURRENT_TIME to be the return value of the time() function, then prints it out:
define("CURRENT_TIME", time());
print CURRENT_TIME;
Note that it is not $CURRENT_TIME or Current_Time - constants, like variables, are case sensitive, but unlike variables they do not start with a dollar sign. You can change this behaviour by passing true as a third parameter to define(), which makes the constant case-insensitive:
define("CURRENT_TIME", time(), true);
print Current_TiMe;
There are two helpful functions available for working with constants, and these are defined() and constant(). The defined() function is basically the constant equivalent of isset(), as it returns true if the constant string you pass to it has been defined. For example:
define("CURRENT_TIME", time(), true);
if (defined("CURRENT_time")) {
/// etc }
Note that you should pass the constant name into defined() inside quotes.

A key characteristic of constants is that they behave like functions and classes, in the sense that they need to be defined when you try to use them, otherwise PHP will produce an error; and that they're global and unconcerned by scope. This makes them ideal for flags in function parameters, where the value is relatively unimportant, yet requires unique identification. Just look at how PHP itself uses constants:
json_encode($foo, JSON_UNESCAPED_UNICODE)
pathinfo($bar, PATHINFO_FILENAME)
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
What would the alternatives be?
$pdo->setAttribute('errmode', 'exception')
Strings cannot be checked for existence the same way constants can, typos are easier and require more manual error handling inside the function, and strings cannot be introspected the same way you can introspect PDO for its constants, and hence discoverability of available options is reduced.
$pdo->setAttribute(1, 2)
Magic numbers are obviously even worse, with even less meaning and the same lack of enforcement and discoverability.
In these cases, constants are ideal. They provide an enforced, readable identifier for a meaning; the actual value the constant holds is relatively unimportant.

Constants are for when someone else might read and try to install your code, but doesn't know what bits they should change to add their own details in. It's especially useful if you don't have an installation script, as the new admin will need to set their own details.
Example:
You need to install a new script on your website that uses a database of some kind. You'd open up the main file, and edit the constants that you need to add in your database connection details. Because they're constants, you know they shouldn't change - And they shouldn't, otherwise your database wouldn't work! If you use variables, the values could be accidentally changed in the script. It's also clearer to know which parts you have to change - and as they're usually at the start of a document or in a separate file easy to identify as well.

Related

Using underscores in global php variables

I'm planning to expose some common variables as globals in my script and am wondering if the following naming scheme would be considered bad ideas:
using single underscore at the beginning and end like: $_some_var_
using triple underscore at the beginning like: $___some_var
I know that php uses single underscore at the beginning for superglobals and double underscore for magic methods so there shouldn't be any conflicts. Is there anything else that could cause trouble? And is doing this considered bad for any other reason?
Thanks!
It won't cause any problems per say. For ease of typing you may just want to go with the single underscore.
In my app, if I must introduce such globals that I may use in many scripts both inside and outside of functions, I use the $GLOBALS superglobal so it is very apparent that the variable being accessed is a global.
This also saves having to use global $somevar; in functions. But it is a lot more typing depending on how often you use them.
Could the values possible be constants or are they actually variable?
If you really think you need global state, how about creating a static class instead?
class myVars {
static property $var1;
}
If they are to be treated as constants then use:
define("CONSTANT_NAME", value)
If they are truly global variables, then one convention is:
$mVariableName

Why C++11 and PHP closures require declaring the closed-over variables?

Function literals in both C++ and PHP require programmer to specify which variables they are using from the current lexical context. What's the reason behind this requirement?
I guess it's not meant for the compiler/interpreter, because one can statically infer this information from function literal's body. Is it only for drawing the reader's attention?
For C++11 at least, [=] () {...} will automatically pull in all and only those local variables which the function body uses. (Or, equally, [&]...)
You can specify individual variables to be captured by reference or by value if you have any specific needs beyond this catch-all.
In PHP, variables are created when their name is first used, so I expect the declaration is to make sure no new variables mask the old ones. A bit like the global keyword.
well can't say for php nor that i got your question 100% - but...in c++ variable total partakes in the lambda function closure. the major premise of this is that it can change its value, being a reference.

Global vs. Define

I have a php file in which I need to be able to easily flip a switch. The switch is set to 1 for local server and 0 for production server. local_on='1'; or local_on='0';. Which way is better (creating a global or using define)? If either way is good which way is best practice?
define. You can't change its value later, and its value is always available in all scopes, tersely.
A global variable is, as its name indicates, variable -- which means its value can be changed by any portion of your code ; which, in your case, is probably not what you want.
On the other hand, a constant (that you'll set with define) is... well... constant ; and, as such, cannot be modified once set ; which is probably what you want, in your case.
Considering the variable vs constant idea, for this kind of switches, I generally use define() and constants.
The define is the better choice of the two, because global variables are bad news for reasons I'm sure you're already familiar with, and because you have to remember to declare global $var in every function and method in your code. Defined constants are automatically available everywhere. Additionally, a variable could inadvertently be set from one state to the other during the running of your script. This could cause some really hard-to-find bugs if it happened.
Another way that performs a little better than define symbols and minimizes name clashes is a class declaration like
abstract config {
const LOCAL = true; // toggle to false
// or maybe
const SERVER = 'local'; // toggle to 'remote'
// (maybe having if (config.SERVER == 'remote') would be more readable in some
// cases than if (!config.LOCAL) depends on your app)
}
I prefer define. Reasons:
You can't redefine it accidentally
You can use in other scope (ex. functions) without ugly $GLOBALS construction
PS: since PHP 5.3 you can use const , not only define to declare constants. It's more readable for me
Both work fine as long as you remember to choose a distinctive name (all-uppercase for defines) and use the modern way to access global variables via the $GLOBALS superglobal (sic). Also, global variables are, well, variable, so you could, in theory, change its value by accident or so.
To simplify deployment and not setting or unsetting the switch by accident, I'd recommend automatically setting it automatically by examining the properties of $_SERVER, like
// Turn on debugging code on local machine
define('MYPAGE_LOCAL_ON', $_SERVER['SERVER_NAME'] == 'my-dev-box');
Also, I don't see why you'd set the switch to a string or an integer for that matter. The boolean values true and false seem more appropriate.
In short terms, define is what you look for (for said reasons).
However, come the future development, you might look for something like a dependency for your whole application providing the context it is running in. This can not be done with constants, so then define but as well as global variables are both wrong.

What can I use instead of eval()?

I have a string that stores some variables that must be executed to produce a result, for example:
define('RUN_THIS', '\$something.",".$somethingElse');
Which is then eval()-uated:
$foo = eval("return ".RUN_THIS.";");
I understand that eval is unsafe if the string that gets evaluated is from user input. However, if for example I wanted to have everything run off Facebook's HipHop which doesn't support eval() I couldn't do this.
Apparently I can use call_user_func() - is this effectively the same result as eval()? How is deemed to be secure when eval() isn't, if that is indeed the case?
Edit:
In response to the comments, I didn't originally make it clear what the goal is. The constant is defined in advance in order that later code, be it inside a class that has access to the configuration constants, or procedural code, can use it in order to evaluate the given string of variables. The variables that need to be evaluated can vary (completely different names, order, formatting) depending on the situation but it's run for the same purpose in the same way, which is why I currently have the string of variables set in a constant in this way. Technically, eval() is not unsafe as long as the config.php that defines the constants is controlled but that wasn't the point of the question.
Kendall seems to have a simple solution, but I'll try to answer your other question:
Apparently I can use call_user_func() - is this effectively the same result as eval()? How is deemed to be secure when eval() isn't, if that is indeed the case?
call_user_func is actually safer than eval because of the fact that call_user_func can only call one user function. eval on the other hand executes the string as PHP code itself. You can append '; (close the string and start a new "line" of code) at the end of the string and then add some more code, add a ;' (end the line of code and start another string so that there is no syntax error), thus allowing the constant RUN_THIS to contain lots of PHP code that the user can run on the server (including deleting all your important files and retrieving information for databases, etc. NEVER LET THIS HAPPEN.
call_user_func doesn't let his happen. When you run call_user_func_array($func, $args) the user can only run a restricted set of functions because: (a) the function has to be user defined (b) you can manipulate $func to ensure the user isn't able to run any function he/she wants either by checking that $func is in a list of "allowed functions" or by prefixing something like user_ to the function names and the $func variable itself (This way the user can run only functions beginning with user_.
I can't see any reason why you can't just use double-quote string building.
$foo = "\$something,$somethingElse";

PHP -What's the difference between global variables and constants

According to many sources, register_globals (global variables that is) should be disables in your php.ini.
Should I write define() in my code and use constants if global variables are disabled? Are those even related?
They are related in that they have global scope, but constants are meant to not change once defined, unlike global variables which the page can modify as it goes along. So just switching over to using define() instead of a global won't help much.
It's better if you refactor your methods to take the variables as parameters and rely on that to pass variables around.
Global variables aren't constant (you can change the value of a global variable, but you can only define a constant once).
Constants aren't always global (you can declare a constant in a class).
Also, global variables can be any type: scalar, array, or object. Constants can only be scalars.
I'm not going to say either constants or globals are good or bad. When used appropriately, they both have beneficial uses. There are security issues around the register_globals feature that are separate from more general use of globals.
A few things here.
First, the register_globals that you disable in your php.ini refers to an old PHP feature where any variable sent via a query string (GET) or form (GET/POST) would be converted into a global PHP variable. This is the functionality that is (and should be) disabled when you turn off register_globals. Even with this off, you can still define global variables in your application.
In general programming terms, global variables (not PHP's register_globals) are considered "bad" because when you encounter one as a programmer, you have no idea what other parts of the application might be using or changing it, or what effect your changes to that global might have. Also, if you're defining a new global variable, there's a chance you're going to overwriting an existing variable that someone else is relying on. When variables are defined locally (in a single function, or in other languages a single block) you can examine the local scope and usually determine what a change to that variable will do.
Constants, on the other hand, never change. You define them once, and they stay defined and no one can change them. That's why having global constants is considered "less bad" than having global variables.
Constants, once defined, cannot be changed.
Don't use constants as variables. If you need to use variables within functions, pass them into the function itself. Use everything in the way it was intended to be used. Variables are variable and Constants are constant.
Some constant examples:
<?php
// Certainly constant
define('MINUTES_PER_HOUR', 60);
define('DOZEN', 12);
// Constant, but specific to this application
define('GREETING', 'Dear %s');
define('TIMEOUT', 30);
// Configurable, but constant for this installation
define('DATABASE', 'mydb');
define('IMAGES_DIRECTORY', '/tmp/images');
// Not constant, or some other reason why can't be constant
$user = $_POST['userid'];
$days_of_week = array('Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su');
?>
Something else to consider -- constants can't store things like arrays or objects, whereas something defined to $GLOBALS can be any variable type. So in some cases, if you need something to be global but it can't be stored to a constant by using define(), you might want to use $GLOBALS instead.
Also, register_globals and $GLOBALS are NOT the same thing!
You can change the global variable inside the function if both have a same name, because local variable override the global variable but does not change the value of global variable outside.in constant if you want to use same name variable in different function that not allowed to you and give a error,because it define one time and used in all program and you can not change the value of this variable in any function or block it is fixed value .
Try this simple test:
fileA.php:
<?php
define('SOMEVAL', 2);
?>
fileB.php:
<?php
if(defined('SOMEVAL')) echo SOMEVAL;
else echo "SOMEVAL does not exists\n";
include 'fileA.php';
if(defined('SOMEVAL')) echo 'SOMEVAL='.SOMEVAL;
else echo "SOMEVAL does not exists\n";
?>
Then run fileB.php and you'll see that before you include fileA.php, SOMEVAL is not defined. So what this means is that before you define anything, it won't be visible to the script.

Categories