Using function pointer with class or function in php - php

I am converting an old project that uses all functions to use a class. Not all installed instances will be updated so I have to have the code work with the function or the class but I can't get it to work. Here is an outline of the code I am using:
function GetStatus($id) {
return true;
}
class myclass (
public function GetStatus($id) {
return true;
}
}
if (class_exists('myclass')) {
$fcn = $myclass->GetStatus;
} else {
$fcn = GetStatus;
}
echo 'result = ' . $fcn($user_id);
So the code checks if the class exists and uses that method, else it uses the function. The code runs without errors but when the class method is used the return is not shown. That is, the results are
result = 1 //when function is used
result = //when method is used
Is this possible? If it matters, the minimum php version is 7.1.

To make a callable from an instance and method, you use an array containing the instance and the method name.
$fcn = [$myclass, 'GetStatus'];

Checking for a myclass existance when you already have the myclass instance stored in a $myclass variable makes no sense. Maybe you should check for a method existance?
if (method_exists($myclass, 'GetStatus')) {
$fcn = function($id) use ($myclass){
return $myclass->GetStatus($id);
};
} else {
$fcn = function($id){
return GetStatus($id);
};
}
echo 'result = ' . $fcn($user_id);

Related

How to make a class stored data to a variable an callback with method?

I am interested in how this works:
<?php
$Query = $mysqli->query("select * from table");
$Query->fetch_array(); // <== How to make $Query a class/method like this?
?>
How do you assign a method to a variable and then have that variable be able to call another method like the $mysqli and $Query example above?
One way to achieve what you are (I think) referring to, is by returning an object. It goes against the principle of dependency injection, but it's one way to do it.
class MyClassA
{
public function myFunction()
{
return new MyClassB();
}
}
class MyClassB
{
public function execute()
{
return true;
}
}
// Start use
$class = new MyClassA();
// Assign variable to function which returns object
$newObj = $class->myFunction();
// Will write "1" because now $newObj is MyClassB()
echo $newObj->execute();
Another way is to return $this from the first method. The usage of the above object would work identical in this instance, however you also allow another principle known as method chaining:
class MyClassA
{
public function myFunction()
{
return $this;
}
public function execute()
{
return true;
}
}
// Same as above works
$class = new MyClassA();
$sameObj = $class->myFunction();
echo $sameObj->execute();
// Allowing for Method Chain
$class = new MyClassA();
// Allowing for chaining
echo $class->myFunction()->execute();
You have to instantiate your class and call it's function with ->
$class = new MyClass(); // Instantiate class
$class->myFunction(); // Use it's function
PHP manual example of creating a class:
http://php.net/manual/en/language.oop5.basic.php

Set an array from class and get him outside a class

I would create an array with ID posts from inside a function, and get him outside the class.
My code:
<?php
class cat_widget extends WP_Widget {
private $newHomePost = array();
function widget($args, $instance){
//...
foreach($img_ids as $img_id) {
if (is_numeric($img_id)) {
$this->setNewHomePost($newsCounter,$post->ID);
$newsCounter++;
//...
}
}
}
function setNewHomePost($num, $value){
$newHomePost[$num] = $value;
}
function getNewHomePost(){
return "ID: ".$this->newHomePost[0];
}
}
$testA = new cat_widget();
echo $testA->getNewHomePost();
?>
I receive on screen this resuld:
ID:
(without the id)
But if I insert inside setNewHomePost() an echo for the array, I'll obtain correctly the array but inside and not outside class.
function setNewHomePost($num, $value){
$newHomePost[$num] = $valore;
echo $newHomePost[0];
}
So seem that the array works fine inside the "function widget", but doesn't works outside it.
Can someone help me, please?
function setNewHomePost($num, $value){
$newHomePost[$num] = $value;
}
This creates a local variable named $newHomePost, setting a value at an index and returning. Once it returns, the local variable disappears. From the linked manual page:
Any variable used inside a function is by default limited to the local function scope.
You want to set the class member property newHomePost instead:
function setNewHomePost($num, $value) {
$this->newHomePost[$num] = $value;
}
Update
This is how you currently have the get method defined:
function getNewHomePost() {
return "ID: " . $this->newHomePost[0];
}
I suspect you're still fiddling with this and trying to get it to work. If you really want to just only ever return the 0'th index, try something like this instead:
function getNewHomePost() {
return isset($this->newHomePost[0]) ? $this->newHomePost[0] : null;
}
When building a class remember that you cannot make any assumptions about what order your public methods can be called from another object or calling code (even if the calling code itself exists inside of the class. The methods are public, meaning anything can call them). The code above assumes nothing in that you do not have to call addNewHomePost prior to getNewHomePost. I imagine if you look in your logs you may see a few Notice: Undefined index.. type errors.
Also be sure to check on the calling side:
$myClass = new cat_widget;
$myClass->setNewHomePost(0, 'my new home post!');
$homePost = $myClass->getNewHomePost();
echo $homePost ? $homePost : 'None';
I think a better getter method would probably look like this:
function getNewHomePost($i) {
return isset($this->newHomePost[$i]) ? $this->newHomePost[$i] : null;
}

