PHP dynamic methods in constructor - php

I want to be able to create methods within __construct
I tried using lambda in the following way
// This is what I am trying to achieve as an end result
class A extends Z{
public function __construct() {
parent::__construct()
}
public function myfunc() { // do something }
}
// This was an attempt to implement it
class A extends Z{
public function __construct() {
//example
if ($something_is_true) {
$this->myfunc = function () {}
}
parent::__construct()
}
}
I hope this explains what I am trying to achieve
EDIT
I have URLs mapped to functions, and I want to have some logic to determine what URL-mapped-functions exist on the class

Don't think that's possible. But another way to dynamically 'create' methods within a class is to use the magic __call() method.
With this method implemented, any attempt to call a non-existent method on an object will call the __call() method instead. The first parameter passed in will be the name of the function that the user called, and the second parameter will be the arguments.
See the manual for further details.

Once a class has been defined, you can't add new methods to it using standard PHP. I'd advise using __call as well but you can also accomplish what you want, if you're ok with using variable variables, by creating the function contents dynamically with create_function:
<?php
class A
{
public function __construct()
{
$this->addUpEchoAndReturn=create_function('$a,$b','$c=$a+$b;echo "$a+$b=$c<hr />";return $c;');
}
public function add_up_and_echo($a,$b,$c,$d)
{
$fn=$this->addUpEchoAndReturn;
return $fn($fn($a, $b),$fn($c, $d));
}
}
$x=new A();
$result=$x->add_up_and_echo(3,4,5,25);
echo "<hr /><hr />Final Result: $result";
?>

Related

Calling a Wordpress function out of class

I have a woocommerce plugin that has a class Foo:
function wc_foo_init(){
class WC_Foo extends WC_Shipping_Method{
$var=get_option(); //gets an option for this session
function sayHello(){
echo $var;
}
new WC_Foo();
}
I want to call sayHello() out of the Foo class:
function bar(){
WC_Foo->sayHello();
}
But I get this error:
Fatal error: Call to a member function `sayHello` on a non-object.
You must instantiate class before make call of its methods:
$foo = new WC_Foo();
$foo->sayHello();
or if your php version is greater than 5.4 you can do:
(new WC_Foo())->sayHello();
Use $this selector if you are calling the method within the class
function bar(){
$this->sayHello();
}
If you want to call the method from other place,
you need to instantiate the class like this:
$object = new WC_Foo();
$object->sayHello();
Or make the method static like this:
public static function sayHello(){
echo "Hello";
}
And call it like this:
WC_Foo::sayHello();
// this way you dont need $object = new WC_Foo();
This might not be the full code, so it's pretty weird what you have there, but let's go.
Since you have a function to init your object, you would probably want to at least return that instance. This code might help you understand:
function init_foo(){
class foo{
function say(){
echo 'hello';
}
}
$foo1 = new Foo();
return $foo1;
}
function bar($foo3){
$foo3->say();
}
$foo2 = init_foo();
bar($foo2);
So, first we create the object and return it. Then we inject it in the bar function, just needing to call the method after that. (I used different var names so it's easier to understand scope)

Adding Parameters after creating an object OOP PHP

REVISED
I have a simple question, but being new to OOP I am not sure if this is possible.
Currently I have a class with one function that accepts an argument.
What the actual function does is irrelevant.
<?php
class Method {
public function show($parameter){
echo $parameter;
}
}
?>
I create the object like this...
$this->Method = new Method();
And use it like this...
$this->Method->show($parameter);
So the question is, can my function be set up in a way to simplify the use to
this...
$this->Method($parameter);
I tried by changing the function to a __construct and using the above line of code but it fails since the new Method() was created without a $parameter specified.
I was hoping to be able to pass the $parameter after the new Method(); was called.
Yes, you can do this. If you add an __invoke() method to your class, instances of that class can be called like you would a method.
class Method {
public function __invoke($param) {
echo $param;
}
}
Then you can use it in your class the way you want to
$this->Method = new Method;
$this->Method('something'); // echos something
If you still want to have the show method (or whatever the method actually is) as well, you can leave it there and just call it in __invoke instead.
class Method {
public function show($param) {
echo $param;
}
public function __invoke($param) {
$this->show($param);
}
}
Another possibility, because it looks like you are wanting to be able to use an object like you would use a function, is to define a trait and use it in the object that currently has a Method instead of using a Method class. If you create a trait like:
trait CanUseMethod {
public function Method ($parameter) {
echo $parameter;
}
}
Then in the class that needs to use Method, instead of
$this->Method = new Method;
You can use the trait like this:
class Example {
use CanUseMethod;
}
Then your Example class will be able to use Method without creating a new object.

Making a method in PHP automatically run some code after being called. Possible?

I'm not really sure if what I am looking for has a name, so it has been a bit difficult for me to search for, so I apologise if what I am asking has already been answered here before.
The situation is that I have an abstract class which has, of course, many other classes which extend it.
The abstract method in the abstract class is called run() and all of the extending classes define this method.
My problem is that I want to call some common code after the run() method has been called, but I want to know if there is a better way to do this.
I could of course just paste my common code into each and every extending class's run() method, but if I do that then it would be a lot of work for me to make simple changes from that point onward.
I could also put my common code into a method in the parent class and then call if from the extending class's run() method with $this.
But my question is, is there a better way to do this, or do I have to either use the $this keyword or paste in the code into each class's?
Here is a small example of what I want to do with my current idea:
abstract class Parent_Class {
public abstract function run();
protected function common_code() {
// Common code here
}
}
class Child_Class {
public function run() {
// Code here
// I want some common code to run after the run method has been called
$this->common_code(); // Is this the best way to do it?
}
}
Or is it possible to somehow tell the class that when the run() method has been called to automatically run the common_code() method?
A far simpler way to do this would to simply have a third method which calls run() and then calls common_code(). Subclasses can then override run() all they want.
abstract class Parent_Class {
public abstract function run();
protected function common_code() {
// Common code here
}
protected function start() {
$this->run();
$this->common_code();
}
}
class Child_Class {
public function run() {
// Code here
}
}
Based on Bradley Forster answer, you can define the method as protected, so when it's called from outside the class, you can intercept the event with php magic __call metod because
__call() is triggered when invoking inaccessible methods in an object context.
and then you can execute that method from the __call function
class A {
public function __call($method, $args){
if(!method_exists($this, $method))
throw new Exception("Call to undefined method ".__CLASS__."::$method()");
echo "doing something BEFORE function 'run' execution\n";
$retval = call_user_func_array(array($this, $method), $args);
echo "doing something AFTER function 'run' execution\n";
return $retval;
}
protected function run() {
echo "function 'run' executed\n" ;
}
}
$a = new A;
$a->run();
The answer given by Amber is nice and simple. But requires you to put your data in run() but call start(). Here is an alternative that allows you to have your code $a->run() in all your scripts, and $a->run() with your common code, but encapsulated in a namespace.
File hooks.php
<?php
// File: hooks.php
namespace hook;
class processHooks {
public function __construct() { /* Fatal Error without constructor */ }
protected function processHooks($_c, $method, $args) {
/* Swap the next two callbacks to run your custom code after */
call_user_func_array("\hook\\{$_c}::{$method}", $args);
return call_user_func_array(array($_c,$method), $args);
}
}
class A {
public function foo() {
echo 'Doing code stuff BEFORE calling child function....<br>';
}
}
File regular_file.php
<?php
// File: regular_file.php
include "hooks.php";
class A extends \hook\processHooks {
/* All that is required is this function
* and the function with common code to be protected
*/
public function __call($method, $args) {
self::processHooks(__CLASS__, $method, $args);
}
protected function foo() {
echo 'Method is called....<br>';
}
}
$a = new A();
$a->foo();
This works beacause method foo of class A in regular_file.php is protected, so it's not callable outside the class, so calling it triggers PHP magic method __call
__call() is triggered when invoking inaccessible methods in an object context.

call a static method inside a class?

how do i call a static method from another method inside the same class?
$this->staticMethod();
or
$this::staticMethod();
self::staticMethod();
More information about the Static keyword.
Let's assume this is your class:
class Test
{
private $baz = 1;
public function foo() { ... }
public function bar()
{
printf("baz = %d\n", $this->baz);
}
public static function staticMethod() { echo "static method\n"; }
}
From within the foo() method, let's look at the different options:
$this->staticMethod();
So that calls staticMethod() as an instance method, right? It does not. This is because the method is declared as public static the interpreter will call it as a static method, so it will work as expected. It could be argued that doing so makes it less obvious from the code that a static method call is taking place.
$this::staticMethod();
Since PHP 5.3 you can use $var::method() to mean <class-of-$var>::; this is quite convenient, though the above use-case is still quite unconventional. So that brings us to the most common way of calling a static method:
self::staticMethod();
Now, before you start thinking that the :: is the static call operator, let me give you another example:
self::bar();
This will print baz = 1, which means that $this->bar() and self::bar() do exactly the same thing; that's because :: is just a scope resolution operator. It's there to make parent::, self:: and static:: work and give you access to static variables; how a method is called depends on its signature and how the caller was called.
To see all of this in action, see this 3v4l.org output.
This is a very late response, but adds some detail on the previous answers
When it comes to calling static methods in PHP from another static method on the same class, it is important to differentiate between self and the class name.
Take for instance this code:
class static_test_class {
public static function test() {
echo "Original class\n";
}
public static function run($use_self) {
if($use_self) {
self::test();
} else {
$class = get_called_class();
$class::test();
}
}
}
class extended_static_test_class extends static_test_class {
public static function test() {
echo "Extended class\n";
}
}
extended_static_test_class::run(true);
extended_static_test_class::run(false);
The output of this code is:
Original class
Extended class
This is because self refers to the class the code is in, rather than the class of the code it is being called from.
If you want to use a method defined on a class which inherits the original class, you need to use something like:
$class = get_called_class();
$class::function_name();
In the later PHP version self::staticMethod(); also will not work. It will throw the strict standard error.
In this case, we can create object of same class and call by object
here is the example
class Foo {
public function fun1() {
echo 'non-static';
}
public static function fun2() {
echo (new self)->fun1();
}
}
call a static method inside a class
className::staticFunctionName
example
ClassName::staticMethod();

Is class being called from another class

Suppose I have the following code:
class siteMS
{
...
function __CONSTRUCT()
{
require 'config.php';
$this->config = new siteMSConfig;
...
}
...
}
From inside the siteMSConfig class can I determine weather or not it is being called from inside the siteMS class?
Yes, but there's no "pretty" way to do it - you'll end up looking through a backtrace or something similar.
It would be better to pass an (optional?) parameter to the siteMSConfig constructor like this:
class siteMSConfig
{
public function __construct($inSiteMS = false)
{
}
}
or alternatively, subclass siteMSConfig:
class siteMSsiteMSConfig extends siteMSConfig
{
public function __construct()
{
// Possibly call parent::__construct();
}
}
Technically yes, you could use debug_backtrace to figure out who your caller was.
Writing a class which alters its behaviour based purely on where it called from is asking for a world of pain later on though. Why not parameterise the different behaviour, or make a subclass?
I guess you have to pass it with variable, from what place you called it
$this->config = new siteMSConfig ('siteMS');

Categories