assign function to class method - php

Is it possible to create a function out of a class method?
ie.
class Test {
public function __construct()
{
if ( ! function_exists('foo') ) {
function foo ()
{
return $this->foo();
}
}
}
private function foo()
{
return 'bar';
}
}
Or would I have to do it the other way around, creating a function and using it within the method?

Just do it like that, php is able to do it
class Test {
public function __construct()
{
if ( ! function_exists('foo') ) {
function foo ()
{
return $this->foo();
}
}
}
private function foo()
{
outsidefunction();
return 'bar';
}
}
private function outsidefunction()
{
return 0;
}

i'm trying to create a global function that is a copy of the class method. I come from javascript land where functions are just variables and you can easily copy them...
Functions in PHP are not first class citizens, you cannot copy functions around like variables in PHP. You can hand a reference to a function around, but not the function itself.

In theory, you could use Reflection to get a Closure, reference it via $GLOBALS and then define a function foo to call the Closure from $GLOBALS, e.g.
<?php // requires 5.4
class Test {
public function __construct()
{
if (!function_exists('foo')) {
$reflector = new ReflectionMethod(__CLASS__, 'foo');
$GLOBALS['foo'] = $reflector->getClosure($this);
function foo() {
return call_user_func($GLOBALS['foo']);
}
}
}
private function foo()
{
return 'bar';
}
}
$test = new Test();
echo foo();
Run Demo
However, that is extremely ugly and you do not want to do it this way.
If you want more JavaScript like objects, have a look at
http://www.phpied.com/javascript-style-object-literals-in-php
But still, even the suggested techniques in there are kludges imo.

Related

use function from index.php like this class->publicF->f()

guys lets say we have this class: all i want to do is to use a specific function to do something, think it as a button, but in a way that you have 1 public function and you can execute parts of it!
CLASS DATA {
public function X() {
function A() {
//do_something
}
}
}
and now i'm in the index.php and i want to call the function A() only.
i tried $data->X()->A() but nothing
i tried $data->X(A()) also nothing
is it possible this?
In the way you've written it, no. Looks to me like you're trying to build something in the way you would a Javascript application. But like Rizier123 points out you could do something like this.
class Foo {
public function getBar(){
return new Bar();
}
}
class Bar {
public function someFunction() {
}
}
$foo = new Foo();
$foo->getBar()->someFunction();
Although I'm not entirely sure why you would want to nest things that way when inheriting would be a better route. Something like this:
class Foo extends Bar {
}
class Bar {
public function someFunction() {
}
}
$foo = new Foo();
$foo->someFunction();
But I guess you could use the former as a way to pass specific constructor parameters in a consistent manor.
class Foo {
public function getRainbow(){
return new Bar('rainbow');
}
}
class Bar {
private $type;
public function __construct($type)
{
$this->type = $type;
}
public function someFunction() {
switch($this->type){
case 'rainbow':
echo 'All the way across the sky.';
break;
default:
echo 'Boring.';
break;
}
}
}
$foo = new Foo();
$foo->getRainbow()->someFunction();

How to define a callback with parameters without closure and use in PHP?