can I pass __construct parameters after a class has been instantiated into an object?

I have a similar code snippet like this
class Search
{
public function search($for, $regEx, $flag) //I would like this to be the constructor
{
// logic here
return $this;
}
}
Then I have another class that creates an object from it, later than tries to use the object.
class MyClass
{
public function start()
{
$this->search = new Search();
}
public function load()
{
$this->search($for, $regEx, $flag);
}
}
My question is, is it possible to create an object first THEN give it the parameters?
I know there are some way around this BUT I only ask because I want to use the object like this
$this->search($params);
// I have my methods chained, so I could use it in one line like
// $this->search($params)->hasResults();
if ($this->search->hasResults()) {
echo 'found stuff';
} else {
echo 'didn't find anything';
}
The way I have it set up right now, I would need to use it like this
$this->search->search($params);
if ($this->search->hasResults()) {
echo 'found stuff';
} else {
echo 'didn't find anything';
}
I have a method called search() that does the logic, and I don't want to be redundant in my naming nor do I want to change the name of the method.
I know another way to keep the visual appeal sane I could pass a variable like so
$search = $this->search->search($params);
then
$search->hasResults();
At the same time I am trying to introduce myself to new OOP concepts and learn from them. Would this require passing things by reference? or setting up some type of magic method?
While the previous anwsers show that you can, I wouldn't use it, because it breaks the concept of encapsulation. A proper way to achieve what you want is the following
class Search
{
public function __constructor($for='', $regEx='', $flag='')
{
$this->Setup($for, $regEx, $flag);
}
public function Setup($for, $regEx, $flag)
{
//assign params
//clear last result search
//chain
return $this;
}
public function search()
{
// logic here
return $this;
}
}
In this way, you can reuse the object and have the params in the constructor, without breaking encapsulation.
Yes it is possible
See the below example
<?php
class a{
public $a = 5;
public function __construct($var){
$this->a = $var;
}
}
$delta = new a(10);
echo $delta->a."\n";
$delta->__construct(15);
echo $delta->a."\n";
Output will be:
10 15
Yep, you can.
class Example {
public $any;
function __counstruct($parameters,$some_text) {
$this->any=$some_text;
return $this->any;
}
}
You can call constructor:
$obj = new Example (true,'hello');
echo $obj->any;
$obj->__construct(true,'bye-bye');
echo $obj->any;
I was able to create the visual coding I wanted by using the __call() magic method like this
public function __call($name, $params)
{
$call = ucfirst($name);
$this->$name = new $call($params);
}
from there I could use this
$this->test->search($params);
$this->test->search->hasResults();
I of course now set the search() method to the class constructor

PHP get_called_class() alternative

