PHP for loop only runs once - php

I've been taking the php course from code academy. In one of the exercises, i've tried to implement a conditional function, where it would take a parameter for how many times the function would run. Unfortunately it is not running. I'm trying to run the bark() twice with bark(2). It's only echoing once. I have tried a "do while", "if" and "for". None worked. Why is that?
<?php
class Dog{
public $numLegs = 4;
public $name;
public $speak = "Woof!";
public function bark($up){
$counter = 0;
for($counter; $counter!=$up;$counter++){
return $this->speak;
}
}
public function greet(){
return "Hello " . $this->name . "!" . "<br />";
}
public function __construct($name){
$this->name = $name;
}
}
$dog1 = new Dog("Barker");
$dog2 = new Dog("Amigo");
echo $dog1 -> bark(2);
echo $dog2 -> name;
?>

You are returning $this->speak, as soon as you return a value the entire function stops execution.
You could do something like:
public function bark($up){
$counter = 0;
$return = '';
for($counter; $counter<$up;$counter++){
$return .= $this->speak;
}
return $return;
}

To add another solution, without using for at all using array_fill() to create an array of the wanted size and content (since it is always the same text) and then simply implode() to receive a String as result.
public function bark($up){
return implode(array_fill(1, $up, $this->speak));
}

return inside the for loop exits from the bark function. So the dog barks only once.
public function bark($up){
$counter = 0;
for($counter; $counter!=$up;$counter++){
echo $this->speak;
}
}
$dog1 -> bark(2);

You have to change these lines:
return $this->speak;
To:
echo $this->speak;
And
echo $dog1->bark(2);
To:
dog1->bark(2);
The return statement stops immediatly the method, this is the reason you are getting only one echo

What you want to do is run the bark function in a for loop, not have a for loop in the bark function.
public function bark(){
return $this->speak;
}
for($i = 0; $i < 2; $i++){
echo $dog1 -> bark();
}
The problem with looping inside the bark function mostly comes from the fact that you lose a lot of flexibility.
You could echo right in there, but outputting data from an object's method is far from ideal. What if you need to perform some kind of logic on the output?
You could also concatenate within the function, but then again, what if you need to format the output? Then you'd have to split the output again, which defeats the purpose.

Related

PHP Calling a callback function from within Object method

I am building a scheduler that will take a callback function and will execute that function a given amount of times, and in between a given amount of delay. Below is that the interface for what the functionality looks like.
Side note I am using the Laravel Framework;
public function testBasicTest()
{
$count = 0;
$schedule = new NodeScheduler();
$schedule->retries(2)->delay(100000)->do(function() use ($count) {
$count++;
});
$this->assertEquals($count === 1);
}
This is my test for this piece of functionality and as you can see i want count to equal 2 by the end of it.
My class looks like this;
class NodeScheduler
{
protected $retries = 1;
protected $milliseconds = 10000;
public function __construct()
{
return $this;
}
public function retries($numberOfRetries)
{
$this->retries = $numberOfRetries;
return $this;
}
public function delay($milliSeconds)
{
$this->milliSeconds = $milliSeconds;
return $this;
}
public function do($callback)
{
for($i = 0; $i < $this->retries; $i++){
$callback(); // <<<<<< How Do I Inject The $count Variable Here?
usleep($this->milliseconds);
}
return;
}
}
My test fails with:
Failed asserting that 2 matches expected 0.
Strangely I don't get $count is undefined.
I think i am close, any help greatly appreciated
When you use() a variable from the outer scope inside a function, this creates a copy of the variable into the function's inner scope (an exception is if you're use()ing an object).
If you want to import a variable from the outer scope and modify it, you'll need to pass it in by reference:
$schedule->retries(2)->delay(100000)->do(function() use (&$count) {
$count++;
});
Edit: Also, what #Arno and #Oniyo pointed out: either use assertEquals(1, $count) or use assertTrue($count === 1)
I think you are doing two things wrong
Firstly: As #Arno pointed out,
$this->assertEquals($expected, $actual);
Secondly: From what I see in your code, the loop will run $this->retries's iterations. So, $this->assertEquals($expected, $actual) should be
$this->assertEquals(2, count);
Good luck man!

Get two values returned from class

