Here is my code:
class myclass{
public function one(){
return 'sth';
}
public function two(){
function myfunc($arg){
if ($arg){
return $this->one();
} else {
return 'nothing';
}
myfunc(true);
}
}
}
$obj = new myclass;
echo $obj->$this->two();
As you see in the fiddle it throws this error:
Fatal error: Uncaught Error: Using $this when not in object context in /in/E1U9n:25
How can I fix the problem? The expected result is sth.
First you're calling myfunc(true); in it's own scope.So it is not
possible to call a function in it's scope as far as i know
Secondly You're calling $this in a scope of function which doesn't know which class does it belong.
Thirdly you're not returning anything from your function two() so as it suppose. It will not echo anything.
See the fiddle https://3v4l.org/sl4eq
class myclass{
public function one(){
return 'sth';
}
public function two(){
function myfunc($arg){
if ($arg){
$newobj = new myclass();
return $newobj->one();
} else {
return 'nothing';
}
}
return myfunc(TRUE);
}
}
$obj = new myclass;
echo $obj->two();
Your code is really messy, because you lack of basic knowledge and experience. I strictly recommending for you to read the basics about OOP in PHP.
http://php.net/manual/en/language.oop5.php
<?php
class myclass {
public function one()
{
return 'sth';
}
public function two()
{
return $this->myfunc(true);
}
protected function myfunc($arg)
{
if ($arg)
return $this->one();
else
return 'nothing';
}
}
$obj = new myclass;
echo $obj->two();
I'm trying to pass a variable to a method in an extended class, but it's not working.
Here's the sample code:
class set2 extends set1
{
function Body($variable) {
}
}
$start2 = new set2();
$start2->Body('some text');
The last line is the part I'm trying to get to work. I'm not sure if I should have a constructor instead to do it or how it's best to get it to work.
I figured it out. I just added a public variable instead and passed its value like this:
class set2 extends set1
{
public $variable = NULL;
function Body() {
echo $this->variable;
}
}
$start2 = new set2();
$start2->variable = 'Some Text';
Three different ways of doing what I think you're trying to do:
class set1
{
protected $headVariable;
function Head() {
echo $this->headVariable;
}
function Body($variable) {
echo $variable;
}
function Foot() {
echo static::$footVariable;
}
}
class set2 extends set1
{
protected static $footVariable;
function Head($variable) {
$this->headVariable = $variable;
parent::Head();
}
function Body($variable) {
parent::Body($variable);
}
function Foot($variable) {
self::$footVariable = $variable;
parent::Foot();
}
}
$start2 = new set2();
$start2->Head('some text');
$start2->Body('some more text');
$start2->Foot('yet more text');
Lets say I have:
class Zebra{
public static function action(){
print 'I was called from the '.get_class().' class'; // How do I get water here?
}
}
class Water{
public static function drink(){
Zebra::action();
}
}
Water::drink();
How do I get "water" from the zebra class?
(This is for php 5.3)
You can get the caller's info from debug_backtrace http://php.net/manual/en/function.debug-backtrace.php
One not so good solution is :
use __METHOD__ or __FUNCTION__ or __CLASS__ .
and pass it as parameter to function being called.
http://codepad.org/AVG0Taq7
<?php
class Zebra{
public static function action($source){
print 'I was called from the '.$source.' class'; // How do I get water here?
}
}
class Water{
public static function drink(){
Zebra::action(__CLASS__);
}
}
Water::drink();
?>
Full usable solution using exception, but not debug_backtrace, no need to modify any prototype :
function getRealCallClass($functionName)
{
try
{
throw new exception();
}
catch(exception $e)
{
$trace = $e->getTrace();
$bInfunction = false;
foreach($trace as $trace_piece)
{
if ($trace_piece['function'] == $functionName)
{
if (!$bInfunction)
$bInfunction = true;
}
elseif($bInfunction) //found !!!
{
return $trace_piece['class'];
}
}
}
}
class Zebra{
public static function action(){
print 'I was called from the '.getRealCallClass(__FUNCTION__).' class';
}
}
class Water{
public static function drink(){
Zebra::action();
}
}
Water::drink();
I'm trying to add methods dynamically from external files.
Right now I have __call method in my class so when i call the method I want, __call includes it for me; the problem is I want to call loaded function by using my class, and I don't want loaded function outside of the class;
Class myClass
{
function__call($name, $args)
{
require_once($name.".php");
}
}
echoA.php:
function echoA()
{
echo("A");
}
then i want to use it like:
$myClass = new myClass();
$myClass->echoA();
Any advice will be appreciated.
Is this what you need?
$methodOne = function ()
{
echo "I am doing one.".PHP_EOL;
};
$methodTwo = function ()
{
echo "I am doing two.".PHP_EOL;
};
class Composite
{
function addMethod($name, $method)
{
$this->{$name} = $method;
}
public function __call($name, $arguments)
{
return call_user_func($this->{$name}, $arguments);
}
}
$one = new Composite();
$one -> addMethod("method1", $methodOne);
$one -> method1();
$one -> addMethod("method2", $methodTwo);
$one -> method2();
You cannot dynamically add methods to a class at runtime, period.*
PHP simply isn't a very duck-punchable language.
* Without ugly hacks.
You can dynamically add attributes and methods providing it is done through the constructor in the same way you can pass a function as argument of another function.
class Example {
function __construct($f)
{
$this->action=$f;
}
}
function fun() {
echo "hello\n";
}
$ex1 = new class('fun');
You can not call directlry $ex1->action(), it must be assigned to a variable and then you can call this variable like a function.
if i read the manual right,
the __call get called insted of the function, if the function dosn't exist
so you probely need to call it after you created it
Class myClass
{
function __call($name, $args)
{
require_once($name.".php");
$this->$name($args);
}
}
You can create an attribute in your class : methods=[]
and use create_function for create lambda function.
Stock it in the methods attribute, at index of the name of method you want.
use :
function __call($method, $arguments)
{
if(method_exists($this, $method))
$this->$method($arguments);
else
$this->methods[$method]($arguments);
}
to find and call good method.
What you are referring to is called Overloading. Read all about it in the PHP Manual
/**
* #method Talk hello(string $name)
* #method Talk goodbye(string $name)
*/
class Talk {
private $methods = [];
public function __construct(array $methods) {
$this->methods = $methods;
}
public function __call(string $method, array $arguments): Talk {
if ($func = $this->methods[$method] ?? false) {
$func(...$arguments);
return $this;
}
throw new \RuntimeException(sprintf('Missing %s method.'));
}
}
$howdy = new Talk([
'hello' => function(string $name) {
echo sprintf('Hello %s!%s', $name, PHP_EOL);
},
'goodbye' => function(string $name) {
echo sprintf('Goodbye %s!%s', $name, PHP_EOL);
},
]);
$howdy
->hello('Jim')
->goodbye('Joe');
https://3v4l.org/iIhph
You can do both adding methods and properties dynamically.
Properties:
class XXX
{
public function __construct($array1)
{
foreach ($array1 as $item) {
$this->$item = "PropValue for property : " . $item;
}
}
}
$a1 = array("prop1", "prop2", "prop3", "prop4");
$class1 = new XXX($a1);
echo $class1->prop1 . PHP_EOL;
echo $class1->prop2 . PHP_EOL;
echo $class1->prop3 . PHP_EOL;
echo $class1->prop4 . PHP_EOL;
Methods:
//using anounymous function
$method1 = function () {
echo "this can be in an include file and read inline." . PHP_EOL;
};
class class1
{
//build the new method from the constructor, not required to do it here by it is simpler.
public function __construct($functionName, $body)
{
$this->{$functionName} = $body;
}
public function __call($functionName, $arguments)
{
return call_user_func($this->{$functionName}, $arguments);
}
}
//pass the new method name and the refernce to the anounymous function
$myObjectWithNewMethod = new class1("method1", $method1);
$myObjectWithNewMethod->method1();
I've worked up the following code example and a helper method which works with __call which may prove useful. https://github.com/permanenttourist/helpers/tree/master/PHP/php_append_methods
Please look at the following code snipped
class A
{
function __get($name)
{
if ($name == 'service') {
return new Proxy($this);
}
}
function render()
{
echo 'Rendering A class : ' . $this->service->get('title');
}
protected function resourceFile()
{
return 'A.res';
}
}
class B extends A
{
protected function resourceFile()
{
return 'B.res';
}
function render()
{
parent::render();
echo 'Rendering B class : ' . $this->service->get('title');
}
}
class Proxy
{
private $mSite = null;
public function __construct($site)
{
$this->mSite = $site;
}
public function get($key)
{
// problem here
}
}
// in the main script
$obj = new B();
$obj->render();
Question is: in method 'get' of class 'Proxy', how I extract the corresponding resource file name (resourceFile returns the name) by using only $mSite (object pointer)?
What about:
public function get($key)
{
$file = $this->mSite->resourceFile();
}
But this requires A::resourceFile() to be public otherwise you cannot access the method from outside the object scope - that's what access modifiers have been designed for.
EDIT:
OK - now I think I do understand, what you want to achieve. The following example should demonstrate the desired behavior:
class A
{
private function _method()
{
return 'A';
}
public function render()
{
echo $this->_method();
}
}
class B extends A
{
private function _method()
{
return 'B';
}
public function render()
{
parent::render();
echo $this->_method();
}
}
$b = new B();
$b->render(); // outputs AB
But if you ask me - I think you should think about your design as the solution seems somewhat hacky and hard to understand for someone looking at the code.