Pass by null reference in PHP - php

In PHP I need to pass some arguments to a function by reference.
I don't want to write 2 different methods for similar behaviour.
So i need to select behaviour by argument.
But I can't pass null by reference.
So I created a dummy array.
So i run it either by
$temp[0]=-1;
$this->doSomething($bigIds, $temp);
or
$temp[0]=-1;
$this->doSomething($temp, $smallIds);
public function doSomething(&$bigIds, &$smallIds) {
if ($bigIds[0] != -1) {
// make some thing
}
if ($smallIds[0] != -1) {
// make some thing
}
}
Is there a better/ elegant way to do this?

I would suggest an enum but this is PHP. So this should do it for you:
class YourClass
{
const DoSomethingSmall = 0;
const DoSomethingBig = 1;
public function doSomething(&$ids, $actionType) {
// can also use a switch here
if($actionType == self::DoSomethingSmall) {
// do small
}
else if($actionType == self::DoSomethingBig) {
// do big
}
}
}
Then you can do:
$this->doSomething($bigIds, self::DoSomethingBig);
$this->doSomething($smallIds, self::DoSomethingSmall);
From outside the class you can use YourClass::DoSomethingBig and YourClass::DoSomethingSmall

There could be loads of things you might rather do, for instance what #ad7six says in a comment, and you could also just give it some sort of setting and just one array..
public function doSomething(&$bIds, $mode) {
switch($mode){
case 1: do smallthing;break;
case 2: do bigthing;break;
case 3: do both;break;
default: do nothing;break;
}
It all depends on what you need really

Related

PHP - code optimisation - parameter "into" a function name (hum) or better method?

I have a function, called function($parameter) for the example. I want this function to call another function, different depending on the parameter.
My code today:
function($parameter)
{
if($parameter == "A")
{
fctA();
}
elseif($parameter == "B")
{
fctB();
}
elseif($parameter == "C")
{
fctC();
}
}
// etc.
// There is a long list. Really long. Imagine that goes to ZZZZZ.
The "inside" function is always named in the same way. For the example, fctA(), fctB()... What is inside these functions is totally different the one with another.
Could I do better than that looooong list of "if" ?
Using a variable into a function name seems impossible... but if there is a better method, I am eager to read about it! :)
Maybe I'm missing something obvious, any tips welcomed, I'm still learning!
Thanks a lot!
You can call a function from your $parameter variable by using it in an interpolated string:
function ($parameter) {
if (function_exists("fct{$parameter}")) {
return "fct{$parameter}"();
} else {
return "Unknown Function: fct{$parameter}";
}
}
If $parameter is A, this will call fctA(), if it is B it will call fctB(), and so on.
Only catch is to make sure you have a function for each possible value of $parameter, and they all have the same signature, such as function fctA() { return 'A'; }, function fctB() { return 'B'; }, etc etc. Thanks to #jhmckimm for the function_exists suggestion; that is a good way to handle that.
Funcional example:

PHP create object inside it's own constructor

EDIT: Link to my first question. Might clear some things up.
PHP Get corresponding data, with default and error handling
I have a function that checks if a GET statement exists. If so, it passes the value to a other function that then selects a class based on the value of the GET statement.
explaining:
The url = Page=Contact
The GetFormVariable approves it, and the class Contact is selected and it will give back a string. This string is used as an object 'Content' that, as it says, creats the content of the page.
public function getFormVariable($value){
switch (strtoupper($_SERVER['REQUEST_METHOD'])) {
case 'GET':
if (isset($_GET[$value]) && $_GET[$value] != NULL) {
return $_GET[$value];
}
else{
return false;
}
break;
case 'POST':
if (isset($POST[$value]) && $POST[$value] != NULL) {
return $POST[$value];
}
else{
return false;
}
break;
default:
return false;
}
}
Now the question.
When there is no GET statement in the url. The GetFormVariable returns false. And this means there is nothing shown.
How do i give this constructor.
public function SetProperty ($prob, $val){
$this->$prob = $val;
}
The information to create the ContentHome.
SetProperty('Content', 'ContentHome');
Sorry for poor explanation, if anything is unclear please tell me so.
I'm suggesting we close this question as unclear what you're asking, but decided to throw some help on the provided code sample anyway...
You can strip this down dramatically, and since there's no context, the function can be static too.
static public function getFormVariable($value)
{
if($_SERVER['REQUEST_METHOD'] == 'GET' &&
isset($_GET[$value]) &&
!empty($_GET[$value]))
return $_GET[$value];
elseif($_SERVER['REQUEST_METHOD'] == 'POST' &&
isset($POST[$value]) &&
!empty($POST[$value]))
return $POST[$value];
return false;
}
Your original isset and != NULL checks were doing the same check. Maybe you want the empty() check as a third check, but look it up to be certain.
The question is unclear.
How you call getFormVariable? How you use SetProperty with the information getFormVariable provides?
As far as I understood, you mean this...
$var = getFormVariable(???);
if (false === $var)
{
SetProperty('Content', 'ContentHome');
} else {
SetProperty('var', $var);
}

