Is it possible to include one function inside another? To learn functions, I'm trying to create a combat sequence using PHP. The sequence would look like this:
Dice would roll, assigning numbers to variables;
Hero1 attack results are printed;
Dice would roll, assigning numbers to variables;
Hereo2 attack results are printed;
Dice would roll, assigning numbers to variables;
Hero3 attack results are printed.
The dice rolling would be an automated function. Here is the code:
<?
rollSim();
combatSim();
function rollSim() {
$hAttack = rand(1,20);
$mDefend = rand(1,20);
$mAttack = rand(1,20);
$hDefend = rand(1,20);
$mDamage = rand(10,25);
$hDamage = rand(1,20);
} // end rollSim
function combatSim() {
rollSim();
if ($hAttack>$mDefend) {
print "Hero hit monster for $hDamage damage.<br>";
} else if ($hAttack<=$mDefend) {
print "Hero missed monster.";
}
} // end combatSim
?>
Your rollSim() function should return the rolled numbers rather than setting some variables and trying to use them in your other function. I would return them in an associative array, like this:
function rollSim() {
$roll['hAttack'] = rand(1,20);
$roll['mDefend'] = rand(1,20);
$roll['mAttack'] = rand(1,20);
$roll['hDefend'] = rand(1,20);
$roll['mDamage'] = rand(10,25);
$roll['hDamage'] = rand(1,20);
return $roll;
}
function combatSim() {
$roll = rollSim();
if ($roll['hAttack'] > $roll['mDefend']) {
print "Hero hit monster for {$roll['hDamage']} damage.<br>";
} else if ($roll['hAttack'] <= $roll['mDefend']) {
print "Hero missed monster.";
}
}
No, you can't really do what you're asking. Even if you embedded the declaration of rollSim() inside the definition of combatSim() (which you can do, that's legal but has no real effects), the variables you're setting in rollSim() would still be local to it and inaccessible by combatSim().
You need a better way of passing around the information you're concerned with. Jeremy Ruten details a good way. Another way would be to define an object that's responsible for modeling your combat event and have rollSim() and combatSim() both be methods on it.
class myCombat {
private $hAttack;
private $mDefend;
private $mAttack;
private $hDefend;
private $mDamage;
private $hDamage;
function rollSim() {
$this->hAttack = rand(1, 20);
$this->mDefend = rand(1, 20);
$this->mAttack = rand(1, 20);
$this->hDefend = rand(1, 20);
$this->mDamage = rand(10, 25);
$this->hDamage = rand(1, 20);
}
function combatSim() {
$this->rollSim();
if($this->hAttack > $this->mDefend)
echo 'Hero hit monster for ' . $this->hDamage . ' damage.<br />';
else
echo 'Hero missed monster';
}
}
$combat = new myCombat;
$combat->combatSim();
You can call functions from one another, certainly... but I think you want to use the scope of one in another, correct?
Sharing scope is a messy business. You're better off passing arguments.
If you want to define functions within function in PHP you can do it like this:
function a()
{
function b()
{
echo 'I am b';
}
function c()
{
echo 'I am c';
}
}
a();
b();
c();
You must call the parent function first, then the functions inside.
here is the simple example call function within function
class Percobaan{
public function coba(){
return "return value";
}
public function call(){
//call coba function
return $this->coba();
}
} // end of class percobaan
//call the method
$klass = new Percobaan();
echo $klass->call();
the output willbe :
"return value"
Related
I know that this question may have been asked before, but I don't quite understand the whole concept of anonymous functions (closures), and how they would apply specifically to my situation. NB: I know it is quite silly to have all these simple functions, but my task requirements say that I should have all these functions :/ .
I have several functions. In the function below, the parameters $action1 and $action2 will be both replaced by functions:
function dothis($num1, $num2, $action1, $action2)
{
$result = $num1 + $num2;
if ($result > 52){
//do $action1 which is a function
} else {
//do $action2 which is another function
}
return $result;
}
The function dothis will be called in another function called add. Here is the add function:
function add($action1,$action2)
{
$answer = dothis(42, 34, $action1, $action2);
echo $answer;
}
$action1 and $action2 in the add function are essentially the same as the $action1 and $action2 in the dothis function. Do they need to have different names now even though they are the same things?
Now, the add function will be called in the main function, where the parameters $action1 and $action2, will be replaced by the actual functions that they correspond to:
function main()
{
add($fun1,$fun2);
echo 'Arithmetic complete';
}
This is the code for $fun1 and $fun2:
$fun1 = function () {
echo 'Wow! The answer is greater than 52.';
};
$fun2 = function () {
echo 'Oh no! The answer is less than 52.';
};
What should I do, and what do I need to change? I really appreciate any help. Thanks in advance!
See the PHP documentation on Variable Functions
You call a function by putting () after it (with arguments inside the parentheses if necessary).
function dothis($num1,$num2,$action1,$action2){
$result = $num1 + $num2;
if ($result > 52){
$action1();
}
else{
$action2();
}
return $result;
}
For this syntax to work with anonymous functions, you have to turn off eAccelerator. See Anonymous functions does not work: Function name must be a string
If you can't use anonymous functions, you'll need to use named functions.
function fun1 () {
echo 'Wow! The answer is greater than 52.';
}
$fun1 = 'fun1';
function fun2() {
echo 'Oh no! The answer is less than 52.';
}
$fun2 = 'fun2';
I guess this is a rather bad approach. You could use a function like call_user_func() but not really for anonymous functions. Why not come up with a class defining both functions or (if the code is rather short) but it in the if/else statements directly?
Some dummy sample code for the class approach:
class doSomething {
function dothis($num1, $num2) {
$result = $num1 + $num2;
if ($result > 52) {
$this->action1($num1, $num2);
} else {
$this->action2($num1, $num2);
}
return $result;
}
function action1($numbers) {
// do sth. here
}
function action2($num1, $num2) {
// do sth. else here
}
}
// afterwards
$pointer = new doSomething();
$pointer->dothis(21,34); // action1
$pointer->dothis(1,1); // action2
I'm currently trying to get back into object oriented programming How do i get my array inside my class? Global doesn't seam to cut it.
<?
$systems = file_get_contents('https://api.eveonline.com/map/Sovereignty.xml.aspx');
$systems = explode("<row ",$systems);
//print_r($systems);
for ($i = 1; $i <= count($systems); $i++) {
//system name
$systemnames=explode("solarSystemName=",$systems[$i]);
$systemnames=explode('"',$systemnames[1]);
$systemnames=$systemnames[1];
//system id
$systemid=explode("solarSystemID=",$systems[$i]);
$systemid=explode('"',$systemid[1]);
$systemid=$systemid[1];
$systembyid[$systemid]=$systemnames;
$systembyname[$systemnames]=$systemid;
}
class Systems{
public function __construct()
{
global $systembyid;
global $systembyname;
}
function getSystems($system)
{
if (is_numeric($system) && $systembyid[$system]) {
return $systembyid[$system];
}
elseif($systembyname[$system]){
return $systembyname[$system];
}
else{
return "Error: Invalid system id or name";
}
}
}
?>
Try passing the values into the constructor like this, also if you use the & you are just passing a reference and not making a copy of the whole array.
class Systems{
private $sysyembyid;
private $systembyname;
public function __construct(&$systembyid, &$systembyname)
{
$this->systembyid = $systembyid;
$this->systembyname = $systembyname;
}
function getSystems($system){
if(is_numeric($system) && $this->systembyid[$system]){
return $this->systembyid[$system];
}
elseif($this->systembyname[$system]){
return $this->systembyname[$system];
}
else{
return "Error: Invalid system id or name";
}
}
}
I prefer to use Dependency Injection. Dependency Injection is when you inject your object's dependencies via the constructor. This ensures that the object will have its dependencies at creation.
class Systems {
protected $systembyid;
protected $systembyname;
public function __construct($systembyid, $systembyname)
{
$this->systembyid = $systembyid;
$this->systembyname = $systembyname;
}
public function getSystems($system) {
//Access them with $this-> like below
$this->systembyid[$system];
$this->systembyname[$system];
}
}
Note If you want to be able to modify $systembyid and $systembyname outside of the class, and see the changes within the class, you can pass references to __construct() instead, by specifying the parameters as references:
public function __construct(&$systembyid, &$systembyname)
{
$this->systembyid = $systembyid;
$this->systembyname = $systembyname;
}
Alternatively, you can pass them as parameters to your getSystems() method.
class Systems() {
public function getSystems($system, $systembyid, $systembyname) {
//Do stuff
}
}
The main drawbacks with this approach is that you always have to pass them as parameters to the method, and the method signature could get quite long.
You either need to use the global key word with var in the function where you use it, in this case getSystems() (bad) or pass them into the constructor or the function where you use them, or set them:
Probably the most common case:
public function __construct($s1, $s2)
{
$this->systembyid = $s1
$this->systembyname = $s2
}
//then use $this->systembyid etc in other functions
Or better yet, why not put all that processing code in a function off the class like processSystems() and set the vars there:
public function processSystems($file) {
$systems = file_get_contents($file);
$systems = explode("<row ",$systems);
//print_r($systems);
for ($i = 1; $i <= count($systems); $i++) {
//system name
$systemnames=explode("solarSystemName=",$systems[$i]);
$systemnames=explode('"',$systemnames[1]);
$systemnames=$systemnames[1];
//system id
$systemid=explode("solarSystemID=",$systems[$i]);
$systemid=explode('"',$systemid[1]);
$systemid=$systemid[1];
$systembyid[$systemid]=$systemnames;
$systembyname[$systemnames]=$systemid;
}
$this->systembyid = $systemnames;
$this->systembyname = $systemid;
}
Aside from that, I would say look into simple_xml or DOM for the XML parsing.
Also, you are storing the exact same data in each array. Just use one and either lookup the key or the value.
I've been looking at Magic Constants and Reflection in PHP to see if the following is possible:
function one() {
setVars();
// $node would be in scope
print_r($node);
}
function setVars() {
return $node = '2';
}
Is this a classical programming concept? Reflection seems to be the closest thing. Basically, I just want to define variables in a different scope (the scope/context of the function that called the setVars() function).
For more than one variable try to store them in a array and return the array.
function one() {
$nodeArray = setVars();
print_r($nodeArray );
}
function setVars() {
$nodeArray[] = 1;
$nodeArray[] = 1;
$nodeArray[] = 1;
return $nodeArray;
}
Take a look at extract().
function one() {
$vars = setVars();
extract($vars);
// $node1 would be in scope
print_r($node1);
}
function setVars() {
$node1 = '1';
$node2 = '2';
return compact('node1','node2');
}
It should be said, although this is possible, it often leads to terrible architecture and problems down the line.
I have a variable like $string = "blah";
How can I create a function that has the variable value as name?
Is this possible in PHP?
Like function $string($args){ ... } or something, and be able to call it like:
blah($args);
this might not be a good idea, but you can do something like this:
$string = "blah";
$args = "args"
$string = 'function ' . $string . "({$args}) { ... }";
eval($string);
That doesn't sound like a great design choice, it might be worth rethinking it, but...
If you're using PHP 5.3 you could use an anonymous function.
<?php
$functionName = "doStuff";
$$functionName = function($args) {
// Do stuff
};
$args = array();
$doStuff($args);
?>
Okay, challenge accepted!
No matter how weird the question is (it's not btw), let's take it seriously for a moment! It could be useful to have a class that can declare functions and make them real:
<?php
customFunctions::add("hello", // prepare function "hello"
function($what) {
print "Hello $what, as Ritchie said";
print "<br>";
}
);
customFunctions::add("goodbye", // prepare function "goodbye"
function($what,$when) {
print "Goodbye cruel $what, ";
print "I'm leaving you $when";
print "<br>";
}
);
eval(customFunctions::make()); // inevitable - but it's safe!
That's it! Now they're real functions. No $-prefixing, no runtime evaluations whenever they get called - eval() was only needed once, for declaration. After that, they work like any function.
Let's try them:
hello('World'); // "Hello World"
goodbye('world','today'); // "Goodbye cruel world, I'm leaving you today"
Magic behind
Here's the class that can do this. Really not a complex one:
class customFunctions {
private static $store = [];
private static $maker = "";
private static $declaration = '
function %s() {
return call_user_func_array(
%s::get(__FUNCTION__),
func_get_args()
);
}
';
private static function safeName($name) {
// extra safety against bad function names
$name = preg_replace('/[^a-zA-Z0-9_]/',"",$name);
$name = substr($name,0,64);
return $name;
}
public static function add($name,$func) {
// prepares a new function for make()
$name = self::safeName($name);
self::$store[$name] = $func;
self::$maker.=sprintf(self::$declaration,$name,__CLASS__);
}
public static function get($name) {
// returns a stored callable
return self::$store[$name];
}
public static function make() {
// returns a string with all declarations
return self::$maker;
}
}
It provides an inner storage for your functions, and then declare "real" functions that call them. This is something similar to fardjad's solution, but with real code (not strings) and therefore a lot more convenient & readable.
Try call_user_func_array()
php.net link
You can call a function by its name stored in a variable, and you can also assign a function to variables and call it using the variable. If it's not what you want, please explain more.
How to calculate(determine) in php the total number of a function calls but the result of this must be in the same function for which I calculate this number.
Exemple:
The test() function is called 100 times(this number is variable and so I don't know it from beginning). I want to find this number in the block of function
test();
function test(){
$no_calls =....
echo $no_calls;
}
I want the message from echo to be shown only once not to every call of function.
use a static variable, like this
function test(){
static $no_calls = 0;
...
++$no_calls;
}
$no_calls will keep its value between calls
In response to your edit, you could do something like this:
function test() {
static $no_calls = 0;
++$no_calls;
...
return $no_calls;
}
test();
test();
test();
$final = test();
echo $final; // will be 4
ok, let's try this a third time:
function test($last_time = false) {
static $no_calls = 0;
++$no_calls;
...
if($last_time)
{
echo $no_calls;
}
}
test();
test();
test();
test(true); // will echo 4
OK, let's try this one more time:
class Test {
private $no_calls;
function test()
{
...
++$this->no_calls;
}
function __destruct()
{
echo $this->no_calls;
}
}
$test = new Test();
$test->test();
$test->test();
$test->test();
$test->test();
//when $test falls out of scope, 4 will be echoed.
so, we need to magically echo the number of times a function is called: only once, inside the function, without using classes, and without telling the function that it is the last call. Hold on to your hats (warning, I do not suggest using this code for many reasons (but you leave me no choice), and it WILL NOT work if there is to be any output in between function calls, including by the function itself):
function test() {
static $no_calls = 1;
if($no_calls == 1)
{
ob_start();
}
else
{
++$no_calls;
ob_clean();
}
echo $no_calls;
}
In this instance, when the script terminates, the output buffering left open will automatically flush to the browser.
<?php
test();
test();
test();
test();
$NoOfCalls=0;
function test(){
global $NoOfCalls;
echo ++$NoOfCalls;
}
function test() {
static $calls = 0;
$calls++;
echo "this function has been called $calls times";
}
test(); // 1 times
test(); // 2 times
test(); // 3 times
If you need that calls value to be available outside of the function, you'll either have to return it from the function (return $calls, or assign it to a global variable somewhere.
This should help:
function test() {
static $count = 0;
$count++;
...
}
You can make global variable and increment it in function. And when you check total call count, you can use that variable.
Sloppy code, but it should be understandable enough. It utilizes the __destruct of the object to only print the summary once. Also it uses debug_backtrace to automagically detect what function is calling it. This will work if you call multiple functions too (like test, test2, some_random_function).
<?php
class Counter {
private $_count = array();
public function count_call()
{
list(, $prev) = debug_backtrace();
$this->_count[$prev['function']] = isset($this->_count[$prev['function']])
? $this->_count[$prev['function']] + 1
: 1;
}
public function __destruct(){
echo '<h2>Calls per function:</h2>';
echo '<pre>';
var_dump($this->_count);
echo '</pre>';
}
}
$counter = new Counter();
function test() {
global $counter;
$counter->count_call();
echo 'called test<br />';
}
$rand = rand(5, 10);
echo "calls to be made: {$rand}<br />";
for ($i = 0; $i < $rand; $i++) {
test();
}
While i was looking for new functions to handle some function call counts. i know that the xhprof extensions can collect thouse things and much more which can be very interessting. without implementing debug code