What happens in this code block during php oop? - php

Could someone please explain the third line where Request and $request is used. It would be great if you could provide me a link having an explanation of the same? I just want to know what is happening there.
<?php
class xyz {
public function foo(Request $request){
//some code
}
}

Type hinting:
http://php.net/manual/en/language.oop5.typehinting.php
<?php
// An example class
class MyClass
{
/**
* A test function
*
* First parameter must be an object of type OtherClass
*/
public function test(OtherClass $otherclass) {
echo $otherclass->var;
}
/**
* Another test function
*
* First parameter must be an array
*/
public function test_array(array $input_array) {
print_r($input_array);
}
}
// Another example class
class OtherClass {
public $var = 'Hello World';
}
It throws an error if the argument is not of the type specified:
<?php
// An instance of each class
$myclass = new MyClass;
$otherclass = new OtherClass;
// Fatal Error: Argument 1 must be an object of class OtherClass
$myclass->test('hello');
// Fatal Error: Argument 1 must be an instance of OtherClass
$foo = new stdClass;
$myclass->test($foo);
// Fatal Error: Argument 1 must not be null
$myclass->test(null);
// Works: Prints Hello World
$myclass->test($otherclass);
// Fatal Error: Argument 1 must be an array
$myclass->test_array('a string');
// Works: Prints the array
$myclass->test_array(array('a', 'b', 'c'));
?>

Arguments:
http://php.net/manual/en/functions.arguments.php
Type hints:
http://php.net/manual/en/language.oop5.typehinting.php

An Object of the type Request is being passed to function foo.
It is made available to the function foo in a private variable named $request.

This is a type hint, to tell php to expect an object wich has
$request instanceof Request == true
Please note that this will actually not ensure anything. If $request is null or another object, there will most likely only a catchable fatal error be thrown, and so you have to test for a valid value anyway.

The third line defines a class method called foo that can get a $request argument of type "Request".
This is a security measure for the class developer. Determine that
<?php
class User
{
private $username;
public function get_username()
{
return $this->username;
}
}
class xyz()
{
public function foo(User $currentUser)
{
$currentUser->get_username();
}
}
$x = new xyz();
$u = new User();
$x->foo($u); // That will not produce any error because we pass an Object argument of type User
$name = "my_name";
$x->foo($name); // This will produce an error because we pass a wrong type of argument
?>

Related

PHP Type hinting callable function

Ok, so I have this class method defined to take a callback and I've type hinted it as callable as per the type hinting documentation.
protected function AddTransformData(array $definition,array $where,callable $callback){
$this->transforms[]=[$definition,$where,$callback];
}
Here is an example of where I might call this function. Using the array syntax for passing a method and object as a callback.
public function __construct(PostalZoneMapping $pzm){
$this->pzm=$pzm;
$this->AddTransformData(Countries::region,['filter'],[$this,'TransformId']);
$this->AddTransformData(PostalZones::id,['filter'],[$this,'TransformId']);
$this->ReceiveData();
}
This throws an error, image below, complaining about argument 3 not being callable, but an array. Logically, I guess this makes sense, as it is array, but it's an array of a callable function - surely it must detect that it's a callback?
Is this a PHP quirk or am I doing something wrong?
public function __construct(PostalZoneMapping $pzm){
$this->pzm=$pzm;
$method = 'TransformId';
$callable = fn() => $this->$method();
$this->AddTransformData(Countries::region,['filter'], $callable);
$this->AddTransformData(PostalZones::id,['filter'], $callable);
$this->ReceiveData();
}
if you have PHP version below 7.4 then instead of this:
$callable = fn() => $this->$method();
do this:
$callable = function() use ($method) { $this->$method() };
You also can receive an arguments:
$callable = fn($param) => $this->$method($param);
or
$callable = function($param) use ($method) { $this->$method($param)};
Looks like TransformId is not a method on that class. Maybe its a typo, maybe its a property but not a method.
In order for array to be a valid callback it has to be: A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.
This works:
class A {
function __construct() {
$this->asd2([$this, 'asd']);
}
private function asd() {}
public function asd2(callable $c) {}
}
$a = new A();
This doesnt:
class A {
function __construct() {
$this->asd2([$this, 'somethingElse']);
}
private function asd() {}
public function asd2(callable $c) {}
}
Fatal error: Uncaught TypeError: Argument 1 passed to A::asd2() must be callable, array given, called in
If I'm wrong - paste whole class code including TransformId method.
I create some test code to reproduce the error, having noticed that I declared the callback as private! This code won't work, but will work if you change the TransformId method to protected or public.
<?php
abstract class CommonDataInterface{
private $transforms=[];
/**
* Adds a callback that transform data
*
* #param array $definition Definition, where, if matches, callback is called.
* #param array $where Where to transform data, array values one or more of 'set','insert' or'filter'
* #param callable $callback Function that takes value as parameter, and returns transformed value.
* #return void
*/
protected function AddTransformData(array $definition,array $where,callable $callback){
$this->transforms[]=[$definition,$where,$callback];
}
}
class Api_PostalZoneMapping extends CommonDataInterface{
private $pzm;
public function __construct($pzm){
$this->pzm=$pzm;
$this->AddTransformData(['blah'],['filter'],[$this,'TransformId']);
$this->AddTransformData(['blah2'],['filter'],[$this,'TransformId']);
//$this->ReceiveData();
}
private function TransformId($data){
if($data==-1)
return null;
return $data;
}
}
$p=new Api_PostalZoneMapping('not relevant for test');