returning from multiple points in a function

This is more or less a readability, maintainability and/or best practice type question.
I wanted to get the SO opinion on something. Is it bad practice to return from multiple points in a function? For example.
<?php
// $a is some object
$somereturnvariable = somefunction($a);
if ($somereturnvariable !== FALSE) {
// do something here like write to a file or something
}
function somefunction($a) {
if (isset($a->value)) {
if ($a->value > 2) {
return $a->value;
} else {
return FALSE;
} else {
// returning false because $a->value isn't set
return FALSE;
}
}
?>
or should it be something like:
<?php
// $a is some object
$somereturnvariable = somefunction($a);
if ($somereturnvariable !== false) {
// do something here like write to a file or something
}
function somefunction($a) {
if (isset($a->value)) {
if ($a->value > 2) {
return $a->value;
}
}
return FALSE
}
?>
As a matter of practice, I always try to return from ONE point in any function, which is usually the final point. I store it in a variable say $retVal and return it in the end of the function.It makes the code look more sane to me.
Having said that, there are circumstances where say, in your function as the first line you check if a var is null and if yes you are returning. In this case, there is no point in holdin on to that variable, then adding additional checks to skip all the function code to return that in the end.
So...in conclusion, both ways works. It always depends on what the situation is and what you are more comfortable with.

Why does my class only return the first value?

This Class gives me a blank output even if I change return to echo, I'm not sure what the issue is but I'm obviously not that versed in dealing with Classes and Objects.
I'm sure I'm just handling the variables/arrays incorrectly, but I can't see where, maybe the variables shouldn't be declared under Class since they should only be returned if a person is created? Should I declare variables in the function, or not declare them at all since they should be handled by $args?
Updated Question: How do I get it to return every argument not just FIRSTNAME?
PHP:
class people_handler
{
public $firstname;
public $middlename;
public $lastname;
public $city;
public $province_state;
/* zip+4 is default for postcode (postal code) */
public $postcode;
public $country;
function create_people($args)
{
$fullname=array($this->firstname,$this->middlename,$this->lastname);
$normname=array($this->firstname,$this->lastname);
$fulladdress=array($this->city,$this->province_state,$this->postcode,$this->country);
if(!$args->middlename&&$args->firstname && $args->lastname && $args->city && $args->province_state && $args->postcode && $args->country)
{
$temp_arr=array($normname,$fulladdress);
foreach($temp_arr as $value)
{
foreach($value as $values)
{
return $values;
}
}
}
else if($args->firstname && $args->middlename && $args->lastname && $args->city && $args->province_state && $args->postcode && $args->country)
{
$temp_arr=array($fullname,$fulladdress);
foreach($temp_arr as $value)
{
foreach($value as $values)
{
return $values;
}
}
}
else
{
die ("Must enter all values excluding middlename.");
}
}
}
$p1=new people_handler;
$p1->firstname="John";
$p1->middlename="Jonah";
$p1->lastname="Jameson";
$p1->city="Lansing";
$p1->province_state="Michigan";
$p1->postcode="48876-4444";
$p1->country="USA";
echo $p1->create_people($p1);
Returns:
John
You're missing the Object self-reference: $this all over the place.
Anytime you refer to a method or property from within the class, you need to refer to $this as the current instantiation of the Object that is doing the process. So, for instance...
$fullname=array($firstname,$middlename,$lastname);
becomes
$fullname=array($this->firstname,$this->middlename,$this->lastname);
Which should work, since you assigned the values to those properties already.
EDIT: Looking at the code further, constantly returning a value through loops won't manage the echoing to the browser. You can either echo $value instead of returning it, or build an array from the values and return that and have the script handle the array to echo to the browser.
EDIT THE SECOND: To get all the values out, you need to collect them as you build them. Another option is to simply output them to the browser as part of the method. Both options work, but collecting them into an array makes it more portable, but also a fair bit more code to maintain. As well, you do not need to pass the object into itself to get the method to work.
echo $p1->create_people($p1);
Should be...
$p1->create_people();
In create_people you'll have...
function create_people()
{
$fullname=array($this->firstname,$this->middlename,$this->lastname);
$normname=array($this->firstname,$this->lastname);
$fulladdress=array($this->city, $this->province_state, $this->postcode, $this->country);
if($args->firstname && $args->lastname && $args->city && $args->province_state && $args->postcode && $args->country)
{ //Don't bother including middlename if it doesn't matter if it is filled or not...
$temp_arr = array($normname, $fulladdress);
foreach($temp_arr as $value)
{
foreach($value as $values)
{
echo $values;
}
}
} else {
die ("Must enter all values excluding middlename.");
}
}
That should work.
Apart from the self-reference problem (btw the $args is also not needed as this should be the self-reference), your loop structure is wrong.
$temp_arr=array($normname,$fulladdress);
foreach($temp_arr as $value)
{
foreach($value as $values)
{
return $values;
}
}
This will:
Loop through temp_arr, finding $normname as the first value
Treat $normname as an array and loop through it
Return the first value it finds in $normname
That concludes the function, everything else is not executed.
A function can only have one return value. If you need to return information on more than one thing, you need to return it as an array or as an object so that it is all wrapped up in one element.
At the moment I'm not quite sure what you're trying to accomplish with your class, so unfortunately I can't help you with what you need to do.
Edit: You don't need to return anything in that case. Your class makes those variables accessible to all functions within the class already. With "new" you create an instance of the object, that is you create "a people_handler". This people_handler has properties about it, which you made public, so they can be set from outside the class (which may not be a great idea in a bigger project but seems fine for this). All functions which are part of the class (that is, inside it), can access what values these properties currently have for that certain people_handler by using the self-reference, $this:
class TestClass {
public fullname; //a random "property"
function echoFullname() {
echo $this->fullname; //whatever fullname is at the moment for the TestClass object we are using
}
}
$a = new TestClass(); //Create a TestClass object
$a->fullname = "Alex"; //make its name "Alex"
$b = new TestClass(); //Create another TestClass object
$b->fullname = "Carl"; //but let's name him Carl
$a->echoFullname(); //And now output the names
$b->echoFullname();
Obviously this has no practical use but hopefully illustrates how it works.As you can see, variable passing wasn't necessary at all.
at line 14:
$fullname=array($firstname,$middlename,$lastname);
Probably should be:
$fullname=array($this->firstname,$this->middlename,$this->lastname);
same one line 16:
$fulladdress=array($city,$province_state,$postcode,$country);

Should I use methods or constant flags?

If I have a database table containing a flag that can have multiple states, should I do this
if ($Object->isStateOne()) {
// do something
}
else if ($Object->isStateTwo()) {
// do something else
}
else if ($Object->isStateThree()) {
// do yet something else
}
or this
switch ($Object->getSomeFlag()) {
case ObjectMapper::STATE_ONE:
// do something
break;
case ObjectMapper::STATE_TWO:
// do something else
break;
case ObjectMapper::STATE_THREE:
// do yet something else
break;
}
?
Whichever makes sense, of course.
The switch looks much cleaner. But, what is this 'state' you are checking? If you're translating a string, use an array, for example.
The if has different behavior from switch. The method calls MAY have side effects. The if is better if multiple states may be active on the object at once, though.
From an OO perspective, both are discouraged. If you have different state, you may want to create a virtual methods, and override it in inherited class. Then based on polymorphism, you can avoid the if, and switch statement.
The second option just seems to be the better solution. IMHO, the unsightly duplication of the comparison code that would accompany the methods of the first solution would be the show-stopper for me, for example:
public function isStateOne() {
if(strcmp(ObjectMapper::STATE_ONE, '1') == 0) {
return true;
}
}
public function isStateTwo() {
if(strcmp(ObjectMapper::STATE_TWO, '2') == 0) {
return true;
}
}
public function isStateThree() {
if(strcmp(ObjectMapper::STATE_THREE, '3') == 0) {
return true;
}
}
Of course, others might disagree. I just don't like having classes cluttered up with 'almost the same' methods.

Categories