PHP basic (noobish) concept question: Constant vs. Function - php

I have a global "functions.php" file containing functions used throughout my site.
In terms of performance, efficiency, etc – is it better to call one of these functions directly or to define them as constants and call the constant instead? (Or does it matter at all?)
ie
<?php echo site_root(); ?>
vs.
<?php echo SITEROOT; ?>
Thanks

It depends on what site_root() does exactly.
If all it does is something very simple like read from an array and return a string, it doesn't matter whether you use the function, or a constant. Use whatever works best for you.
If the function does something expensive like a database lookup, it is indeed wise to do the call only once, store the result in a constant, and use that in the code.

Adam, another option is to use static vars as a cache inside a function:
function site_root() {
static $result = null;
if (!is_null($result)) {
return $result;
}
// code for defining and returning result only once
}
You can use constants only when your code always require them. And if your code use it only here or there, then don`t use them, as code, that will define them will slow down your main code.

Related

PHP Global Variables Issue

I've got a scope problem here. and no idea why its not working, ive got a setup as follows:
functions.php
global $id;
$id = $_GET['id'];
index.php
require_once('functions.php');
echo $id;
now inside functions.php i can echo out $id. however my echo $id; inside index.php is bringing up blank. absolutely nothing.
what am i doing wrong?
In PHP, the global keyword allows you to reference variables in the global scope from inside a local scope - eg to access a global variable inside a function. You don't need global in your example, because you are in the global scope anyway.
I suspect you are showing us a simplified version of what you have, where the issue is in code you haven't shown us.
Why you shouldn't use globals
Confusion like this is part of why using globals is a bad idea and should be avoided.
The alternative is to pass variables around explicitly, so for example if you call a function or instantiate a class from another file, you pass the variable in as a parameter to that function or constructor. Doing this, instead of using global variables, makes it easier to follow what function is accessing what variable because you can follow the trail easier.
You don't need globals between files, only for functions.
Functions.php
<?php
$foobar = "Hello";
?>
Index.php
<?php
include('Functions.php');
echo $foobar;
?>
You shouldn't use globals, but you have it backwards. You declare the variable global after you include its definition:
file1.php:
$name = 'Josh';
file2.php:
require_once('file1.php');
global $name;
echo $name;
#thomasrutter is correct (+1) Global variables areA Bad Thing. Always seek alternatives.
Perhaps you can use $_SESSION (which sort of amounts to the same thing, I know), or declare a class which has a static variable and use a getter() and setter() ? (the latter uis definitely cleaner, but $_SESSION might tie in better with your design, I can't say)
Btw, I hope that functions.php was just an example name, or that you have an extermely simple project.
Otherwise fucntions.php is going to get extermaly large and hard to oversee. If you are going OO then user one file per class, otherwse try to group your functions into separate files (file_management.php, databse.php, forms.php and the like).
If you are just starting out, I would advise you to use Netbeans and document your code with PhpDoc comments which will allow you to generate good documentation which you can view in your browser (including the structure of your coed, what gets declared where, used where, descruptions of function parameters and return values, etc)
Btw, I notice that you use include() I prefer require_once. The _once helps spee dperformnce a little and hte require makes sure that you are aware of missing files more quickly.
Oh, and learn to use Xdebug, which plays well with NetBeans.

Get a called functions list in PHP

In PHP, get_included_files() returns an array with the names of included files.
In a similar fashion, is there any way to get an array with the names of called functions with parameters?
In this way, Is any way to get an array with the names of called functions with parameters?
No.
What you can do is a debug_backtrace() which will show all the function calls (with parameters) that lead to the execution of the line you are doing the backtrace from (the "call stack"), but that's different from all functions that were ever called in the script.
What do you want to do? Maybe there's a different approach.
I was searching for something similar and found xdebug's tracing very useful.
Here's an example of how it could look like:
http://devzone.zend.com/1135/tracing-php-applications-with-xdebug/
I was trying to achieve what you want and finally came up with an reasonable solution.
Make a class named Debug and include that above every file you want to debug in. Build yourself a function that prints nicely the information stored in $calls.
class Debug {
private static $calls;
public static function log($message = null)
{
if(!is_array(self::$calls))
self::$calls = array();
$call = debug_backtrace(false);
$call = (isset($call[1]))?$call[1]:$call[0];
$call['message'] = $message;
array_push(self::$calls, $call);
}
}
Call this function everytime you declare a function first line in the functionbody: Debug::log($message(optional) )
Not that I'm aware.
You can however use debug_backtrace to get the currently active function/method hierarchy.
I don't think there's a way to do what you want. Sorry.
The closest I can get is the function_exists() function, which will tell you whether a specific function has been loaded.
What exactly do you want to achieve here? I can't see a use case (outside of a php_info() type screen) that would require a list of available functions.
You will have to install it as an extension, but a profiler like XHProf will give you a breakdown of which functions are called and how long they take, as well as a callgraph.
XHProf or Webgrind/KCachegrind will show you the functions called, but not their parameters.
You could also use get_defined_functions, which gives you a list of all functions defined. But it won't show you which functions have actually been called, and with what parameters.
If you really need to know the parameters, I don't know of any tools other than a custom logger like the one Henze provided in his answer.

PHP best practices: repass variables from config file when calling functions or use global?

I have a program that I use on several sites. It uses require('config.php'); to set any site dependant variables like mysql connect info, paths, etc.
Let's say that I use one of these site-dependant variables in a function, like $backup_path.
This variable was initially declared in config.php, and does not appear in the main program file.
I need to access this variable in function makebackup($table_name); (also in a separate functions.php file).
Is it better to say
makebackup('my_table');
and then use "global $backup_path" inside the function, or is it better to call the function using
makebackup('my_table',$backup_path);
The argument for the first is that it keeps the main program flow simple and easy to understand, without clutter.
The argument for the second is that it might not be obvious that the variable $backup_path exists after some time has passed, and debugging or reworking could be difficult.
Is one or the other of these techniques "standard" among professional programmers? Or should I be using $_SESSION to declare these global variables?
The second alternative,
makebackup('my_table', $backup_path);
is a reusable function and therefore generally preferable. The extra argument is not a big price for reusability.
If you are entirely sure that you'll ever use that function in that particular application only, and for $backup_path only, then maybe consider the global alternative. Even then it's good to check that the global variable actually exists. And be aware that it's extremely difficult to get rid of globals once you start using them.
Remember that you can set a default value for your function:
function makebackup($table, $dir = CONFIG_BACKUP_PATH)
That way you won't have to supply the variable in the default case, you can simply assume that the configured backup path is the default.
This assumes that you are using constants, not global variables.
I'm think you must use Singleton of Factory class config for this purposes.
function makebackup($table)
{
$backup_path = ConfigFactory().getConfig($some_site_specific_data).getBackupPath()
mysqldump($table, $backup_path)
}
Passing references around is far easier to test (you can give mock configuration objects). Globals less so. You can assert that the reference is not null on the method. I would call testability best practice.
Label that global variable
Personally, I have also taken to marking global variables very clearly. If I must use them, I want to be clear about them.
So here, I'd rename $backup_path to $GLOBAL_backup_path. Every time I saw it, I'd know to be careful with it.
An alternative option is using php constants with define().
Your config.php will set constants for every parameter (mysql connection, css style, wathever). Then you will not need to pass variables to functions nor using global.
One downside is that you can define only booleans, floats, strings or integers, no complex data structures.
Not sure there's really a 'right' way to do it, but another option would be something like this:
function makebackup($table, $backup_path = '') {
if ( $backup_path == '' ) {
if ( isset($GLOBALS['backup_path']) ) {
$backup_path = $GLOBALS['backup_path'];
}
else {
die('No backup path provided');
}
}
}
That way you can either pass in the value (for testing and future use) or if you don't pass it in, then the function will look for a possible global variable.

DEFINE vs Variable in PHP

Can someone explain the difference between using
define('SOMETHING', true);
and
$SOMETHING = true;
And maybe the benefits between one or the other?
I use variables everywhere and even in a config type file that is included to everypage I still use variables as I don't see why to use the define method.
DEFINE makes a constant, and constants are global and can be used anywhere. They also cannot be redefined, which variables can be.
I normally use DEFINE for Configs because no one can mess with it after the fact, and I can check it anywhere without global-ling, making for easier checks.
Once defined, a 'constant' cannot be changed at runtime, whereas an ordinary variable assignment can.
Constants are better for things like configuration directives which should not be changed during execution. Furthermore, code is easier to read (and maintain & handover) if values which are meant to be constant are explicitly made so.
There is also a difference in scope.
In the example given by the orignal poster, $SOMETHING will not be accessible within a function whereas define('SOMETHING', true) will be.
define() makes a read-only variable, compared to a standard variable that supports read and write operations.
A constant is very useful when you want access data from inside a function, check this
<?php
function data(){
define("app","hey you can see me from outside the function",false);
$tech = "xampp";
}
data();
echo $tech;
echo app;
?>
If you use a variable you are never going to get the inside value here is what i get
Notice: Undefined variable: tech in D:\xampp\htdocs\data\index.php on line 8
hey you can see me from outside the function

"Namespaces", constants and multiple PHP includes

I have some PHP code similar to the following:
foreach ($settingsarray as $settingsfile)
{
include ($settingsfile);
// do stuff here
}
$settingsarray is an array of file names from a particular folder.
The problem is, that each $settingsfile defines constants (with the same names), which of course, can not be redefined.
What possible methods are there to prevent errors occurring in this situation?
Two options I can think of include, changing all the constants to variables and using PHP namespaces.
However, I'm not sure how I would go about using namespaces, it would require the declaration at the start of every $settingsfile? Is there a method of isolating constants, ariables and functions without using namespaces?
What I would really love, is to be able to do something as simple as:
foreach ($settingsarray as $settingsfile)
{
{//added braces to indicate where the isolation is
include ($settingsfile);
// do stuff here
}//what happens in here does not affect what happens outside of here
}
I should just note, this is part of a new feature, and is the only part of the code that loads all the $settingsfiles. The rest of the code only ever loads one file at a time. One reason I am using constants is so that I don't have to worry about defining variables "global" to be able to access them inside functions.
My answer is somewhat complex, but should work for you quite nicely. I'm assuming you have a ton of these settings files, since you're so averse to changing each one individually.
If you're able to use namespaces, I'll assume you've already upgraded to PHP 5.3RC2. Copy the following into a .php file, and change the namespace to your liking:
<?php
namespace myapp\config;
function define($key, $val) {
Config::set($key, $val);
}
class Config {
private $vars = array();
// This class should not be instantiated
private function __construct() {}
public function set($key, $val) {
self::$vars[$key] = $val;
}
public function get($key) {
return isset(self::$vars[$key]) ? self::$vars[$key] : NULL;
}
}
?>
Include that in your code, and now making everything work is a simple matter of changing the
<?php
in your settings files to
<?php namespace myapp\config;
If you have a ton of them, a quick 'sed' command in your terminal should take care of it quite nicely, all in one fell swoop.
If I lost you on how to use my code, here's an example:
<?php
require_once('the_php_file_i_just_gave_you.php');
use \myapp\config\Config;
foreach ($settingsarray as $settingsfile) {
include ($settingsfile);
$varname = 'key';
echo "In this file, '$varname' equals: " . Config::get($varname);
}
?>
Good luck!
Okay, so if I'm understanding you correctly, inside that loop you'd like to do things with the constants defined inside each $settingsfile and then basically get rid of them after each loop?
Unlike variables, a constant is a value that, once set, cannot be changed or unset during the execution of your script
src
Your only option is to change the define() declarations to variables.
not easy but you could read the php file with file_get_contents($settingsfile) then rewrite the constants, and eval the code.
$settingsstr = file_get_contents($settingsfile);
$settingsstr = preg_replace('/<\?\w*(.*)/', '\\1', $settingsstr);//get rid of the php open tag
$settingsstr = preg_replace('/define\("(\w+)"/', 'define("NAMESPACE_\\1"', $settingsstr);
eval($settingsstr);
You have a few options:
Use PHP Namespaces
Surprisingly, PHP actually does have support for namespaces. I was very surprised to find this since I have been working in PHP for years and have never heard of this feature. It is likely a newer feature and one that is not commonly used, so I would suggest not using this method
Use Class Constants
You could use classes and class constants to load your settings. Class constants are local to the defining class, so you will not need to worry about name collisions within the class. You would probably need to do more than include the file, but you could call a method on each class, such as defineConstants() or loadConfiguration() that would define the application constants, keeping the class constants for internal use.
Use Functions to Extend the Settings
Another idea is to create a settings array and separate functions to 'extend' those settings. That way you can over-write any configuration in subsequent functions without causing an error. Finally, if you want to put those in constants, you could loop over the array and use define() to define the constants.
There are many other ways to accomplish what you are trying to do, but these are just a few ideas.
A settings file should not contan PHP code.
It should be some kind of "standard" format.
http://www.php.net/parse_ini_file
In the first step (in your foreach) you read all files
Collect the variables into a temporary array
In another loop over this array, you can define them as constants.
If you routinely feel the need to "redefine constants" then something is amish in the application design.

Categories