how many times a parameter was call - php

I'n just learning PHP by myself, and I have a question, hope you will be able to help.
In fist style
<?php
class Fist_style
{
function method_1()
{
global $a;
return $a + 1;
}
function method_2()
{
global $a;
return $a - 1;
}
function method_3()
{
$call_1 = $this->method_1();
$call_2 = $this->method_2();
}
// In this case, how many times $a was called?
}
In second style
<?php
class Second_style
{
function method_1($a)
{
return $a + 1;
}
function method_2($a)
{
return $a - 1;
}
function method_3()
{
global $a;
//I will call both method_1 and method_2
$call_1 = $this->method_1($a);
$call_2 = $this->method_2($a);
//............
}
// In this case, how many times $a was called
}
?>
The questions are inside my code, and what style will better when develop?

Using globals is very often a recipe for disaster - as many people with experience will be happy to tell you.
The normal way of having state in a class is declaring a class property:
<?
class MyClass
{
public $a;
function __construct($valueForA) {
$this->a = $valueForA;
}
function increment()
{
$this->a += 1;
}
function decrement()
{
$this->a -= 1;
}
function plusminus()
{
$this->increment();
$this->decrement();
}
}
Which can be used like so:
$anInstance = new MyClass(10); // sets a to 10 by calling the __construct method
$anInstance->increment();
echo($anInstance->a); // 11
$anInstance->decrement();
echo($anInstance->a); // 10
Read more about oop in PHP here.
As for the question in your code, the $a is not a method, so it can't be called.
Also, return $a -1; does not change the global $a (not sure if this was the intention).
Edit:
If you have a function increment like
function increment ($var) {
$var = $var - 1;
return $var;
}
then the $var is passed in as a value - if you passed in a 5, php only cares about 5, not the name. Example:
$a = 5;
$incremented = increment($a);
echo($a); // echoes 5;
echo($incremented); //echoes 6
I would suggest reading up on scoping in php.

Related

Vector calculations class oop php

I'm learning php oop and seems like i still do not understand of how some things work as my code, which, imo, looks properly doesn't work and returns few errors. This is the code:
<?php
class Vector {
private $x;
private $y;
public function __construct($x, $y) {
if (is_nan($x) || is_nan($y)) {
$this->x = 0 && $this->y = 0;
} else {
$this->set($x, $y);
}
}
public function __destruct() {
var_dump($x, $y);
}
public function setx($x) {
if (is_numeric($x)) {
$this->x;
}
}
public function sety($y) {
if (is_numeric($y)) {
$this->y;
}
}
public function retLength() {
return $x;
}
public function addVector() {
$sum=$x+$y;
}
public function dotProduct() {
$dot_product = array_sum(array_map(function($x,$y) { return $x*$y; }, $array1, $array2));
}
}
$wekt= new Vector($x, $y);
echo $wekt->addVector(5,7);
Errors i get are: undefined variables "x" and "y" on line 42 (which is $wekt= new Vector($x, $y); ) and "Call to undefined method Vector::set()".
Specification for this class is:
two private attributes $x and $y (seems to be ok)
constructor receives $x and $y and on receive checks if these are numbers. Constructor is supposed to output message about just created vector.
I do not understand much all this constructor and probably this is one of reasons why this code doesn't work as it is intended to.
destructor is supposed to output info about destroyed object.
there should be available functions to change values of $x and $y
there should be available function to return $x
two more functions: one outputting sum of two vectors, second function supposed to output scalar product which takes as value a number.
There are two things in your code going wrong. See the following code:
class Vector {}
$wekt= new Vector($x, $y);
echo $wekt->addVector(5,7);
Where are $x and $y defined? This is the main reason you are getting the error. You class has a different scope then the global scope, meaning everything you define there is only accessible by $wekt-> as $wekt is defined in the global scope.
Now the second thing is addVector():
echo $wekt->addVector(5,7);
You ask to echo the return of this method, yet no return is defined in that function. Secondly where is the $x and $y defined within the scope of that function?
Change it to something like:
class Vector {
private $list = [];
public function addVector($x, $y) {
$this->list[] = new Vector($x, $y);
return $x + $y;
}
}

php class return; function return