I've got an Abstract PHP superclass, which contains code that needs to know which subclass its running under.
class Foo {
static function _get_class_name() {
return get_called_class();
//works in PHP 5.3.*, but not in PHP 5.2.*
}
static function other_code() {
//needs to know
echo self::_get_class_name();
}
}
class Bar extends Foo {
}
class FooBar extends Foo {
}
Bar::other_code(); // i need 'Bar'
FooBar::other_code(); // i need 'FooBar'
This would work if I called the function get_called_class() -- however, this code is going to be run in PHP version 5.2.*, so that function is not available.
There's some custom PHP implementations of get_called_class() out there, but they all rely on going thru the debug_backtrack(), parsing a file name & line number, and running a regex (as the coder is not aware that PHP 5.2 has reflection) to find the class name. This code needs to be able to be run with php, ie. not only from a .php file. (It needs to work from a php -a shell, or an eval() statement.)
Ideally, a solution would work without requiring any code to be added to the subclasses… The only potential solution I can see though is adding the following code to each subclass, which is obviously a disgusting hack:
class FooBar extends Foo {
static function _get_class_name() {
return 'FooBar';
}
}
EDIT: Wait, this doesn't even seem to work. It would've been my last resort. Can anybody think of something similar to this solution that'd get me the required functionality. Ie., I'm willing to accept a solution that requires me to add one function or variable to each subclass telling it what its class name is. Unfortunately, it seems that calling self::_get_class_name() from the superclass calls the parent class' implementation, even if the subclass has overridden it.
In reality it is often helpful to know the actual called (sub)class when executing a superclass method, and I disagree that there's anything wrong with wanting to solve this problem.
Example, my objects need to know the class name, but what they do with that information is always the same and could be extracted into a superclass method IF I was able to get the called class name. Even the PHP team thought this was useful enough to include in php 5.3.
The correct and un-preachy answer, as far as I can tell, is that prior to 5.3, you have to either do something heinous (e.g. backtrace,) or just include duplicate code in each of the subclasses.
Working solution:
function getCalledClass(){
$arr = array();
$arrTraces = debug_backtrace();
foreach ($arrTraces as $arrTrace){
if(!array_key_exists("class", $arrTrace)) continue;
if(count($arr)==0) $arr[] = $arrTrace['class'];
else if(get_parent_class($arrTrace['class'])==end($arr)) $arr[] = $arrTrace['class'];
}
return end($arr);
}
This is not possible.
The concept of "called class" was introduced in PHP 5.3. This information was not tracked in previous versions.
As an ugly work-around, you could possibly use debug_backtrace to look into the call stack, but it's not equivalent. For instance, in PHP 5.3, using ClassName::method() doesn't forward the static call; you have no way to tell this with debug_backtrace. Also, debug_backtrace is relatively slow.
The PHP/5.2 alternative to late static binding that keeps duplicate code to the minimum while avoiding weird hacks would be to create one-liners on child classes that pass the class name as argument:
abstract class Transaction{
public $id;
public function __construct($id){
$this->id = $id;
}
protected static function getInstanceHelper($class_name, $id){
return new $class_name($id);
}
}
class Payment extends Transaction{
public static function getInstance($id){
return parent::getInstanceHelper(__CLASS__, $id);
}
}
class Refund extends Transaction{
public static function getInstance($id){
return parent::getInstanceHelper(__CLASS__, $id);
}
}
var_dump( Payment::getInstance(1), Refund::getInstance(2) );
object(Payment)#1 (1) {
["id"]=>
int(1)
}
object(Refund)#2 (1) {
["id"]=>
int(2)
}
The solution is:
get_class($this);
However, I don't know if this sentence works in static functions. Give it a try and tell me your feedback.
This hack includes the heinous use of debug_backtrace... not pretty, but it does the job:
<?php
function callerName($functionName=null)
{
$btArray = debug_backtrace();
$btIndex = count($btArray) - 1;
while($btIndex > -1)
{
if(!isset($btArray[$btIndex]['file']))
{
$btIndex--;
if(isset($matches[1]))
{
if(class_exists($matches[1]))
{
return $matches[1];
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
$lines = file($btArray[$btIndex]['file']);
$callerLine = $lines[$btArray[$btIndex]['line']-1];
if(!isset($functionName))
{
preg_match('/([a-zA-Z\_]+)::/',
$callerLine,
$matches);
}
else
{
preg_match('/([a-zA-Z\_]+)::'.$functionName.'/',
$callerLine,
$matches);
}
$btIndex--;
if(isset($matches[1]))
{
if(class_exists($matches[1]))
{
return $matches[1];
}
else
{
continue;
}
}
else
{
continue;
}
}
}
return $matches[1];
}
I have asked a question like this before, because I wanted a parent to have a factory method that was something like this
public static function factory() {
return new __CLASS__;
}
But it always returned the parent class, not the inherited one.
I was told that it is not possible without late static binding. It was introduced in PHP 5.3. You can read the documentation.
This function does the same job but works with instances too:
if (!function_exists('get_called_class')) {
function get_called_class() {
$bt = debug_backtrace();
/*
echo '<br><br>';
echo '<pre>';
print_r($bt);
echo '</pre>';
*/
if (self::$fl == $bt[1]['file'] . $bt[1]['line']) {
self::$i++;
} else {
self::$i = 0;
self::$fl = $bt[1]['file'] . $bt[1]['line'];
}
if ($bt[1]['type'] == '::') {
$lines = file($bt[1]['file']);
preg_match_all('/([a-zA-Z0-9\_]+)::' . $bt[1]['function'] . '/', $lines[$bt[1]['line'] - 1], $matches);
$result = $matches[1][self::$i];
} else if ($bt[1]['type'] == '->') {
$result = get_class($bt[1]['object']);
}
return $result;
}
}
<?php
class Foo {
private static $instance;
static function _get_class_name() {
return self::myNameIs();
}
static function other_code() {
//needs to know
echo self::_get_class_name();
}
}
class Bar extends Foo {
public static function myNameIs() {
self::$instance = new Bar();
return get_class(self::$instance);
}
}
class FooBar extends Foo {
public static function myNameIs() {
self::$instance = new FooBar();
return get_class(self::$instance);
}
}
Bar::other_code(); // i need 'Bar'
FooBar::other_code(); // i need 'FooBar'

Accept function as parameter in PHP

I've been wondering whether it is possible or not to pass a function as a parameter in PHP. I want something similar to when you're programming the following code in JavaScript:
object.exampleMethod(function(){
// some stuff to execute
});
What I want is to execute that function somewhere in exampleMethod. Is that possible in PHP?
It's possible if you are using PHP 5.3.0 or higher.
See Anonymous Functions in the manual.
In your case, you would define exampleMethod like this:
function exampleMethod($anonFunc) {
//execute anonymous function
$anonFunc();
}
Just to add to the others, you can pass a function name:
function someFunc($a)
{
echo $a;
}
function callFunc($name)
{
$name('funky!');
}
callFunc('someFunc');
This will work in PHP4.
Valid: (PHP 4 >= 4.0.1, PHP 5, PHP 7)
You can also use create_function to create a function as a variable and pass it around. Though, I like the feeling of anonymous functions better. Go zombat.
Update 09 - Jan - 2022
Warning
This function has been DEPRECATED as of PHP 7.2.0, and REMOVED as of PHP 8.0.0. Relying on this function is highly discouraged.
Just code it like this:
function example($anon) {
$anon();
}
example(function(){
// some codes here
});
it would be great if you could invent something like this (inspired by Laravel Illuminate):
Object::method("param_1", function($param){
$param->something();
});
PHP VERSION >= 5.3.0
Example 1: basic
function test($test_param, $my_function) {
return $my_function($test_param);
}
test("param", function($param) {
echo $param;
}); //will echo "param"
Example 2: std object
$obj = new stdClass();
$obj->test = function ($test_param, $my_function) {
return $my_function($test_param);
};
$test = $obj->test;
$test("param", function($param) {
echo $param;
});
Example 3: non static class call
class obj{
public function test($test_param, $my_function) {
return $my_function($test_param);
}
}
$obj = new obj();
$obj->test("param", function($param) {
echo $param;
});
Example 4: static class call
class obj {
public static function test($test_param, $my_function) {
return $my_function($test_param);
}
}
obj::test("param", function($param) {
echo $param;
});
According to #zombat's answer, it's better to validate the Anonymous Functions first:
function exampleMethod($anonFunc) {
//execute anonymous function
if (is_callable($anonFunc)) {
$anonFunc();
}
}
Or validate argument type since PHP 5.4.0:
function exampleMethod(callable $anonFunc) {}
Tested for PHP 5.3
As i see here, Anonymous Function could help you:
http://php.net/manual/en/functions.anonymous.php
What you'll probably need and it's not said before it's how to pass a function without wrapping it inside a on-the-fly-created function.
As you'll see later, you'll need to pass the function's name written in a string as a parameter, check its "callability" and then call it.
The function to do check:
if( is_callable( $string_function_name ) ){
/*perform the call*/
}
Then, to call it, use this piece of code (if you need parameters also, put them on an array), seen at : http://php.net/manual/en/function.call-user-func.php
call_user_func_array( "string_holding_the_name_of_your_function", $arrayOfParameters );
as it follows (in a similar, parameterless, way):
function funToBeCalled(){
print("----------------------i'm here");
}
function wrapCaller($fun){
if( is_callable($fun)){
print("called");
call_user_func($fun);
}else{
print($fun." not called");
}
}
wrapCaller("funToBeCalled");
wrapCaller("cannot call me");
Here's a class explaining how to do something similar :
<?php
class HolderValuesOrFunctionsAsString{
private $functions = array();
private $vars = array();
function __set($name,$data){
if(is_callable($data))
$this->functions[$name] = $data;
else
$this->vars[$name] = $data;
}
function __get($name){
$t = $this->vars[$name];
if(isset($t))
return $t;
else{
$t = $this->$functions[$name];
if( isset($t))
return $t;
}
}
function __call($method,$args=null){
$fun = $this->functions[$method];
if(isset($fun)){
call_user_func_array($fun,$args);
} else {
// error out
print("ERROR: Funciton not found: ". $method);
}
}
}
?>
and an example of usage
<?php
/*create a sample function*/
function sayHello($some = "all"){
?>
<br>hello to <?=$some?><br>
<?php
}
$obj = new HolderValuesOrFunctionsAsString;
/*do the assignement*/
$obj->justPrintSomething = 'sayHello'; /*note that the given
"sayHello" it's a string ! */
/*now call it*/
$obj->justPrintSomething(); /*will print: "hello to all" and
a break-line, for html purpose*/
/*if the string assigned is not denoting a defined method
, it's treat as a simple value*/
$obj->justPrintSomething = 'thisFunctionJustNotExistsLOL';
echo $obj->justPrintSomething; /*what do you expect to print?
just that string*/
/*N.B.: "justPrintSomething" is treated as a variable now!
as the __set 's override specify"*/
/*after the assignement, the what is the function's destiny assigned before ? It still works, because it's held on a different array*/
$obj->justPrintSomething("Jack Sparrow");
/*You can use that "variable", ie "justPrintSomething", in both ways !! so you can call "justPrintSomething" passing itself as a parameter*/
$obj->justPrintSomething( $obj->justPrintSomething );
/*prints: "hello to thisFunctionJustNotExistsLOL" and a break-line*/
/*in fact, "justPrintSomething" it's a name used to identify both
a value (into the dictionary of values) or a function-name
(into the dictionary of functions)*/
?>
Simple example using a class :
class test {
public function works($other_parameter, $function_as_parameter)
{
return $function_as_parameter($other_parameter) ;
}
}
$obj = new test() ;
echo $obj->works('working well',function($other_parameter){
return $other_parameter;
});
Here is a simple procedural example of how you could implement validation of multiple data items using separate functions for each data item validation, passed as an array of functions argument to a master validations function, with the data to be validated (the arguments to the functions) passes as the other array argument to the master validation function. Useful for writing generic code to validate form data.
<?php
function valX($value) {
echo "<p>Validating $value == 5</p>";
if ($value == 5) {
return true;
} else {
return false;
}
}
function valY($value) {
echo "<p>Validating $value == 6</p>";
if ($value == 6) {
return true;
} else {
return false;
}
}
function validate($values, $functions) {
for ($i = 0; $i < count($values); $i++) {
if ($functions[$i]($values[$i])) {
echo "<p>$values[$i] passes validation</p>";
} else {
echo "<p>$values[$i] fails validation</p>";
}
}
}
$values = [5, 9];
$functions = ['valX', 'valY'];
validate($values, $functions);
?>

Categories