PHP - Pass a function into another function and call it [duplicate]

I would like to create a Listener class
class Listener {
var $listeners = array();
public function add(callable $function) {
$this->listeners[] = $function;
}
public function fire() {
foreach($this->listeners as $function) {
call_user_func($function);
}
}
}
class Foo {
public function __construct($listener) {
$listener->add($this->bar);
}
public function bar() {
echo 'bar';
}
}
$listener = new Listener();
$foo = new Foo($listener);
But this code fails with this error:
Notice: Undefined property: Foo::$bar in index.php on line 18
Catchable fatal error: Argument 1 passed to Listener::add() must be callable, null given, called in index.php on line 18 and defined index.php on line 5
What am I doing wrong?
Before PHP 5.4, there was no type named callable, so if you use it as a type hint, it means "the class named callable". If you use PHP >= 5.4, callable is a valid hint.
A callable is specified by a string describing the name of the callable (a function name or a class method name for example) or an array where the first element is an instance of an object and the second element is the name of the method to be called.
For PHP < 5.4, replace
public function add(callable $function)
with:
public function add($function)
Call it with:
$listener->add(array($this, 'bar'));
Methods and properties have separate namespaces in PHP, which is why $this->bar evaluates to null: You're accessing an undefined property.
The correct way to create an array in the form of array($object, "methodName"):
Passing the callback correctly:
$listener->add(array($this, 'bar'));
The type hint you have given is okay—as of PHP 5.4, that is.
I don't think you can specify a callable this way...
Try
$listener->add(array($this, 'bar'));
And see http://php.net/manual/en/language.types.callable.php too.

Using local variable from call in a function