object var $c->$var1 has been changed in class a;
var $new_var has not be changed in function d;
i was a litte puzzled.
my english is poor,can you understand me?
<?php
class a{
public function test () {
$b = new b;
$c = new c;
$b->test($c);
var_dump($c);
}
}
class b{
public function test($c) {
$c->var1 = 2;
return $c;
}
}
class c {
public $var1 = 1;
}
$a = new a;
$a->test();
function d($new_var) {
$new_var = 2;
return $new_var;
}
$new_var = 1;
d($new_var);
echo $new_var
You problem is that you have this function
function d($new_var) {
$new_var = 2;
return $new_var;
}
Where is it true that you maybe pass a different variable as parameter, but then you take that parameter and you decide to set it = 2 and then return it.
If you want to return what you passed you should change it in
function d($new_var) {
return $new_var;
}
Or if you want something similar to test function of class b try tgus
function d($new_var) {
$d->new_var = $new_var;
return $d;
}
So you can access to your $new_var in the returned objecd $d
You expect the following piece of code to change the value for $new_var from 1 to 2, right?
$new_var = 1;
d($new_var);
echo $new_var
Alas, that cannot be, because the returned value is never assigned back to the variable. To make sure the passed variable will retain its new value even outside the scope of the function it was passed to as an argument, you need to pass the variable as a reference instead of as a value, like this:
function d(&$new_var) {
$new_var = 2;
return $new_var;
}
Notice the ampersand (&) in front of the variable name in the signature of the function. This will cause the variable to be passed as a reference, so that it will retain any changes made to it inside the function.

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

Restricting variable access

I need to have a variable that only one function can write (let's call that function a) and that only one other function can read (let's call that function b). Is that possible?
You could use a static variable:
function foo($val=null) {
static $var = null;
if (!is_null($var)) $var = $val;
return $val;
}
Here $var is only visible inside the function foo and is maintained throughout multiple calls:
foo(123);
echo foo(); // 123
foo(456);
echo foo(); // 456
Or use a class with a private member and access/modify it with public methods:
class A {
private $var;
public function setVar($val) {
$this->var = $val;
}
public function getVar() {
return $this->var;
}
}
With this the private member var is only visible to a particular instance of this class:
$obj1 = new A();
$obj1->setVar(123);
$obj2 = new A();
$obj2->setVar(456);
echo $obj1->getVar(); // 123
echo $obj2->getVar(); // 456
If you make the member static, then there is just one for the class instead of for each instance:
class A {
private static $var;
public function setVar($val) {
self::$var = $val;
}
public function getVar() {
return self::$var;
}
}
$obj1 = new A();
$obj1->setVar(123);
$obj2 = new A();
$obj2->setVar(456);
echo $obj1->getVar(); // 456
echo $obj2->getVar(); // 456
You can use a static abstract class.
abstract class Settings
{
private static var $_settings = array();
public static function get($key,$default = false)
{
return isset(self::$_settings[$key]) ? self::$_settings[$key] : $default;
}
public static function set($key,$value)
{
self::$_settings[$key] = $value;
}
}
Example Usage:
Settings::set('SiteName',`SomeResult`);
echo Settings::get('SiteName');
Since 5.3.0, you can use anonymous functions as closures. The advantage here, is that you can hold on to b... which is returned by a... and fire it off when you're ready:
<?php
function a()
{
// Only a() can write to $myVar
$myVar = 42;
$b = function() use ($myVar)
{
// $b can read $myVar
// no one else can
return $myVar;
};
return $b;
}
// get $b
$test = a();
// use $b
echo $test();
?>
Another solution before 5.3.0, but here a has to fire b which may not be that practical:
You can simply create an internal variable and pass it as an argument. You can do this inside a class, or just inside simple functions:
function a()
{
// ...
// Write the variable that
// only this function can write to
$thisVar = 1;
b($thisVar);
//...
}
function b($myVar)
{
// ...
// Do stuff w $myVar, a copy of $thisVar
// Changing $myVar has no effect on $thisVar
//
}
Do you mean friend functions? Because I'd love to be able to do that. So far I haven't found an easy way though (although you could try using Reflection, but that seems like way to much effort).
For me, it usually hasn't been an issue of maintaining data integrity / encapsulation, but of keeping the list of public methods (which is kinda like a class's API) free of clutter. A perfect framework should be easy to use, have obvious function names etc etc etc. Methods intended for use by a single other method really mess things up. The "solution" I've taken to is prefixing those function names by one or two underscores and writing "intended for internal use only" or something to that extent in the comments.

Reference to static method in PHP?