In PHP in order to define a callback a closure can be used and the tool for passing static parameters is the use directive.
class MyClass {
public function foo($x) {
echo $x;
}
public function bar() {
$x = '123';
$callback = function () use ($x) {
$this->foo($x);
};
$callback();
}
}
$myClass = new MyClass();
$myClass->bar();
Is it possible / How to avoid the anonymous function and replace it by a method?
class MyClass {
public function foo($x) {
echo $x;
}
public function baz() {
$x = '567';
// There is no function with the name create_user_func.
// Just to show, what I'm looking for.
$callback = create_callback([$this, 'foo'], $params = [$x]);
$callback();
}
}
$myClass = new MyClass();
$myClass->baz();
EDIT:
Some additional / backgroud info (to make clear, what I want to achieve and why -- and to avoid misanderstandings):
In my concrete case I need to pass the callback to a method of a framework. That means: I cannot / may not affect the way it gets called.
The method accepts only the callback itself, no arguments for the callback. That means, the callback has to "know"/provide the static parameters (and their values) it needs.
It's exactly, what the use directive solves. But I have multiple callback definitions in my method, and the method is getting long. So I want to move the logic of the callbacks to separate methods.
But I have multiple callback definitions in my method, and the method is getting long. So I want to move the logic of the callbacks to separate methods.
This is a perfect example for the magic method __invoke()
For each callback you need, extract the functionality and the properties it uses into a new class. Put the code into the __invoke() method of the new class, initialize all the properties it needs into its __construct() and you're ready to go.
The code:
class MyClass {
public function bar() {
$x = '123';
// Create the callback, pass the values it needs to initialize
$callback = new ActionFoo($x);
// Call the callback without arguments
$callback();
}
}
class ActionFoo {
private $x;
public function __construct($x) {
$this->x = $x;
}
public function __invoke() {
echo($this->x);
}
}
$myClass = new MyClass();
$myClass->bar();
I guess it's fair to say that you're trying to emulate Javascript's bind method. The problem with this in PHP is that functions are not first class citizens or objects, so something like ->bind($x) is not possible. There's also no way to pass additional parameters for a callable. So you're going to have to wrap it in something.
A more reusable method would be to write an appropriate class:
class CallbackWrapper {
protected $callable,
$args;
public function __construct(callable $callable, array $args) {
$this->callable = $callable;
$this->args = $args;
}
public function __invoke() {
call_user_func_array($this->callable, $this->args);
}
}
giveMeACallback(new CallbackWrapper([$this, 'foo'], [$x]));
Or you just simplify the construction of anonymous functions:
function make_callback(callable $callable, array $args) {
return function () use ($callable, $args) {
return call_user_func_array($callable, $args);
};
}
giveMeACallback(make_callback([$this, 'foo'], [$x]));
There are many ways to achieve this.
Using a helper function.
Code:
class MyClass {
private $x;
public function foo() {
echo $this->x;
}
public function bar() {
$this->x = '123';
anon($this);
}
}
$myClass = new MyClass();
$myClass->bar();
function anon($obj) {
$obj->foo();
}
Using call_user_func.
Code:
class MyClass {
private $x;
public function foo() {
echo $this->x;
}
public function bar() {
$this->x = '123';
call_user_func([$this, 'foo']);
}
}
$myClass = new MyClass();
$myClass->bar();
If for some reason you don't want to use member variables, you can pass the arguments with call_user_func_array.
Code:
class MyClass {
private $x;
public function foo($x) {
echo $x;
}
public function bar() {
$x = '123';
call_user_func_array([$this, 'foo'], [$x]);
}
}
$myClass = new MyClass();
$myClass->bar();

Nested method in php object

How can I create something like
MyObject->property->method()
in PHP?
I only know how to create a method for a class:
class MyObject
{
public function MyMethod()
{
// do something
}
}
In Javascript I can easily do something like
var MyObject = {
property : {
method : function ()
{
// do something
}
}
}
How do I do that?
In Javascript you can create objects and methods inline, in PHP you need to have a class and instantiate it:
class Foo {
public function method() {}
}
class MyObject {
public $property;
public function __construct() {
$this->property = new Foo;
}
}
$o = new MyObject;
$o->property->method();
You can set an object as the value of a property. Something like this:
class Foo {
public $Bar;
public function __construct() {
$this->Bar = new Bar();
}
}
class Bar {
public function ShowBar() {
echo 'Bar';
}
}
$Foo = new Foo();
$Foor->Bar->ShowBar();
As others have correctly answered, this works differently in PHP and Javascript. And these differences are also the reason why in PHP you need to define the class methods before you run them. It might become a bit more dynamic in the future but I'm sure not on the level of Javascript.
You can however fake this a bit in PHP because you can assign functions to properties dynamically:
$myObject = new PropCall;
$myObject->property->method = function() {
echo "hello world\n";
};
$myObject->property->method();
This example outputs:
hello world
This does work because some little magic has been added in the instantiated object:
class PropCall
{
public function __call($name, $args) {
if (!isset($this->$name)) {
return null; // or error handle
}
return call_user_func_array($this->$name, $args);
}
public function __get($name) {
$this->$name = new PropCall;
return $this->$name;
}
}
This class code checks if a dynamic property has been added with the name of the method called - and then just calls the property as a function.

Using a class that has params inside another class (PHP)