After 9 hours of struggling to get this right, I have turned to the internet for help. I can't seem to find any relevant answers doing a Google search.
I currently have a class called Test. Test accepts a single argument.
<?php
class test {
private $varpassed;
public function getVarpas() {
return $this->varpassed;
}
Public function setVarpas($value) {
$this->varpassed= $value;
}
public function stringGen(){
$testvar = $this->varpassed;
echo $testvar;
}
}
The stringGen function should return the $varpassed variable whenever its called. The value for $varpassed is set using the setVarpas function. However, when ever I call the stringGen() method I only seem to be getting the following error:
Fatal error: Using $this when not in object context in file.php line 14.
Pointing to this line:
$testvar = $this->varpassed;
Is there any other way to pass the variable to the stringGen method? I've tried using:
self::$this->varpassed;
Which also throws an error.
first create an instance of the object (so you can use $this in the context), for example:
$test = new test();
then you can call:
$test->setVarpas('Hello World!');
now you can call:
$test->stringGen();
you have to do something like this
$var = new test();
$var->setVarpas("Hello");
$var->stringGen(); // this will echo Hello
$this is used when you are withing class. outside class you have to use class object.
1) Change this: class test() to class test
2) Create and instance first something like $t1 = new test();
3) Call the function $t1->setVarpas(5);
4) Now you can call the function $t1->stringGen();
Fixed:
<?php
class test
{
private $varpassed;
public function getVarpas() {
return $this->varpassed;
}
Public function setVarpas($value) {
$this->varpassed= $value;
}
public function stringGen(){
$testvar = $this->varpassed;
echo $testvar;
}
}
$t1 = new test();
$t1->setVarpas(5);
$t1->stringGen();
OUTPUT:
5
You should not declare a class with parentheses.
Use
class test {
instead of
class test(){

Passing an instance method as argument in PHP

I would like to create a Listener class
class Listener {
var $listeners = array();
public function add(callable $function) {
$this->listeners[] = $function;
}
public function fire() {
foreach($this->listeners as $function) {
call_user_func($function);
}
}
}
class Foo {
public function __construct($listener) {
$listener->add($this->bar);
}
public function bar() {
echo 'bar';
}
}
$listener = new Listener();
$foo = new Foo($listener);
But this code fails with this error:
Notice: Undefined property: Foo::$bar in index.php on line 18
Catchable fatal error: Argument 1 passed to Listener::add() must be callable, null given, called in index.php on line 18 and defined index.php on line 5
What am I doing wrong?
Before PHP 5.4, there was no type named callable, so if you use it as a type hint, it means "the class named callable". If you use PHP >= 5.4, callable is a valid hint.
A callable is specified by a string describing the name of the callable (a function name or a class method name for example) or an array where the first element is an instance of an object and the second element is the name of the method to be called.
For PHP < 5.4, replace
public function add(callable $function)
with:
public function add($function)
Call it with:
$listener->add(array($this, 'bar'));
Methods and properties have separate namespaces in PHP, which is why $this->bar evaluates to null: You're accessing an undefined property.
The correct way to create an array in the form of array($object, "methodName"):
Passing the callback correctly:
$listener->add(array($this, 'bar'));
The type hint you have given is okay—as of PHP 5.4, that is.
I don't think you can specify a callable this way...
Try
$listener->add(array($this, 'bar'));
And see http://php.net/manual/en/language.types.callable.php too.

get function name that called function without arguments

I have a class admin_model with the private method admin_form()
There are a number of other public functions that call this method.
Is there a way to get the name of the function that called admin_form() from INSIDE admin_form()?
I could easily add an argument when calling admin_form() like:
$this -> admin_form(__FUNCTION__);
then inside admin_form($caller) I have the caller. It will be $caller
But i was hoping there was a way to do this WITHOUT passing arguments.
Any Ideas??
Cheers,
Alex
You can do this with debug_backtrace():
<?php
class admin_model {
public function foo() {
$this->admin_form();
}
public function bar() {
$this->admin_form();
}
private function admin_form() {
// Get the current call stack
$stack = debug_backtrace();
// Remove this call (admin_form()) from the stack
array_shift($stack);
// The calling method is now on the top of the stack
$lastCall = array_shift($stack);
$callingMethod = $lastCall['function'];
echo "admin_form() called by method: $callingMethod\n";
}
}
$model = new admin_model();
$model->foo();
$model->bar();
Output:
admin_form() called by method: foo
admin_form() called by method: bar
But, as others have pointed out, this is bad practice and you should rethink your design.
No matter,
For my requirement this functionality is useful rather that 'bad coding'.
Anyway the answer is:
$e = new Exception();
$trace = $e -> getTrace();
$caller = $trace[1]["function"];
This will get the function name of the caller.

Categories