how to turn associative array into function parameters in php - php

Is there a way to turn an associative array into parameters for a function.
I have a simply array such:
$arr = [
'id' => 321654,
'name' => 'action1'
];
I have a static function in a class:
class someclass{
static function someFunction( $id, $name ){
//the rest of the method
}
}
I can call the class by variables, eg:
$class = 'someclass';
$method = 'somFunction';
return $class::$method( );
I can also pass is in a definite qty of function parameters, or an array
return $class::$method( $arr );
In this example's case I could hard code the params to:
return $class::$method( $arr['id'], $arr['name'] );
But how would i pass an unknown qty of keys. Another run may contain 1 key or 4 or 10...

Thanks to #Rizier123 comment:
This worked very nicely:
call_user_func_array( ''.$class.'::'.$method, $arr );

Related

How to set default value for assocc array function argument in PHP?

How to correctly write default value for assocc array function argument?
function foo($arr['key']='value');
<?php
function foo($arr = null)
{
if (is_null($arr))
{
$arr = array(
'key' => 'value'
);
}
...
You cant use the direct way you tried above. Just work with this little workaround
Else you might go with this:
function foo($a = array('key' => 'value'))
{
...
But in my opinion its a bit unhandy to declare an array in the function head. Its purely on you how you want to use it

PHP Parse an arrays values to a function

Ok so I have a function with 2 mandatory arguments and then it must have many optional arguments too.
function example($a,$b, $username, $email) {
// code
}
My data for the optional arguments comes from an array
$x = array('joeblogs', 'joe#blogs.com');
How would i be able to parse these? bearing in mind that the function may be required to parse a different set of arguments each time.
An example is with CakePHP you can specify the action arguments that are required
Something like this?
$a = 'a';
$b = 'b';
$x = array('joeblogs', 'joe#blogs.com');
$args = array_merge(array($a, $b), $x);
call_user_func_array('example', $args);
See http://php.net/manual/en/function.call-user-func-array.php
There are two approaches to optional arguments.
In the first, you specify all of the arguments like this:
function example($a, $b, $c=null, $d=null, $e=null)
Parameters $a and $b are required. The others are optional and are null if nothing is provided. This method requires that each of the optional parameters be specified in the indicated order. If you want to call the method using only $a, $b and $e you have to provide null values for $c and $d:
example($a, $b, null, null, $d);
The second method accepts an array as the third parameter. This array will be checked for keys and processed based on the keys found:
function example($a, $b, $c=array()) {
$optionalParam1 = ( !empty( $c['param1'] ) ) : $c['param1'] ? null;
$optionalParam2 = ( !empty( $c['param2'] ) ) : $c['param2'] ? null;
In this way, you can check for each key that may be provided. Null values will be provided for any key not populated.
Following shows syntax for optional parameters and default values
function example($a,$b, $username = '', $email = '') {
}
Another possibility is to pass an "optional values array"
function example($a,$b, $optional_values = array()) {
if($optional_values[0] != '') { blah blah .... }
}
This solution is a merge of your sugestion and Jez's solution.
call_user_func_array(array($controller, $action), $getVars);
Where $controller is the instance of your controller, $action is the string to the action that you want to call, and $getVars is an array of parameters.
The first parameter of the call_user_func_array function is a callback. It's possible to define a method invocation as callback.
Here is a link to the documentation of PHP's callback: http://www.php.net/manual/pt_BR/language.pseudo-types.php#language.types.callback
To pass the array parameters to a function you can use call_user_func_array:
$args = array( 'foo', 'bar', 'joeblogs', 'joe#blogs.com' );
call_user_func_array( 'example', $args );
Or simple pass any number of parameters:
example( $a, $b, $username, $email );
To retrieve the parameters inside function use func_get_args:
function example() {
$args = func_get_args();
print_r( $args );
// output:
// Array (
// [0] => foo
// [1] => bar
// [2] => joeblogs
// [3] => joe#blogs.com
// )
}

Dynamically call Class with variable number of parameters in the constructor

I know that it is possible to call a function with a variable number of parameters with call_user_func_array() found here -> http://php.net/manual/en/function.call-user-func-array.php . What I want to do is nearly identical, but instead of a function, I want to call a PHP class with a variable number of parameters in it's constructor.
It would work something like the below, but I won't know the number of parameters, so I won't know how to instantiate the class.
<?php
//The class name will be pulled dynamically from another source
$myClass = '\Some\Dynamically\Generated\Class';
//The parameters will also be pulled from another source, for simplicity I
//have used two parameters. There could be 0, 1, 2, N, ... parameters
$myParameters = array ('dynamicparam1', 'dynamicparam2');
//The instantiated class needs to be called with 0, 1, 2, N, ... parameters
//not just two parameters.
$myClassInstance = new $myClass($myParameters[0], $myParameters[1]);
You can do the following using ReflectionClass
$myClass = '\Some\Dynamically\Generated\a';
$myParameters = array ('dynamicparam1', 'dynamicparam2');
$reflection = new \ReflectionClass($myClass);
$myClassInstance = $reflection->newInstanceArgs($myParameters);
PHP manual: http://www.php.net/manual/en/reflectionclass.newinstanceargs.php
Edit:
In php 5.6 you can achieve this with Argument unpacking.
$myClass = '\Some\Dynamically\Generated\a';
$myParameters = ['dynamicparam1', 'dynamicparam2'];
$myClassInstance = new $myClass(...$myParameters);
I implement this approach a lot when function args are > 2, rather then end up with an Christmas list of arguments which must be in a specific order, I simply pass in an associative array. By passing in an associative array, I can check for necessary and optional args and handle missing values as needed. Something like:
class MyClass
{
protected $requiredArg1;
protected $optionalArg1;
public function __construct(array $options = array())
{
// Check for a necessary arg
if (!isset($options['requiredArg1'])) {
throw new Exception('Missing requiredArg1');
}
// Now I can just localize
$requiredArg1 = $options['requiredArg1'];
$optionalArg1 = (isset($options['optionalArg1'])) ? $options['optionalArg1'] : null;
// Now that you have localized args, do what you want
$this->requiredArg1 = $requiredArg1;
$this->optionalArg1 = $optionalArg1;
}
}
// Example call
$class = 'MyClass';
$array = array('requiredArg1' => 'Foo!', 'optionalArg1' => 'Bar!');
$instance = new $class($array);
var_dump($instance->getRequiredArg1());
var_dump($instance->getOptionalArg1());
I highly recommend using an associative array, however it is possible to use a 0-index array. You will have to be extremely careful when constructing the array and account for indices that have meaning, otherwise you will pass in an array with offset args and wreck havoc with your function.
You can do that using func_get_args().
class my_class {
function __construct( $first = NULL ) {
$params = func_get_args();
if( is_array( $first ) )
$params = $first;
// the $params array will contain the
// arguments passed to the child function
foreach( $params as $p )
echo "Param: $p\n";
}
}
function my_function() {
$instance = new my_class( func_get_args() );
}
echo "you can still create my_class instances like normal:";
$instance = new my_class( "one", "two", "three" );
echo "\n\n\n";
echo "but also through my_function:";
my_function( "one", "two", "three" );
Basically, you simply pass the result of func_get_args to the constructor of your class, and let it decide whether it is being called with an array of arguments from that function, or whether it is being called normally.
This code outputs
you can still create my_class instances like normal:
Param: one
Param: two
Param: three
but also through my_function:
Param: one
Param: two
Param: three
Hope that helps.
I've found here
Is there a call_user_func() equivalent to create a new class instance?
the example:
function createInstance($className, array $arguments = array())
{
if(class_exists($className)) {
return call_user_func_array(array(
new ReflectionClass($className), 'newInstance'),
$arguments);
}
return false;
}
But can somebody tell me if there is an example for classes with protected constructors?

strip null values of json object

All my AJAX requests are in json format which are being parsed in javascript.
How can i prevent null values being displayed in an HTML page without needing to write an if-statement in javascript for each json value?
Or should i write a custom PHP function to encode an array to json instead of using json_encode() so it doesn't display 'null' ?
In server side with PHP,
You can use array_filter before json_encode.
array_filter without second argument removes null elements of entry array, example :
$object= array(
0 => 'foo',
1 => false,
2 => -1,
3 => null,
4 => ''
);
$object = (object) array_filter((array) $object);
$result = json_encode($object);
The $result contains:
{"0":"foo","2":-1}
As you see, the null elements are removed.
I'm going to add to the accepted answer because that will only work if you have a 1 dimensional object or array. If there is any array or object nesting then in order to get the accepted solution to work, you must create some sort of recursive array filter. Not ideal.
The best solution my colleague and I came up with was to actually perform a regular expression on the JSON string before it was returned from the server.
$json = json_encode($complexObject);
echo preg_replace('/,\s*"[^"]+":null|"[^"]+":null,?/', '', $json);
The regular expression will remove all places in the string of the form ,"key":null including any whitespace between the leading comma and the start of the key. It will also match "key":null, afterwards to make sure that no null values were found at the beginning of a JSON object.
This isn't an ideal solution but it's far better than creating a recursive array filter given an object could be several dimensions deep. A better solution would be if json_encode had a flag that let you specify if you wanted null entries to remain in the output string.
To remove only NULL, but keep FALSE, '', and 0:
function is_not_null($var)
{
return !is_null($var);
}
echo json_encode(array_filter((array) $object, 'is_not_null'));
public function __toString() {
$obj = clone $this;
$keys = get_object_vars($obj);
foreach ($keys as $key => $value) {
if (!$value) {
unset($obj->{$key});
}
}
return json_encode($obj);
}
What about using the native JSON.stringify method on the javascript side?
You can set, a second parameter, a function to remove keys with a null value.
If you return undefined, the property is not included in the output JSON string (check the documentation for "the replacer parameter" at https://developer.mozilla.org/en-US/docs/Using_native_JSON#The_replacer_parameter).
function removeNulls(obj) {
var str = JSON.stringify(obj, function(key, val) {
if (val == null) return undefined;
return val;
});
return JSON.parse(str);
}
Then you can have a "normalized" JSON object by calling:
var obj = removeNulls(obj);
echo json_encode(array_filter((array) $object, function($val) {
return !empty($val);
}));
class Foo implements JsonSerializable
{
public $param1;
public $param2;
public function jsonSerialize()
{
return array_filter((array) $this, function ($var) {
return !is_null($var);
});
}
}
public function testJsonSerialization()
{
$expectedJson = '{"param1":true}';
$foo = new Foo();
$foo->param1 = true;
$foo->param2 = null;
$this->assertEquals(
$expectedJson,
json_encode($foo)
);
}`
of course you can create Abstract class with custom jsonSerialize method and extend all your DTOs from this
A version that works with multi-dimensional arrays.
$withoutNull = function($a) use (&$withoutNull) {
return array_filter(
array_map(
fn($p) => is_array($p) ? $withoutNull($p) : $p, $a
)
);
};
Example:
$a = [
"name" => "nathan",
"data" => [
"age" => 27,
"something" => null
],
"another" => null
];
$b = $withoutNull($a);
print_r($b);
Output:
Array
(
[name] => nathan
[data] => Array
(
[age] => 27
)
)

php - function to set var if it key exists in array, otherwise set to default

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.

Categories