PHP function with variable as default value for a parameter - php

By default a PHP function uses $_GET variables. Sometimes this function should be called in an situation where $_GET is not set. In this case I will define the needed variables as parameter like: actionOne(234)
To get an abstract code I tried something like this:
function actionOne($id=$_GET["ID"])
which results in an error:
Parse error: syntax error, unexpected T_VARIABLE
Is it impossible to define an default parameter by using an variable?
Edit
The actionOne is called "directly" from an URL using the framework Yii. By handling the $_GET variables outside this function, I had to do this on an central component (even it is a simple, insignificant function) or I have to change the framework, what I don't like to do.
An other way to do this could be an dummy function (something like an pre-function), which is called by the URL. This "dummy" function handles the variable-issue and calls the actionOne($id).

No, this isn't possible, as stated on the Function arguments manual page:
The default value must be a constant
expression, not (for example) a
variable, a class member or a function
call.
Instead you could either simply pass in null as the default and update this within your function...
function actionOne($id=null) {
$id = isset($id) ? $id : $_GET['ID'];
....
}
...or (better still), simply provide $_GET['ID'] as the argument value when you don't have a specific ID to pass in. (i.e.: Handle this outside the function.)

function actionOne( $id=null ) {
if ($id === null) $id = $_GET['ID'];
}
But, i would probably do this outside of the function:
// This line would change, its just a for instance
$id = $id ? $id : $_GET['id'];
actionOne( $id );