In PHP, I am able to use a normal function as a variable without problem, but I haven't figured out how to use a static method. Am I just missing the right syntax, or is this not possible?
(EDIT: the first suggested answer does not seem to work. I've extended my example to show the errors returned.)
function foo1($a,$b) { return $a/$b; }
class Bar
{
static function foo2($a,$b) { return $a/$b; }
public function UseReferences()
{
// WORKS FINE:
$fn = foo1;
print $fn(1,1);
// WORKS FINE:
print self::foo2(2,1);
print Bar::foo2(3,1);
// DOES NOT WORK ... error: Undefined class constant 'foo2'
//$fn = self::foo2;
//print $fn(4,1);
// DOES NOT WORK ... error: Call to undefined function self::foo2()
//$fn = 'self::foo2';
//print $fn(5,1);
// DOES NOT WORK ... error: Call to undefined function Bar::foo2()
//$fn = 'Bar::foo2';
//print $fn(5,1);
}
}
$x = new Bar();
$x->UseReferences();
(I am using PHP v5.2.6 -- does the answer change depending on version too?)
PHP handles callbacks as strings, not function pointers. The reason your first test works is because the PHP interpreter assumes foo1 as a string. If you have E_NOTICE level error enabled, you should see proof of that.
"Use of undefined constant foo1 - assumed 'foo1'"
You can't call static methods this way, unfortunately. The scope (class) is relevant so you need to use call_user_func instead.
<?php
function foo1($a,$b) { return $a/$b; }
class Bar
{
public static function foo2($a,$b) { return $a/$b; }
public function UseReferences()
{
$fn = 'foo1';
echo $fn(6,3);
$fn = array( 'self', 'foo2' );
print call_user_func( $fn, 6, 2 );
}
}
$b = new Bar;
$b->UseReferences();
In php 5.2, you can use a variable as the method name in a static call, but to use a variable as the class name, you'll have to use callbacks as described by BaileyP.
However, from php 5.3, you can use a variable as the class name in a static call. So:
class Bar
{
public static function foo2($a,$b) { return $a/$b; }
public function UseReferences()
{
$method = 'foo2';
print Bar::$method(6,2); // works in php 5.2.6
$class = 'Bar';
print $class::$method(6,2); // works in php 5.3
}
}
$b = new Bar;
$b->UseReferences();
?>
You could use the full name of static method, including the namespace.
<?php
function foo($method)
{
return $method('argument');
}
foo('YourClass::staticMethod');
foo('Namespace\YourClass::staticMethod');
The name array array('YourClass', 'staticMethod') is equal to it. But I think the string may be more clear for reading.
In PHP 5.3.0, you could also do the following:
<?php
class Foo {
static function Bar($a, $b) {
if ($a == $b)
return 0;
return ($a < $b) ? -1 : 1;
}
function RBar($a, $b) {
if ($a == $b)
return 0;
return ($a < $b) ? 1 : -1;
}
}
$vals = array(3,2,6,4,1);
$cmpFunc = array('Foo', 'Bar');
usort($vals, $cmpFunc);
// This would also work:
$fooInstance = new Foo();
$cmpFunc = array('fooInstance', 'RBar');
// Or
// $cmpFunc = array('fooInstance', 'Bar');
usort($vals, $cmpFunc);
?>
Coming from a javascript background and being spoiled by it, I just coded this:
function staticFunctionReference($name)
{
return function() use ($name)
{
$className = strstr($name, '::', true);
if (class_exists(__NAMESPACE__."\\$className")) $name = __NAMESPACE__."\\$name";
return call_user_func_array($name, func_get_args());
};
}
To use it:
$foo = staticFunctionReference('Foo::bar');
$foo('some', 'parameters');
It's a function that returns a function that calls the function you wanted to call. Sounds fancy but as you can see in practice it's piece of cake.
Works with namespaces and the returned function should work just like the static method - parameters work the same.
This seems to work for me:
<?php
class Foo{
static function Calc($x,$y){
return $x + $y;
}
public function Test(){
$z = self::Calc(3,4);
echo("z = ".$z);
}
}
$foo = new Foo();
$foo->Test();
?>
In addition to what was said you can also use PHP's reflection capabilities:
class Bar {
public static function foo($foo, $bar) {
return $foo . ' ' . $bar;
}
public function useReferences () {
$method = new ReflectionMethod($this, 'foo');
// Note NULL as the first argument for a static call
$result = $method->invoke(NULL, '123', 'xyz');
}
}
"A member or method declared with static can not be accessed with a variable that is an instance of the object and cannot be re-defined in an extending class"
(http://theserverpages.com/php/manual/en/language.oop5.static.php)

Categories