I am trying to access the results of a function that is public inside another class, but I'm not entirely sure how to do this. The class i'm trying to access require parameters, so the class_name::function() method is not working. I'm still new to working with classes, and trying to learn it.
Class one:
class foo {
private $var1;
function __construct($param) {
$this->var1 = $param
}
public function myFunc() {
echo $this->var1;
}
}
Class 2
class bar {
public function secondFunc() {
var_dump(**RESULT FROM foo->myFunc HERE);
}
}
These two classes are a basic example of what i'm actually doing, but from this you should get the general idea of my question.
For the correct result to display, the first class needs the params passed to it otherwise the function fails.
I tried using foo::bar(), but this doesn't pass any params to the first class, and it therefor fails.
So, how do I access myFunc from foo inside secondFunc from bar?
You have to pass an instance of foo to bar:
class Foo {
private $var1;
function __construct($param) {
$this->var1 = $param
}
public function myFunc() {
return $this->var1;
}
}
class Bar {
private $foo;
function __construct(Foo $foo) {
$this->foo = $foo
}
public function secondFunc() {
var_dump($this->foo->myFunc());
}
}
$bar = new Bar(new Foo('something'));
$bar->secondFunc();
Is that what you want?
Your example isn't very practical but here is the basic idea
public function secondFunc($dependency) {
var_dump($dependency->myFunc());
}
or...
public function secondfunc() {
$foo = new foo();
var_dump($foo->myFunc();
}
What about
class bar {
public function secondFunc() {
$foo = new foo($param);
var_dump($foo->myFunc());
}
}
Or do you need something in one line?

PHP class: Global variable as property in class

I have a global variable outside my class = $MyNumber;
How do I declare this as a property in myClass?
For every method in my class, this is what I do:
class myClass() {
private function foo() {
$privateNumber = $GLOBALS['MyNumber'];
}
}
I want this
class myClass() {
//What goes here?
var $classNumber = ???//the global $MyNumber;
private function foo() {
$privateNumber = $this->classNumber;
}
}
EDIT: I want to create a variable based on the global $MyNumber but
modified before using it in the methods
something like: var $classNumber = global $MyNumber + 100;
You probably don't really want to be doing this, as it's going to be a nightmare to debug, but it seems to be possible. The key is the part where you assign by reference in the constructor.
$GLOBALS = array(
'MyNumber' => 1
);
class Foo {
protected $glob;
public function __construct() {
global $GLOBALS;
$this->glob =& $GLOBALS;
}
public function getGlob() {
return $this->glob['MyNumber'];
}
}
$f = new Foo;
echo $f->getGlob() . "\n";
$GLOBALS['MyNumber'] = 2;
echo $f->getGlob() . "\n";
The output will be
1
2
which indicates that it's being assigned by reference, not value.
As I said, it will be a nightmare to debug, so you really shouldn't do this. Have a read through the wikipedia article on encapsulation; basically, your object should ideally manage its own data and the methods in which that data is modified; even public properties are generally, IMHO, a bad idea.
Try to avoid globals, instead you can use something like this
class myClass() {
private $myNumber;
public function setNumber($number) {
$this->myNumber = $number;
}
}
Now you can call
$class = new myClass();
$class->setNumber('1234');
Simply use the global keyword.
e.g.:
class myClass() {
private function foo() {
global $MyNumber;
...
$MyNumber will then become accessible (and indeed modifyable) within that method.
However, the use of globals is often frowned upon (they can give off a bad code smell), so you might want to consider using a singleton class to store anything of this nature. (Then again, without knowing more about what you're trying to achieve this might be a very bad idea - a define could well be more useful.)
What I've experienced is that you can't assign your global variable to a class variable directly.
class myClass() {
public $var = $GLOBALS['variable'];
public function func() {
var_dump($this->var);
}
}
With the code right above, you get an error saying "Parse error: syntax error, unexpected '$GLOBALS'"
But if we do something like this,
class myClass() {
public $var = array();
public function __construct() {
$this->var = $GLOBALS['variable'];
}
public function func() {
var_dump($this->var);
}
}
Our code will work fine.
Where we assign a global variable to a class variable must be inside a function. And I've used constructor function for this.
So, you can access your global variable inside the every function of a class just using $this->var;
What about using constructor?
class myClass {
$myNumber = NULL;
public function __construct() {
global myNumber;
$this->myNumber = &myNumber;
}
public function foo() {
echo $this->myNumber;
}
}
Or much better this way (passing the global variable as parameter when inicializin the object - read only)
class myClass {
$myNumber = NULL;
public function __construct($myNumber) {
$this->myNumber = $myNumber;
}
public function foo() {
echo $this->myNumber;
}
}
$instance = new myClass($myNumber);
If you want to access a property from inside a class you should:
private $classNumber = 8;
I found that globals can be used as follows:
Create new class:
class globalObj{
public function glob(){
global $MyNumber;
return $this;
}
}
So, now the global is an object and can be used in the same way:
$this->glob();
class myClass
{
protected $foo;
public function __construct(&$var)
{
$this->foo = &$var;
}
public function foo()
{
return ++$this->foo;
}
}

Categories