You should get that id before you call the function. Checking for the existence of the parameter breaks encapsulation. You should do something like that:
if (isset($_GET["ID"])
{
$id = $_GET["ID"];
}
else
{
//$id = something else
}
function doSomethingWithID($id)
{
//do something
}

You could use constant variable
define('ID',$_GET["ID"]);
function($id = _ID_){
//code
}

Yes it is impossible.
The default has to be a static variable:
function actionOne( $id='something') {
//code
}

Easy peanuts! (Might contain minor mistakes, errors or typos!)
You need a helper function, which will call you main function recursively, but having NULL as default:
Wrong: function actionOne($id=$_GET["ID"])
Right:
function actionOne($id) {...}
function actionOnewithID($id=NULL) {
if (NULL==$id){actionOne($_GET["ID"]);}
else {actionOne($id);
}
And if you need to return a value:
function actionOne($id) {...}
function actionOnewithID($id=NULL) {
if (NULL==$id){return(actionOne($_GET["ID"]));}
else {return(actionOne($id));
}
I hope this helps!

shortest way is:
function actionOne($id = null)
{
$id = $id ?? $_GET["ID"];
...
}

Related

PHP - Pass arguments into function as array without having to define as parameters

Is there away to pass a variable (with array data) into a function without having to use as a parameter each time I want to use the function?
My situation is that I have producing UI elements for a form. Right now if I define the input's name I get the field which works as designed, but I also have to pass two variables every time.
Function Defined:
function getDecision($name,$game,$answer) {
// lots of code not very relevant
}
Ideally I want to pass the $game and $answer variables inside the function for what is dependent on them. I am using code igniter and the $game variable is passed to the view on load of the page. The $answer variable can be defined within function only if the $game has been passed or define.
Current use of the function:
getDecision('company_name', $game, $answer);
Ideal use of function (simpler use):
getDecision('company_name');
Let me know if there is anything else I need to define, I don't want to show all of the code because there is nearly 100 lines of code.
You could use global variables to do so. For example:
<?php
$array = array();
function test() {
global $array;
print_r($array);
}
function main() {
test();
}
main();
?>
http://php.net/manual/en/language.variables.scope.php
Although, it should be avoided.
Using closures for this would be a good option - http://php.net/manual/en/functions.anonymous.php, specifically the 'use' construct
#!/usr/bin/env php
<?php
function getDecision($name, $game, $answer) {
echo "$name : $game : $answer \n";
}
function main() {
$my_game = "my game";
$my_answer = "my answer";
$getDecisionCaller = function($name) use ($my_game, $my_answer) {
getDecision($name, $my_game, $my_answer);
};
// Don't really need the line below, can simply use: $getDecisionCaller('company 0');
getDecision('company 0', $my_game, $my_answer);
$getDecisionCaller('company 1');
$getDecisionCaller('company 2');
}
main();
?>
Will give the output
company 0 : my game : my answer
company 1 : my game : my answer
company 2 : my game : my answer
In the code above i define getDecision($name, $game, $answer) that simply prints out the values sent.
Then, i define getDecisionCaller that accepts only $name an an argument but uses the values of $my_game, $my_answer already defined.
Note - The 'use' construct needs variables to bind to, and you cannot set the values via a string. It will give the error - 'Parse error: parse error, expecting '&'' or"variable (T_VARIABLE)"''
eg. You cannot do the below
$getDecisionCaller = function($name) use ('a game', 'an answer') {
getDecision($name, $my_game, $my_answer);
};
Hopefully, that helped :)

PHP take string and check if that string exists as a variable

I have an interesting situation. I am using a form that is included on multiple pages (for simplicity and to reduce duplication) and this form in some areas is populated with values from a DB. However, not all of these values will always be present. For instance, I could be doing something to the effect of:
<?php echo set_value('first_name', $first_name); ?>
and this would work fine where the values exist, but $user is not always set, since they may be typing their name in for the first time. Yes you can do isset($first_name) && $first_name inside an if statement (shorthand or regular)
I am trying to write a helper function to check if a variable isset and if it's not null. I would ideally like to do something like varIsset('first_name'), where first_name is an actual variable name $first_name and the function would take in the string, turn it into the intended variable $first_name and check if it's set and not null. If it passes the requirements, then return that variables value (in this case 'test'). If it doesn't pass the requirements, meaining it's not set or is null, then the function would return '{blank}'.
I am using CodeIgniter if that helps, will be switching to Laravel in the somewhat near future. Any help is appreciated. Here is what I've put together so far, but to no avail.
function varIsset($var = '')
{
foreach (get_defined_vars() as $val) {
if ($val == $var) {
if (isset($val) && $val) {
echo $val;
}
break;
}
}
die;
}
Here is an example usage:
<?php
if (varIsset('user_id') == 100) {
// do something
}
?>
I would use arrays and check for array keys myself (or initialize all my variables...), but for your function you could use something like:
function varIsset($var)
{
global $$var;
return isset($$var) && !empty($$var);
}
Check out the manual on variable variables. You need to use global $$var; to get around the scope problem, so it's a bit of a nasty solution. See a working example here.
Edit: If you need the value returned, you could do something like:
function valueVar($var)
{
global $$var;
return (isset($$var) && !empty($$var)) ? $$var : NULL;
}
But to be honest, using variables like that when they might or might not exist seems a bit wrong to me.
It would be a better approach to introduce a context in which you want to search, e.g.:
function varIsset($name, array $context)
{
return !empty($context[$name]);
}
The context is then populated with your database results before rendering takes place. Btw, empty() has a small caveat with the string value "0"; in those cases it might be a better approach to use this logic:
return isset($context[$name]) && strlen($name);
Try:
<?php
function varIsset($string){
global $$string;
return empty($$string) ? 0 : 1;
}
$what = 'good';
echo 'what:'.varIsset('what').'; now:'.varIsset('now');
?>

Why can I not use $this in function arguments default value

I trying to pass a parameter in codeigniter.
This works for me:
function the_kwarg($gender){
$gender = $this->uri->segment(3);
}
However,i don't understand why this is wrong
function the_kwarg($gender=$this->uri->segment(3)){
//$gender = $this->uri->segment(3);
}
Why is it wrong to do it that way?.
Because functions can only accept scalar default values, it can't evaluate $this (or any variable) in that context.
From the manual:
A function may define C++-style default values for scalar arguments.
And:
The default value must be a constant expression, not (for example) a variable, a class member or a function call.
Function arguments default values cannot be a dynamic expression, e.g.
function foo ($x = 1 + 1) { }
is illegal, because 1 + 1 is an expression. We all know the result is a constant 2, but PHP isn't smart, and just sees an expression.
While people already gave you correct answers, I can give you an example how to solve the problem:
function the_kwarg($gender = null){
$gender = (!is_null($gender)) ? $gender : $this->uri->segment(3);
}
Why don't you just use the function like
function the_kwarg($gender){
echo $gender; // will echo male
}
// http://www.example.com/controller/the_kwarg/male
In CI the uri segments after the function name are basically the parameters of the function

PHP: how to force property of method to be integer?

My current way:
class A {
public function function_b($myint) {
if (!is_numeric($myint)) return false;
// code ...
}
}
I would like to abandon the function is_numeric() like this:
public function function_b(Integer $myint) {
// code ...
}
It works with arrays like this:
public function function_c(Array $arr) {
// only executes following code if $arr is an array / instance of Array!
}
Note: the function has to return false if the value isn't a number (int)! I don't want to cast it.
How would you short my current code? Thanks in advance!
You can't force strict types in function prototypes in PHP inherently, because it's not a strictly typed language. PHP is a weakly typed language and trying to go against the grain will only hurt you in many situations. Also, is_numeric does not guarantee that your value is of type int (for what it's worth).
What you can do is analyze your need for why you think this approach is necessary in the first place and decide on how to best implement this without creating potential for bugs.
For example, take the following scenario where what your method expects is an ID for a database query.
class MyClass {
public function getUser($id) {
if (!is_int($id)) {
throw new Exception("Invalid argument supplied. Expecting (int), but argument is of type (" . gettype($id) . ").");
}
// Otherwise continue
$db = new PDO($dsn);
$stmt = $db->prepare("SELECT username FROM users WHERE user_id = ?");
$stmt->execute(array($id));
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
$MyObject = new MyClass;
$result = $MyObject->getUser($_POST['id']);
/* The problem here is $_POST will always be of type string. */
What this should tell you is that it makes no sense to force type checking here since PHP will have done the right thing for you had you just let it alone.
The question you need to be asking yourself is not "How do I force strict typing?", but rather "Why would I need to force strict typing at all?".
You should look into typecasting:
http://php.net/manual/en/language.types.type-juggling.php#language.types.typecasting
Just use (int) when accessing the value to typecast it to an integer.
You could just typecast it:
public function function_b($myint) {
$myint = (int) $myint;
}
Or better yet add a public setter to class A which will do it for you every time you set the value:
class A
{
public function setMyInt($myInt)
{
$this->myInt = (int) $myInt;
}
}
-- Update (based on comment) --
class A
{
public function doSomethingWithAnArray(array $array)
{
....
}
}
Notice the keyword array in the signature of the doSomethingWithAnArray method, now if you don't pass an array to this function PHP will throw a fatal error and cease code execution. This is known as typehinting, and can be applied to objects as well.
function needsInteger($int) {
if (((int) $int) != $int) return false;
// ...
}
The advantage here is that you can still accept loosely typed parameters, but the non-strict equality check against the cast value will yield an acceptable result.

Returning function result into array

I am passing an array to a function and expecting the function to store values in it. Here's my code
The Function -
function GetDetailsById ($iStudentId, $aDetailsId)
{
/* SQL */
while ($row = mysql_fetch_array($result))
{
array_push($aDetailsId, $row[0]);
}
}
Usage -
$aDetailsId = array();
$oDetailsTable->GetDetailsById("1", $aDetailsId)
When I try to do
print_r($aDetailsId)
the array shows nothing. Am I doing it the right way?
Your array needs to be passed by reference to the function ; which means the function should be defined this way :
function GetDetailsById ($iStudentId, & $aDetailsId)
{
// ...
}
For more informations, see Making arguments be passed by reference
Or you could have your function return its result -- which might be better idea (looking at the code that calls the function, you immediately know what it does) :
function GetDetailsById ($iStudentId)
{
$result = array();
// TODO here, fill $result with your data
return $result;
}
And call the function :
$aDetailsId = $oDetailsTable->GetDetailsById("1");
That's because parameters are passed by value by default, meaning only the value of the variable is passed into the function, not the variable itself. Whatever you do to the value inside the function does not affect the original outside the function.
Two options:
return the modified value from the function.
Pass the parameter by reference:
function GetDetailsById ($iStudentId, &$aDetailsId) ...
first count/check your resutl is contain any resultset. and try using '&' in parameter of array
function GetDetailsById ($iStudentId, &$aDetailsId)
Please change function declaration to,
function GetDetailsById ($iStudentId, &$aDetailsId)
There is one more mistake in array_push call. Change it to,
array_push($aDetailsId, $row[0]);

Categories