I can't seem to find anything of this, and was wondering if it's possible to store a function or function reference as a value for an array element. For e.g.
array("someFunc" => &x(), "anotherFunc" => $this->anotherFunc())
Thanks!
You can "reference" any function. A function reference is not a reference in the sense of "address in memory" or something. It's merely the name of the function.
<?php
$functions = array(
'regular' => 'strlen',
'class_function' => array('ClassName', 'functionName'),
'object_method' => array($object, 'methodName'),
'closure' => function($foo) {
return $foo;
},
);
// while this works
$functions['regular']();
// this doesn't
$functions['class_function']();
// to make this work across the board, you'll need either
call_user_func($functions['object_method'], $arg1, $arg2, $arg3);
// or
call_user_func_array($functions['object_method'], array($arg1, $arg2, $arg3));
PHP supports the concept of variable functions, so you can do something like this:
function foo() { echo "bar"; }
$array = array('fun' => 'foo');
$array['fun']();
Yout can check more examples in manual.
Yes, you can:
$array = array(
'func' => function($var) { return $var * 2; },
);
var_dump($array['func'](2));
This does, of course, require PHP anonymous function support, which arrived with PHP version 5.3.0. This is going to leave you with quite unreadable code though.
check out PHP's call_user_func. consider the below example.
consider two functions
function a($param)
{
return $param;
}
function b($param)
{
return $param;
}
$array = array('a' => 'first function param', 'b' => 'second function param');
now if you want to execute all the function in a sequence you can do it with a loop.
foreach($array as $functionName => $param) {
call_user_func($functioName, $param);
}
plus array can hold any data type, be it function call, nested arrays, object, string, integer etc. etc.
Is there a way to view the variables set in each stack frame in a backtrace? I can come pretty close with a combination of debug_backtrace(true) to get the objects, get_object_vars on each object to get $this vars, the args key in each backtrace frame, and get_defined_vars to get globals, but any temporary variables set within a function I can't find a way to retrieve.
Here's an example situation:
function method1($foo) {
$temp = method2($foo + 1);
foreach ($temp as $t) {
method2($t);
}
}
function method2($bar) {
$temp2 = $bar->value + $_GET['val'];
debug();
}
function debug() {
// to be created
$global_scope = get_defined_vars();
$bt = debug_backtrace(true);
}
I can get $foo and $bar via the args key in the backtrace, the object variables of $bar through get_object_vars, and the globals through get_defined_vars. I want to get the value of $temp2 and $temp as well.
Install and Enable XDebug on your (local) server. Then use xdebug_get_declared_vars(). Make sure that you set xdebug.collect_vars to On in your xdebug .ini file.
Example:
<?php
class strings {
static function fix_strings($a, $b) {
foreach ($b as $item) {
}
var_dump(xdebug_get_declared_vars());
}
}
strings::fix_strings(array(1,2,3), array(4,5,6));
?>
Returns:
array
0 => string 'a' (length=1)
1 => string 'b' (length=1)
2 => string 'item' (length=4)
Example from xdebug.org
Note, that the function only returns variables in the scope where the function xdebug_get_declared_vars() is called in.
Alter your debug to take 1 param. Then just pass in get_defined_vars. This will give you an array of all the vars in the local scope.
So I've got a class that I'd like to have it just set defaults if they're not passed in. For example, I can pass it an array called $options.
function new_score($options)
{
}
Then I'd like to have a different function that I can set a var to a default if a key with that var's name doesn't exist in the $options array;
The function definition could look like this:
function _set(&$key, $options, $default)
{
}
I know there's array_key_exists(), and I guess I'm sort of looking for a way to access the variables name.
For example:
$apple = 'orange';
How can I get the string 'apple', so I can look for that key? I know I could take the function _set() and have it look for $key, $var, $options, and $default, but I'd rather abstract it further.
function method($options)
{
//First, set an array of defaults:
$defaults = array( "something" => "default value",
"something_else" => "another default");
//Second, merge the defaults with the $options received:
$options = array_merge($defaults, $options);
//Now you have an array with the received values or defaults if value not received.
echo($options["something"]);
//If you wish, you can import variables into local scope with "extract()"
//but it's better not to do this...
extract($options);
echo($something);
}
References:
http://ar.php.net/manual/en/function.array-merge.php
http://ar.php.net/manual/en/function.extract.php
there's two ways of doing this:
One at a time with the ternary operator:
$key = isset($array['foo']) ? $array['foo'] : 'default';
Or, as an array as a whole:
$defaults = array('foo' => 'bar', 'other' => 'default value');
$array = $array + $defaults;
How about this:
class Configurable
{
private static $defaults = array (
'propertyOne'=>'defaultOne',
'propertyTwo'=>'defaultTwo'
);
private $options;
public function __construct ($options)
{
$this->options = array_merge (self::$defaults, $options);
}
}
From the documentation for array_merge:
If the input arrays have the same
string keys, then the later value for
that key will overwrite the previous
one.
This failed:
define('DEFAULT_ROLES', array('guy', 'development team'));
Apparently, constants can't hold arrays. What is the best way to get around this?
define('DEFAULT_ROLES', 'guy|development team');
//...
$default = explode('|', DEFAULT_ROLES);
This seems like unnecessary effort.
Since PHP 5.6, you can declare an array constant with const:
<?php
const DEFAULT_ROLES = array('guy', 'development team');
The short syntax works too, as you'd expect:
<?php
const DEFAULT_ROLES = ['guy', 'development team'];
If you have PHP 7, you can finally use define(), just as you had first tried:
<?php
define('DEFAULT_ROLES', array('guy', 'development team'));
PHP 5.6+ introduced const arrays - see Andrea Faulds' answer.
You can also serialize your array and then put it into the constant:
# define constant, serialize array
define ("FRUITS", serialize (array ("apple", "cherry", "banana")));
# use it
$my_fruits = unserialize (FRUITS);
You can store them as static variables of a class:
class Constants {
public static $array = array('guy', 'development team');
}
# Warning: array can be changed lateron, so this is not a real constant value:
Constants::$array[] = 'newValue';
If you don't like the idea that the array can be changed by others, a getter might help:
class Constants {
private static $array = array('guy', 'development team');
public static function getArray() {
return self::$array;
}
}
$constantArray = Constants::getArray();
EDIT
Since PHP5.4, it is even possible to access array values without the need for intermediate variables, i.e. the following works:
$x = Constants::getArray()['index'];
If you are using PHP 5.6 or above, use Andrea Faulds answer
I am using it like this. I hope, it will help others.
config.php
class app{
private static $options = array(
'app_id' => 'hello',
);
public static function config($key){
return self::$options[$key];
}
}
In file, where I need constants.
require('config.php');
print_r(app::config('app_id'));
This is what I use. It is similar to the example provided by soulmerge, but this way you can get the full array or just a single value in the array.
class Constants {
private static $array = array(0 => 'apple', 1 => 'orange');
public static function getArray($index = false) {
return $index !== false ? self::$array[$index] : self::$array;
}
}
Use it like this:
Constants::getArray(); // Full array
// OR
Constants::getArray(1); // Value of 1 which is 'orange'
You can store it as a JSON string in a constant. And application point of view, JSON can be useful in other cases.
define ("FRUITS", json_encode(array ("apple", "cherry", "banana")));
$fruits = json_decode (FRUITS);
var_dump($fruits);
PHP 7+
As of PHP 7, you can just use the define() function to define a constant array :
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // outputs "cat"
I know it's a bit old question, but here is my solution:
<?php
class Constant {
private $data = [];
public function define($constant, $value) {
if (!isset($this->data[$constant])) {
$this->data[$constant] = $value;
} else {
trigger_error("Cannot redefine constant $constant", E_USER_WARNING);
}
}
public function __get($constant) {
if (isset($this->data[$constant])) {
return $this->data[$constant];
} else {
trigger_error("Use of undefined constant $constant - assumed '$constant'", E_USER_NOTICE);
return $constant;
}
}
public function __set($constant,$value) {
$this->define($constant, $value);
}
}
$const = new Constant;
I defined it because I needed to store objects and arrays in constants so I installed also runkit to php so I could make the $const variable superglobal.
You can use it as $const->define("my_constant",array("my","values")); or just $const->my_constant = array("my","values");
To get the value just simply call $const->my_constant;
Yes, You can define an array as constant. From PHP 5.6 onwards, it is possible to define a constant as a scalar expression, and it is also possible to define an array constant. It is possible to define constants as a resource, but it should be avoided, as it can cause unexpected results.
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
// Works as of PHP 5.6.0
const ANOTHER_CONST = CONSTANT.'; Goodbye World';
echo ANOTHER_CONST;
const ANIMALS = array('dog', 'cat', 'bird');
echo ANIMALS[1]; // outputs "cat"
// Works as of PHP 7
define('ANIMALS', array(
'dog',
'cat',
'bird'
));
echo ANIMALS[1]; // outputs "cat"
?>
With the reference of this link
Have a happy coding.
Can even work with Associative Arrays.. for example in a class.
class Test {
const
CAN = [
"can bark", "can meow", "can fly"
],
ANIMALS = [
self::CAN[0] => "dog",
self::CAN[1] => "cat",
self::CAN[2] => "bird"
];
static function noParameter() {
return self::ANIMALS[self::CAN[0]];
}
static function withParameter($which, $animal) {
return "who {$which}? a {$animal}.";
}
}
echo Test::noParameter() . "s " . Test::CAN[0] . ".<br>";
echo Test::withParameter(
array_keys(Test::ANIMALS)[2], Test::ANIMALS["can fly"]
);
// dogs can bark.
// who can fly? a bird.
if you're using PHP 7 & 7+, you can use fetch like this as well
define('TEAM', ['guy', 'development team']);
echo TEAM[0];
// output from system will be "guy"
Using explode and implode function we can improvise a solution :
$array = array('lastname', 'email', 'phone');
define('DEFAULT_ROLES', implode (',' , $array));
echo explode(',' ,DEFAULT_ROLES ) [1];
This will echo email.
If you want it to optimize it more you can define 2 functions to do the repetitive things for you like this :
//function to define constant
function custom_define ($const , $array) {
define($const, implode (',' , $array));
}
//function to access constant
function return_by_index ($index,$const = DEFAULT_ROLES) {
$explodedResult = explode(',' ,$const ) [$index];
if (isset ($explodedResult))
return explode(',' ,$const ) [$index] ;
}
Hope that helps . Happy coding .
Doing some sort of ser/deser or encode/decode trick seems ugly and requires you to remember what exactly you did when you are trying to use the constant. I think the class private static variable with accessor is a decent solution, but I'll do you one better. Just have a public static getter method that returns the definition of the constant array. This requires a minimum of extra code and the array definition cannot be accidentally modified.
class UserRoles {
public static function getDefaultRoles() {
return array('guy', 'development team');
}
}
initMyRoles( UserRoles::getDefaultRoles() );
If you want to really make it look like a defined constant you could give it an all caps name, but then it would be confusing to remember to add the '()' parentheses after the name.
class UserRoles {
public static function DEFAULT_ROLES() { return array('guy', 'development team'); }
}
//but, then the extra () looks weird...
initMyRoles( UserRoles::DEFAULT_ROLES() );
I suppose you could make the method global to be closer to the define() functionality you were asking for, but you really should scope the constant name anyhow and avoid globals.
You can define like this
define('GENERIC_DOMAIN',json_encode(array(
'gmail.com','gmail.co.in','yahoo.com'
)));
$domains = json_decode(GENERIC_DOMAIN);
var_dump($domains);
Constants can only contain scalar values, I suggest you store the serialization (or JSON encoded representation) of the array.
If you are looking this from 2009, and you don't like AbstractSingletonFactoryGenerators, here are a few other options.
Remember, arrays are "copied" when assigned, or in this case, returned, so you are practically getting the same array every time. (See copy-on-write behaviour of arrays in PHP.)
function FRUITS_ARRAY(){
return array('chicken', 'mushroom', 'dirt');
}
function FRUITS_ARRAY(){
static $array = array('chicken', 'mushroom', 'dirt');
return $array;
}
function WHAT_ANIMAL( $key ){
static $array = (
'Merrick' => 'Elephant',
'Sprague' => 'Skeleton',
'Shaun' => 'Sheep',
);
return $array[ $key ];
}
function ANIMAL( $key = null ){
static $array = (
'Merrick' => 'Elephant',
'Sprague' => 'Skeleton',
'Shaun' => 'Sheep',
);
return $key !== null ? $array[ $key ] : $array;
}