I have two classes:
class Init {
public function test() {
echo 1;
}
public static function loadSecond() {
// Load the class
}
}
class Second extends Init {
public function test2() {
echo 2;
}
}
I need to load Second class only by request. For example:
$init = new Init();
$init->test();
$second = $init::loadSecond();
$second->test2();
Replace // Load the class with
return new Second()
You just need to create a new object. (I do not know why you need it to be that way, but this should work for your purpose.
I'm not sure what you need to do.
If you mean to include a class whenever you need it automatically :
As Marcin Orlowski mentionned it, what you need is to use the autoloading function of PHP.
Basically it should look like :
function __autoload ($name)
{
include "/path/to/my/includes/" . $name . "inc.php";
}
If you mean creating an object from another class, you should probably do like
class Init {
public function test() {
echo 1;
}
public static function loadSecond() {
return new Second;
}
}
class Second extends Init {
public function test2() {
echo 2;
}
}
What you need is class autoloading feature implemented. It's basically supported by PHP, so follow the docs: http://php.net/manual/pl/language.oop5.autoload.php
Related
I have two classes: Action and MyAction. The latter is declared as:
class MyAction extends Action {/* some methods here */}
All I need is method in the Action class (only in it, because there will be a lot of inherited classes, and I don’t want to implement this method in all of them), which will return classname from a static call. Here is what I’m talking about:
Class Action {
function n(){/* something */}
}
And when I call it:
MyAction::n(); // it should return "MyAction"
But each declaration in the parent class has access only to the parent class __CLASS__ variable, which has the value “Action”.
Is there any possible way to do this?
__CLASS__ always returns the name of the class in which it was used, so it's not much help with a static method. If the method wasn't static you could simply use get_class($this). e.g.
class Action {
public function n(){
echo get_class($this);
}
}
class MyAction extends Action {
}
$foo=new MyAction;
$foo->n(); //displays 'MyAction'
Late static bindings, available in PHP 5.3+
Now that PHP 5.3 is released, you can use late static bindings, which let you resolve the target class for a static method call at runtime rather than when it is defined.
While the feature does not introduce a new magic constant to tell you the classname you were called through, it does provide a new function, get_called_class() which can tell you the name of the class a static method was called in. Here's an example:
Class Action {
public static function n() {
return get_called_class();
}
}
class MyAction extends Action {
}
echo MyAction::n(); //displays MyAction
Since 5.5 you can use class keyword for the class name resolution, which would be a lot faster than making function calls. Also works with interfaces.
// C extends B extends A
static::class // MyNamespace\ClassC when run in A
self::class // MyNamespace\ClassA when run in A
parent::class // MyNamespace\ClassB when run in C
MyClass::class // MyNamespace\MyClass
It's not the ideal solution, but it works on PHP < 5.3.0.
The code was copied from septuro.com
if(!function_exists('get_called_class')) {
class class_tools {
static $i = 0;
static $fl = null;
static function get_called_class() {
$bt = debug_backtrace();
if (self::$fl == $bt[2]['file'].$bt[2]['line']) {
self::$i++;
} else {
self::$i = 0;
self::$fl = $bt[2]['file'].$bt[2]['line'];
}
$lines = file($bt[2]['file']);
preg_match_all('/([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/',
$lines[$bt[2]['line']-1],
$matches);
return $matches[1][self::$i];
}
}
function get_called_class() {
return class_tools::get_called_class();
}
}
Now (when 5.3 has arrived) it's pretty simple:
http://php.net/manual/en/function.get-called-class.php
class MainSingleton {
private static $instances = array();
private static function get_called_class() {
$t = debug_backtrace();
return $t[count($t)-1]["class"];
}
public static function getInstance() {
$class = self::get_called_class();
if(!isset(self::$instances[$class]) ) {
self::$instances[$class] = new $class;
}
return self::$instances[$class];
}
}
class Singleton extends MainSingleton {
public static function getInstance()
{
return parent::getInstance();
}
protected function __construct() {
echo "A". PHP_EOL;
}
protected function __clone() {}
public function test() {
echo " * test called * ";
}
}
Singleton::getInstance()->test();
Singleton::getInstance()->test();
(PHP 5 >= 5.3.0, PHP 7)
get_called_class — The "Late Static Binding" class name
<?php
class Model
{
public static function find()
{
return get_called_class();
}
}
class User extends Model
{
}
echo User::find();
this link might be helpfull
There is no way, in the available PHP versions, to do what you want. Paul Dixon's solution is the only one. I mean, the code example, as the late static bindings feature he's talking about is available as of PHP 5.3, which is in beta.
I am writing a basic class with some call_user_func() and then derived class with a method I want to be called from said call_user_func(). It looks as follows:
class Basic
{
private $InputHandler = null;
public function SetNewHandler(callable $NewHandler)
{
$this->InputHandler = $NewHandler;
}
public function ProcessInput()
{
call_user_func(array($this,$this->InputHandler));
}
}
class Specific extends Basic
{
public function Handler()
{
echo "Handler() is called\n";
}
}
$spec = new Specific();
$spec->SetNewHandler('Specific\Handler');
$spec->ProcessInput();
unset($spec);
Obviously it does not work since Specific\Handler is not recognized as a valid callable.
But what is the proper way to achieve this outcome? Parent class should be oblivious to the details of implementation of derived class and\or handler method.
I use php 7.4
I would just create a default handler method in the base class:
class Base
{
public function ProcessInput()
{
$this->Handler();
}
public function Handler()
{
// Some default code or just leave empty
echo "Base Handler() is called\n";
}
}
class Specific extends Base
{
public function Handler()
{
echo "Specific Handler() is called\n";
}
}
$spec = new Specific;
$spec->ProcessInput();
This way you don't need to manually bind the handler you want to use for each instance (which could be cumbersome). If you want a new handler, create a new class with that handler.
Here's a demo
If you made the call with call_user_func(array ($this, $this->InputHandler)); a method name is expected as the 2nd array element.
class Basic
{
private $InputHandler = null;
public function SetNewHandler($NewHandler)
{
$this->InputHandler = $NewHandler;
}
public function ProcessInput()
{
call_user_func(array($this,$this->InputHandler));
}
}
class Specific extends Basic
{
public function Handler()
{
echo "Handler() is called\n";
}
}
$spec = new Specific();
$spec->SetNewHandler('Handler');
$spec->ProcessInput();
Instead of call_user_func(Array($this, $this->InputHandler)); does this work here too:
$method = $this->InputHandler;
$this->$method();
or this:
$this->{$this->InputHandler}();
Alternatively: A callable is passed similarly as described by #Magnus Eriksson in the comment.
class Basic
{
private $InputHandler = null;
public function SetNewHandler(callable $NewHandler)
{
$this->InputHandler = $NewHandler;
}
public function ProcessInput()
{
call_user_func($this->InputHandler);
}
}
class Specific extends Basic
{
public function Handler()
{
echo "Handler() is called\n";
}
}
$spec = new Specific();
$spec->SetNewHandler([$spec,'Handler']);
$spec->ProcessInput();
The magical __call() and __callStatic can pretty much handle any non existing method on the class, but is there a way to handle a non existing magical method on a class?!
Here's an example on why I need this:
I have a class called DoSomething:
class DoSomething{
public function ok(){
echo 'Something!';
}
}
I want to call this class as a function for a reason! which should call the __invoke function of that class:
$doSomething = new DoSomething();
$doSomething();
Normally by doing that, the class should look for the __invoke function, however in my case I don't to have that function declared on my class (DoSomething), instead I want to be able to call another function (such as the ok()) if the __invoke doesn't exist.
I was expecting something like this to work, but of course it didn't :)
public function __call($class, $arguments)
{
$object = IoC::resolve($class);
$object->ok(...$arguments);
}
The main goal is to use the class as a function, without having to declare the __invoke method. Handle the function does not exist error and call another function instead.
I think that would be really cool :D I appreciate suggestions or other solutions to achieve this.
Internal solution
Extract an abstract class
You could extract an abstract class and have your classes extend it:
<?php
abstract class Invokable
{
public function __invoke()
{
return $this->ok();
}
abstract public function ok();
}
class DoSomething extends Invokable
{
public function ok()
{
echo 'Something';
}
}
$doSomething = new DoSomething();
echo $doSomething();
For an example, see:
https://3v4l.org/m0ih8
Extract a trait
You could extract a trait and have your classes use it:
<?php
trait InvokableTrait
{
public function __invoke()
{
return $this->ok();
}
}
class DoSomething
{
use InvokableTrait;
public function ok()
{
echo 'Something';
}
}
$doSomething = new DoSomething();
echo $doSomething();
For an example, see:
https://3v4l.org/ftUfI
External Solution
Create a proxy
You could create a proxy (a decorator) that composes the object that is not invokable:
<?php
class InvokableDecorator
{
private $decorated;
public function __construct($decorated)
{
$this->decorated = $decorated;
}
public function __call($name, $arguments)
{
/**
* delegate to decorated object if the method exists
*/
if (method_exists($this->decorated, $name)) {
return $this->decorated->{$name}($arguments);
}
}
public function __invoke()
{
return $this->decorated->ok();
}
}
class DoSomething
{
public function ok()
{
echo 'Something';
}
}
$doSomething = new InvokableDecorator(new DoSomething());
echo $doSomething();
For an example, see:
https://3v4l.org/C3XEX
Create a handler
You could create a handler that takes care of determining this externally:
<?php
class Handler
{
public function handle($subject)
{
if (is_callable($subject)) {
return $subject();
}
if (method_exists($subject, 'ok')) {
return $subject->ok();
}
throw new \BadMethodCallException(sprintf(
'Unable to handle instance of "%s"',
get_class($subject)
));
}
}
class DoSomething
{
public function ok()
{
echo 'Something';
}
}
$handler = new Handler();
echo $handler->handle(new DoSomething());
For an example, see:
https://3v4l.org/E0NVs
In PHP, how do I find out if a class method was called via a method inherited from a trait?
Say I have a class myClass that uses the Psr\Log\LoggerTrait (see: PSR-3). I need to be able to find out if the method myClass::log() was called via a method from the Psr\Log\LoggerTrait, for example LoggerTrait::debug(), or if it was called directly from outside myClass.
All the methods are non-static.
This is related to a debugging package. I'm not trying to alter behavior based on the caller, I just need to be able to pass that information forward. And to be more precise, I need just the entry point, ie. just the last call outside of my package.
I'm looking at debug_backtrace() but it doesn't seem to offer any direct solutions. Is there some rational way of doing this?
Here's some code:
<?php
class myClass
{
use Psr\Log\LoggerTrait;
public function log($level, $message, array $context = array())
{
if (called_via_trait) {
...
} else {
...
}
}
}
$myObject = new myClass;
$myObject->log('debug', 'This is a direct call');
$myObject->debug('This is a call via a trait method');
You could use get_called_class to determine the class that called it.
trait Test {
public function doTest() {
echo get_called_class() . "\n";
}
}
class Some {
use Test;
public function myFunc() {
$this->doTest();
}
}
$some = new Some();
$some->myFunc(); // Outputs "Some" since Some uses Test
So in your case, inside your class, you could do something like
function test() {
if(get_called_class() == 'myClass') {
// You're in the myClass class
} else {
// You're not in the myClass class
}
}
Yes, you have to use debug_backtrace(); Please follow my example:
namespace Psr\Log;
class LoggerTrait{
public static function debug(){
return myClass::log();
}
}
class myClass{
public static function log(){
$trace = debug_backtrace();
if(isset($trace[1])){
echo'<br />Called by <b>'.$trace[1]['class'].'</b>. ';
} else {
echo'<br />Called by <b>'.$trace[0]['class'].'</b>. ';
}
if(isset($trace[1]['class']) && $trace[1]['class']!=get_class()){
echo'Called outside';
} else {
echo'Called inside';
}
//return get_class();
}
}
trait ExampleTrait {
public function doSay() {
echo LoggerTrait::debug();
echo myClass::log();
}
}
echo LoggerTrait::debug();
echo myClass::log();
echo ExampleTrait::doSay();
Is there a way to do something like this:
class Test {
if(!empty($somevariable)) {
public function somefunction() {
}
}
}
I know this might not be best practice, but I need to do this for a very specific problem I have, so is there anyway to do it?
I just want that function to be included in the class if that variable (which is tied to a URL param) is not empty. As it is written now, I get Error: syntax error, unexpected T_VARIABLE, expecting T_FUNCTION
Thanks!
It depends on the your specific use case, and I don't have enough info to give a specific answer, but I can think of one possible fix.
Extend the class, using an if statement. Put everything except the one function in AbstractTest.
<?php
abstract class AbstractTest
{
// Rest of your code in here
}
if (!empty($somevariable)) {
class Test extends AbstractTest {
public function somefunction() {
}
}
} else {
class Test extends AbstractTest { }
}
Now, the class Test only has the method somefunction if $somevariable isn't empty. Otherwise it directly extends AbstractTest and doesn't add the new method.
Call the required function if the variable is not empty.
<?php
class Test {
public function myFunct() {
//Function description
}
}
$oTest = new Test();
if(!empty($_GET['urlParam'])) {
oTest->myFunc();
}
?>
class Test {
public function somefunction() {
}
}
is all you need actually.
Please note that a function inside a class is called 'method'.
AFAIK you cannot have a condition out of the method in class scope (if that flows)
Class Test {
if (empty($Var)){
public function Test_Method (){
}
}
}
Will not work. Why not have it constantly exisisting but only call the method when it's needed?
Example:
Class Test {
public function Some_Method(){
return 23094; // Return something for example purpose
}
}
Then from your PHP:
$Var = ""; // set an empty string
$Class = new Test();
if (empty($Var)){
echo $Class->Some_Method(); // Will output if $Var is empty
}
Perhaps you trying to validate a string within OOP scope, then take this example:
Class New_Test {
public $Variable; // Set a public variable
public function Set(){
$This->Variable = "This is not empty"; // When calling, $this->variable will not be empty
}
public function Fail_Safe(){
return "something"; // return a string
}
}
Then out of Scope:
$Class = new New_Test();
if (empty($Class->Variable)){
$Class->Fail_Safe();
} // Call failsafe if the variable in OOP scope is empty