I wrote the following recursive function to keep looping through result looking for $result->pages->next and calling out to curl fetching the next page and aggregating the results. Finally it returns all results as a single object.
private function pager($result) {
static $all_results;
if(isset($result->pages->next) && !empty($result->pages->next)) {
$all_results[] = $this->get_curl_request($result->pages->next);
$this->pager(end($all_results));
} else {
return $all_results;
}
}
However I really don't like using static and it feels poorly implemented and a source of technical debt. What is a more elegant way to do this?
Update
Being called with:
return $this->pager($this->get_curl_request("https://api/request/here"));
Open to changing how it is called.
Try putting $all_result as second parameter like this and add return for this line: $this->pager(end($all_results), $all_results);
Code
private function pager($result, $all_results) {
if(isset($result->pages->next) && !empty($result->pages->next)) {
$all_results[] = $this->get_curl_request($result->pages->next);
return $this->pager(end($all_results), $all_results);
} else {
return $all_results;
}
}
The above code function will return the last updated array $all_results.
Example of use:
$pager_array = $this->pager($result, array());
Related
What are the best usages of functions that end with "return;" and what are the advantages of writing a function that ends this way?
Example:
function MyFunction() {
// (do something)
return;
}
Thank you
You shouldn't, I would always use return null; so that it is an explicit declaration of what is returned (even if it is null). I'm sure this is also in one of the PSR specs as well, but I don't know them well. To confirm that return; === return null;:
function test() {
return;
}
var_dump(test());
// NULL
As to when you would want to return null;..any function that returns something, should always return something. So maybe if you have a function that gathers and returns a value from a DB, and an error occurs:
public function retrieveData()
{
$data = DB::retrieve();
if(!$data) {
return null;
}
return $data;
}
However, a lot of functions that may have errors just return true/false on success or failure so you won't necessarily use this often.
My main point to drive home: if you don't want/need to return anything, don't return anything.
A return; says only "thats the end". Mostly useful in following examples:
function test($string) {
if(empty($string)) {
return; // If the variable is empty, then stop to work!
}
echo $string;
}
A simple example is that you can write a PHP function that spits out formatted HTML:
function printHeader($value)
{
echo "<h1>$value</h1>";
return;
}
However, since you are not returning anything, the return statement is unnecessary and can be left out.
If you are talking about a empty return;, I can think of one example, if you have code that should be executed under a condition, and more code that should be executed if that condition is not met.
function MyFunction() {
if(a < 1) {
// (do something)
return;
}
// If a >= 0 it executes the code above and the code below
// Do something else
}
Please note the below is just a demo, and I know it can be solved with static variables, however I am trying to work out why it doesn't work without static variables.
The below recursive function should create an array with 10 values, however it is only returning an array with a single value.
function test_function($return_array,$j) {
$j++;
$return_array[$j]='dave';
if($j<10){
test_function($return_array,$j);
}
return $return_array;
}
$sample_array=test_function(array(),0);
print_r($sample_array);
Thanks to any responders.
You have to pass your initial array per reference:
function test_function(&$return_array,$j) {
$j++;
$return_array[$j]='dave';
if($j<10){
test_function($return_array,$j);
}
return $return_array;
}
$sample_array=test_function(($tmpvar = array()),0);
print_r($sample_array);
I got stuck when I learned about recursive functions in PHP. I know recursive function are those which are being called by itself. My code is:
function addition_no($x,$y) {
if($x==0) {
return $x;
}
return addition_no($x+$y);
}
echo addition_no(1,2);
When I tried executing this code I get:
Warning: Missing argument 2 for addition_no(), called in
/web/com/13978781902261/main.php on line 6 and defined in
/web/com/13978781902261/main.php on line 2
What i need is to add two numbers via recursion.
I created this code in order to summarize values in an array using recursivity is:
<?php
//values to add
$add = array(5,4,4,6,7);
function addval($add,$pos) {
if($pos == 0) {
return $add[0];
}
else {
return $add[$pos] + addval($add,$pos-1);
}
}
//last position in vector
$last_position = count($add)-1;
echo addval($add, $last_position);
?>
You can try this
return addition_no($x,$y);
You have to check any condition for recursive function otherwise it will be infinite recursion..
The warning is appropriate as you call the function inside it self with a different argument structure.
Try the factorial recursive function to learn how it works:
<?php
// Initiating Recursion
echo factorial(5);
//Recursive Function Definition with 1 parameter
function factorial($number)
{
//Break condition for recursion
if($number==1)
return $number;
//Fetch and Stack Recursion
return $number*factorial($number-1);
}
So, you get the basic recursion, in simple English, as :
factorial(n) = n x factorial(n-1) = n x (n-1) x factorial(n-2)
For You particular case, you actually don't need a recursion as your arguments are not relying on the previous argument result. However, for the sake of learning, you can do something like this:
<?php
//Summation
function summation($x) {
if($x==0) {
return $x;
}
return $x+summation($x-1);
}
echo summation(5);
//Summation with 2 step
function summation($x,$y) {
if($x<1) {
return $x;
}
return $x+summation($x-$y,$y);
}
echo summation(5,2);
Right now I'm trying to write a function that would allow me to access member functions. The code in question looks a little like this:
protected $formName;
protected $formClass;
protected $formAction;
protected $formMethod;
protected $formObjArray = array(); //outputs in order. So far it should only take newLine, selectTag, inputTag, textTag.
protected $submitBtnVal;
protected $encType;
function __construct($args) {
$this->formName = $args['formName'];
$this->formAction = $args['formAction'];
if (isset($args['formClass'])) $this->formClass = $args['formClass'];
if (isset($args['encType'])) $this->encType = $args['encType'];
//default should be POST. Hell, you should never really be using GET for this..
//also, the default submit value is Submit
$this->formMethod = isset($args['formMethod']) ? $args['formMethod'] : "POST";
$this->submitBtnVal = isset($args['submitBtnVal']) ? $args['submitBtnVal'] : "Submit";
}
//get functions
function getFormName () { return $this->formName; }
function getFormAction () { return $this->formAction; }
function getFormMethod () { return $this->formMethod; }
function getSubmitBtnVal () { return $this->submitBtnVal; }
function getEncType () { return $this->encType; }
//set functions
function setFormName ($newName) { $this->fromName = $newName; }
function setFormAction ($newAction) { $this->formAction = $newAction; }
function setFormMethod ($newMethod) { $this->formMethod = $newMethod; }
function setEncType ($newEType) { $this->encType = $newEType; }
function addTag($newTag) {
if ($newTag instanceof formTag || $newTag instanceof fieldSetCont || $newTag instanceof newLine
|| $newTag instanceof noteTag)
$this->formObjArray[] = $newTag;
else throw new Exception ("You did not add a compatible tag.");
}
I'd like to be able to call $myForm->getTagByName("nameA")->setRequired(true);
How would I do that? Or would I need to do something more like..
$tagID = $myForm->getTagByName("nameA");
$myForm->tagArray(tagID)->setRequired(true);
Nothing in your code seems to be protected so you should have no trouble accessing any of it.
It looks like all your tags are in $formObjArray so it should be trivial to filter than array and return tags that match the name you've passed in. The trouble you will have is that, getTagByName really should be getTagsByName and should return an array because you can have more than one tag with the same name. Since it will return an array, you can not call setRequired on the return value, arrays don't have such a method. You'll need to do it more like:
$tags = $myForm->getTagsByName("nameA");
foreach ($tags as $tag) {
$tag->setRequired(true);
}
Exactly what are you stuck on? Maybe I don't understand the question very well.
So maybe the filtering has you stuck? Try this (if you you're using at least php 5.3)
function getTagsByName($tagname)
{
return array_filter($this->formObjArray, function($tag) use($tagname) {
return $tag->getName() == $tagname;
});
}
No ifs or switches.
Prior to 5.3, you don't have lambda functions so you need to do it differently. There are several options but this may be the simplest to understand:
function getTagsByName($tagname)
{
$out = array();
foreach ($this->formObjArray as &$tag) {
if ($tag->getName() == $tagname) {
$out[] = $tag;
}
}
return $out;
}
In your addTag method, you are storing new tags in $this->formObjArray using the [] notation, which will just append the new tag to the end of the array. If your tag objects all have a getName() method, then you can do something like this:
$this->formObjArray[$newTag->getName()] = $newTag;
Then, you can easily add a getTagByName() method:
public function getTagByName($name) {
if (array_key_exists($name, $this->formObjArray) {
return $this->formObjArray($name);
}
else {
return null;
}
}
Please beware of the solutions suggesting you to iterate through all the tags in your array! This could become very costly as your form gets larger.
If you need to use the [] construct because the order of the elements added is important, then you can still maintain a separate index by name, $this->tagIndex, that will be an associative array of name => tag. Since you are storing object references, they will not be using much space. Assuming that getTagByName will be used many times, this will save you a lot of resources over iterating the tags array on every call to getTagByName.
In that case, your addTag method would look like this:
$this->formObjArray[] = $newTag;
$this->tagIndex[$newTag->getName()] = $newTag; // it seems that you're doubling the memory needed, but you're only storing object references so this is safe
EDIT : Here is some modified code to account for the fact that multiple tags can have the same name:
In your addTag() method, do:
$this->formObjArray[] = $newTag;
$tag_name = $newTag->getName();
if (!array_key_exists($tag_name, $this->tagIndex)) {
$this->tagIndex[$tag_name] = array();
}
$this->tagIndex[$tag_name][] = $newTag
You can then rename getTagByName to getTagsByName and get the expected result.
As mentioned in the comments, this is only useful if you will call getTagsByName multiple times. You are trading a little additional memory usage in order to get quicker lookups by name.
I have a method in PHP which calls a SOAP service, parses some data and returns it.
It will return the same data - it asks how many records in a data object.
I need to call it twice with a pass.
My question is, what is best practice for structuring this in PHP? I've tried to see if the function has been called already.Do I use static variables / functions?
function MinimumRequired() {
return $this->NumberPeopleJoined();
}
function NumberPeopleJoined () {
if (isset($NumberPeople)) {
Debug::Show($NumberPeople);
}
static $NumberPeople;
$NumberPeople = Surge_Controller::NumberPeopleJoined();
return $NumberPeople;
}
Thanks!
Just create a local class member, and check if that has a value. If not, set the value to whatever is retrieved from Surge_Controller, and if it was already set, just return the value:
<?php
class Surge_Controller {
static public function NumberPeopleJoined() {
echo "Surge_Controller::NumberPeopleJoined() got called.\n";
return 2;
}
}
class Foo {
protected $cacheNumberPeople;
function MinimumRequired() {
return $this->NumberPeopleJoined();
}
function NumberPeopleJoined () {
if( !isset( $this->cacheNumberPeople ) ) {
$this->cacheNumberPeople = Surge_Controller::NumberPeopleJoined();
}
return $this->cacheNumberPeople;
}
}
$foo = new Foo( );
echo $foo->numberPeopleJoined( ) . "\n";
echo $foo->numberPeopleJoined( ) . "\n";
Output:
$ php foo.php
Surge_Controller::NumberPeopleJoined() got called.
2
2
The simple way is to have a global variable, and check if is "true", and set it to true at the end of your function. The value can be cached too...
But if you want to make your code fun, you can use underscore:
http://brianhaveri.github.com/Underscore.php/#once
http://brianhaveri.github.com/Underscore.php/#memoize