I am trying to understand object oriented PHP programming and wrote a small class to learn. I am having trouble understanding why its not working the way I intend. I have two variables inside the class method hello() $result and $test. I am trying to access the data that is stored in those two variables and print it to the screen. I know I can just call an echo inside the method but I am trying to get it to echo outside of it.
What I get printed to the screen is 88 it does not print out the second variable $test. I am trying to understand why thats happening. My lack of understanding probably shows in the code.
<?php
class simpleClass{
public function hello($result,$test) {
$result = 4+4;
$test = 10+5;
return $result;
return $test;
}
}
$a = new simpleClass;
echo $a->hello();
echo $a->hello($result, $test);
?>
you can return a list or array
public function hello($result,$test) {
$result = 4+4;
$test = 10+5;
return array($result, $test);
}
Use parameter referencing :
class simpleClass{
public function hello(&$result, &$test) {
$result = 4+4;
$test = 10+5;
}
}
$a = new simpleClass;
$result=''; $test='';
$a->hello($result, $test);
echo $result;
echo '<br>';
echo $test;
8
15
To clarify, when you add & to a function param, the value of that param - if you change or manipulate it inside the function - is handled back to your original variable passed. So you dont even have to return a result, and lets say pack it into an array or stdObject and unpack it afterwards. But you can still return something from the function, eg
$ok = $a->hello($result, $test);
as a flag to indicate if the calculation went right, for instance.
You cannot have multiple return statements in the same function because of the way return works. When a return statement is encountered the function stops executing there and then, passing back to the caller. The rest of the function never runs.
The complicated answer is to use a model.
class simpleResultTestModel {
public $result;
public $test;
public function __construct($result,$test) {
$this->result = $result;
$this->test = $test;
}
}
class simpleClass {
public function hello($result=4, $test=10) {
$result = $result+4;
$test = $test+5;
return new simpleResultTestModel($result, $test);
}
}
This way, you know simpleClass->hello() will always return an instance of simpleResultTestModel.
Also, I updated your hello method definition. You have two parameters, but don't actually apply them; I took the liberty of setting default values and then used them in the computation.
Usage:
$a = new simpleClass();
$first = $a->hello();
echo $first->result;
echo $first->test;
$second = $a->hello($first->result,$first->test);
echo $second->result;
echo $second->test;
I would try to stay away from passing by reference (especially within a class definition) unless you have a legitimate reason for doing so. It is bad practice when creating instances of classes (i.e. "sticky values" if you will).

access(return) a variable from with in a private function inside a class

I have this kind of class and i would like to take variable outside(return i guess) so that i would be able to do stuff with it.
class MyClass{
private function MyPrivate(){
$rows = 'SomeVar';
echo $rows.' is echoed from inside';
//return $rows;
return $this->rows;
}
function Foo(){
$this->MyPrivate();
//$this->rows;
}
//return $rows;
//return $this->rows;
}
$myclass = new MyClass;
$myclass->Foo();
//$myclass->rows;
echo '<br />';
echo $rows.'is echoed from outside';
Echoing variable inside the private function inside the class works, but echoing variable outside does not. Commented out code is what I tried to use to achieve wanted result. I did not make this class so I do not want to mess with it and change anything in it, because I fear it may mess things up.
this is my out put:
SomeVar is echoed from inside
is echoed from outside
As you can see in the second instance there is no SomeVar(variable) present. I am surprised it's working though.
I am reading up on documentation and tutorials on the web for the past two days but this needs to be solved soon, that is why I posted. Please help. Thanks.
When you use the return statement, you should assign it to a variable. Also, you should have returned $rows, not $this->rows, since they're actually different variables:
class MyClass{
private function MyPrivate(){
$rows = 'SomeVar';
echo $rows.' is echoed from inside';
return $rows;
}
function Foo(){
return $this->MyPrivate();
}
}
$myclass = new MyClass;
$rows = $myclass->Foo();
echo '<br />';
echo $rows.'is echoed from outside';
You really should explicitly declare your variables in your class. Also, there's no reason to worry about returning rows from the different functions - just make it a member of your class, set it's visibility to public and access it inside and outside your class.
It looked like you were also confused between local variables in a function and class member variables. You must always use $this-> to access a member of the class.
<?php
class MyClass
{
public $rows;
private function MyPrivate()
{
$this->rows = "Low-level programming is good for the programmer's soul --J. Carmack";
echo $this->rows . ' is echoed from inside';
}
function Foo()
{
$this->MyPrivate();
}
}
$obj = new MyClass;
$obj->Foo();
echo $obj->rows . ' is echoed from outside.';
you could do:
class MyClass{
private function MyPrivate(){
$rows = 'SomeVar';
echo $rows.' is echoed from inside';
//return $rows;
return $rows;
}
function Foo(){
return $this->MyPrivate();
//$this->rows;
}
//return $rows;
//return $this->rows;
}
$myclass = new MyClass;
$rows = $myclass->Foo();
//$myclass->rows;
echo '<br />';
echo $rows.'is echoed from outside';
codepad here: http://codepad.org/8rr1hfI3
Try setting $rows as a member var:
class MyClass
{
public $rows;
private function myPrivate()
{
$this->rows = 1;
}
function Foo(){
$this->MyPrivate();
}
}
$myclass = new MyClass();
$myclass->foo();
$rows = $myclass->rows;

Calculate number of function calls in the same function

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

Can I include a function inside of another function?

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"

Categories