php class call function within function - php

Could someone help me understand how I can make functions within class methods, that would allow me to do things like this:
$class->send->activation_email()
I've seen many APIs do this, so I've tried:
class MyClass
{
public function send()
{
function activation_email()
{
echo "success!";
}
}
}
Undefined property: MyClass::$send

Consider:
class emailSender()
{
function activation_email()
{
if (mail($this->to, $this->subj, $this->body)) {
print $this->msg;
}
}
class MyClass
{
var $send;
function __construct()
{
$this->send=new emailSender();
$this->send->msg="success!";
}
}
$obj=new MyClass();
$obj->send->activation_email();

You probably want to an instance of another class within your class. Make a variable inside your class like this:
$this->otherclass = new Otherclass();
In this case, you can call functions from your other class the following way:
$myClass->otherclass->otherClassFunction()

Someone had answered but deleted the post. This is along the lines of what I was hoping for, and it works as expected:
class MyClass {
public function send(){
echo "Sending: ";
return $this;
}
public function activation_email(){
echo "activation email.";
}
}
$myClass = new MyClass();
$myClass->send()->activation_email();

What you are referring to (shame on no one for noticing this, for shame) is called "method chaining". A lot of big frameworks do this. Consider this example of use:
echo $obj->setName('Mike')->convertMtoN()->getName();
// Echoes "Nike"
Cool.
But here is how it works:
class Example {
private $name = '';
public function setName($name) {
$this->name = $name;
// We return the object, so you can call it again.
return $this;
}
public function convertMtoN() {
// Let's do Caps first
$this->name = str_replace("M", "N", $this->name);
// Then lowercase
$this->name = str_replace("m", "n", $this->name);
// We return the object, keep working
return $this;
}
public function getName() {
return $this->name;
}
}
$name = new Example;
echo $name->setName('Mike')->convertMtoN()->getName();
Essentially, for each method that does not implicitly return a value, you simply return the object, allowing you to continue chaining.
Awesome, right?
PHP rocks (now, I know it has its faults, but with HHVM and process forking, it basically rocks [dude, you will get there]).
You can play with this here:
https://ideone.com/fMcQ9u

Related

Get name function in PHP

I have some classes:
class A
{
private $_method;
public function __construct()
{
$this->_method = new B();
}
public function demo()
{
$this->_method->getNameFnc();
}
}
class B
{
public function getNameFnc()
{
echo __METHOD__;
}
}
I'm trying to get the function name of a class B class, but I want the function getNameFnc to return 'demo'. How do I get the name 'demo' in function getNameFnc of class B?
Well, if you really want to do this without passing a parameter*, you may use debug_backtrace():
→ Ideone.com
public function getNameFnc()
{
$backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
echo $backtrace[1]['function'];
}
* this would be the recommended way although one should never need to know which function has been previously called. If your application relies on that fact, you have got a major design flaw.
You will need to use debug_backtrace to get that information.
I haven't tested the code below but I think this should give you the information you want:
$callers = debug_backtrace();
echo $callers[1]['function'];
Why not pass it?
class A
{
private $_method;
public function __construct()
{
$this->_method = new B();
}
public function demo()
{
$this->_method->getNameFnc(__METHOD__);
}
}
class B
{
public function getNameFnc($method)
{
echo $method;
}
}
Or use __FUNCTION__ if you don't want the class name.

Can I call inherited parent method without a name in PHP?

Is there a way to call an inherited method, without specifying it's function name?
Something like:
class Child extends Parent {
function some_function(){
// magically inherit without naming the parent function
// it will call parent::some_function()
parent::inherit();
// other code
}
function another_function(){
// it will call parent::another_function()
$result = parent::inherit();
// other code
return $result;
}
}
I could think of a hack to do this using debug_backtrace(), get the last function where inherit() was called and access it's parent with the same function name. I was wondering if there's a nicer way instead of using debug functions which are clearly not meant for this.
You can use the magic __FUNCTION__ constant.
class A
{
function some_function()
{
echo 'called ' . __METHOD__;
}
}
class B extends A
{
function some_function()
{
call_user_func(array('parent', __FUNCTION__));
}
}
$b = new B;
$b->some_function(); // prints "called A::some_function"
Instead of
call_user_func(array('parent', __FUNCTION__));
you can also do
parent::{__FUNCTION__}();
Dirty, but:
class Adult {
function mummy(){
return 'Walk like an Egyptian';
}
function daddy(){
return 'Luke, I am your father';
}
}
class Child extends Adult {
function mummy(){
echo 'Mummy says: ';
$me = explode('::',__METHOD__)[1];
echo parent::$me();
}
function daddy(){
echo 'Daddy says: ';
$me = explode('::',__METHOD__)[1];
echo parent::$me();
}
}
$o = new Child();
$o->mummy();
$o->daddy();
EDIT
Actually giving you a parent method called inherit();
class Adult {
private function mummy(){
return 'Walk like an Egyptian';
}
private function daddy(){
return 'Luke, I am your father';
}
protected function inherit($method) {
$beneficiary = explode('::', $method)[1];
return $this->$beneficiary();
}
}
class Child extends Adult {
public function mummy() {
echo 'Mummy says: ',
parent::inherit(__METHOD__),
PHP_EOL;
}
public function daddy() {
echo 'Daddy says: ',
parent::inherit(__METHOD__),
PHP_EOL;
}
}
$o = new Child();
$o->mummy();
$o->daddy();
Dynamically calling functions:
static::$functionName();
In your case:
$func = __FUNCTION__;
parent::$func();
Note: the function name must be a string, if it's the actual function (not really relevant in this context) then it first needs to be converted to its string name first.
Other stuff that your question will probably lead you towards in the long run.
Check out late static binding it's what you're looking for.
Example taken from the linked page.
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();

How do I call a static method of a class stored as a variable?

Why, in a class instance context, don't calls of the form $this->className::staticMethod work, but calls of the form $className::staticMethod do work?
In the example below callDoSomething2 works, but callDoSomething does not work (I get a parser error). I'm using PHP version 5.3.15.
<?php
class A {
private $className;
public function __construct($className) {
$this->className = $className;
}
public function callDoSomething() {
$this->className::doSomething();
}
public function callDoSomething2() {
$className = $this->className;
$className::doSomething();
}
}
class B {
public static function doSomething() {
echo "hello\n";
}
}
$a = new A('B');
$a->doSomething();
callDoSomething2 is one way to do it, the other would be to use something along the lines of
call_user_func("{$this->className}::doSomething");

PHP OOP Multicall

i have seen in some libraries something like this :
$this->getResponse()->setRedirect($returnUrl);
How is this 'multicall' done, or, how should the class be build to do something like this?
I think :
class greeting
{
public function hi()
{
public function howAreYou()
{
echo 'How are you?';
}
}
}
$greet = new greeting;
$greet->hi()->howAreYou();
But i think it's not so good, i would better use something like extends, but i don't know. Thx for your suggestions.
If this is a class instance calling itself, it is called "method chaining".
In PHP, can be done by using return $this; note that this is a very different mechanism than class inheritance - it doesn't really make sense to treat them as interchangeable.
See also: https://stackoverflow.com/search?q=method+chaining+php
getResponse() is returning a class instance which has a setRedirect() method.
Example:
class Foo
{
public function getResponse()
{
$redirect = new Bar();
return $redirect;
}
}
class Bar
{
public function setRedirect($returnUrl)
{
// do something
}
}
$foo = new Foo();
$foo->getResponse()->setRedirect("returnUrl");
No.
All you have to do is return self at very end of each function.
So Your example would be like>
class greeting
{
public function hi()
{
echo "Hi";
return $this;
}
public function howAreYou()
{
echo 'How are you?';
return $this;
}
}
$greet = new greeting;
$greet->hi()->howAreYou();
Or even:
$greet->hi()->howAreYou()->hi()->howAreYou();
class stutter{
public function a(){
echo 'h';
return $this;
}
public function b(){
echo 'hello world!';
}
}
$var=new stutter();
var->a()->b();
Output is:
h hello world
Chaining methods is not the same as declaring functions within a method... in fact the latter will spit an error (not the function declaration, but the way you're calling it). In order to chain a method, just have it return the object itself:
Class chainableObject
{
public $name=null;
public function __construct($name='')
{
$this->name=$name;
return $this;
}
public function setName($name)
{
$this->name = $name;
return $this;//makes chainable
}
public function greet()
{
echo 'Hello, '.$this->name;
return $this;
}
}
$chain = new chainableObject('Frank')->greet();//outputs: Hello, frank
The explanation: All methods return the instance itself, so basically, read the last line of the snippet like this [create object with name:Frank]=>call method greet on the return value of this action. Since the return value is $this, the object that has a greet method, that's what will happen... easy, for more info: just google php method chaining

Chaining a new object instance in PHP

We have the following chaining:
$obj = new obj();
$obj->setname($params1)->setcolor($params2);
Is there a way to do the same chaining on one line, without creating a dummy function?
P.S: I want to skip the part where the constructor itself is on a new line. I want to construct the object and start the chaining on the same line. Something like this:
$obj = new obj()->setname($params1)->setcolor($params2);
Since PHP 5.4, class member access on instantiation has been added so you can do it like this:
$obj = (new obj())->setname($params1)->setcolor($params2);
In previous versions, like you I hate that you have to instantiate the object on one line and then start using it on another, so I have a global function _i() which looks like this:
function _i($i) { return $i; }
I use it like this:
_i(new Obj)->doThis($param)->doThat($param2);
Some people will find it ugly but PHP lacks language expression power, so it works for me :)
I use static functions of class for it.
class a{
static public function gets($args){
return new self($args);
}
public function do_other(){
}
}
a::gets()->do_other();
Usually there are more then I static method to different usages
Should be possible if you allways return the object itself in the function.
function setname($param) {
// set the name etc..
return $this;
}
You can also use PHP type hinting to make sure only the correct object is used as an argument
function instance(sdtClass $instance) { return $instance }
or as the static method using the class name
class CustomClass{
static public function gets(CustomClass $obj){
return $obj;
}
}
You can also use this technique from Singleton pattern (without using singleton pattern):
<?php
class test
{
public function __construct() {
}
public static function getInstance() {
return new test();
}
public function chain() {
echo 'ok';
}
}
// outputs 'ok'
$test = test::getInstance()->chain();
Sure is. Simplt return this at the end of each function, to return the object so your next chained function can use it.
<?php
class A
{
public __constructor()
{ .... }
public function B($params)
{
//Processing
return this;
}
public function C($params)
{
//Processing
return this;
}
public function D($params)
{
//Processing
}
}
$O = new A();
$O->B($params)->C($params)->D($params); //Will work because B and C return this
$O->B($params)->D($params)->C($params); //WILL NOT work because D doesn't return this
?>

Categories