Call function of class ONE from class TWO without extend? - php

If i have two classes A, B and one does not extend another they are separate but both loaded into script can i still reference function in A from B?
class A {
function one() {
echo "Class A";
}
}
class B {
function two() {
echo "Class B";
A::one();
}
}
$a new A;
$b = new B;
$b->two();

On the face of it, yes, you can do this. However, function one() in class A needs to be declared as static for your call notation to work. (This makes it a class method.)
The other alternative, suggested by the last lines in your code, is for the instance $b to call a function in instance $a. Such functions are called instance methods and are how you normally interact with an object. To access these methods, they must be declared as public. Methods declared as private can only be called by other methods inside that class.
There are several ways to call an instance method in your code. These are the obvious two you can pass in $a as a parameter to the function, or you can create an instance of class A inside your method.
What are you actually trying to achieve?

You can define it like this.
class A {
public static function one() {
echo "Class A";
}
}
class B {
function two() {
echo "Class B";
A::one();
}
}
$a new A;
$b = new B;
$b->two();

You can define one as static, but why would you do such a thing?

Related

PHP - Call a method from the class where i instantiated my object

I have 2 classes declared like in the example below.
class A{
protected $process;
public function __construct() {
......
$this->process=new B();
}
public function do_something(){
....
}
}
class B{
// content not important
// I need to call do_something from class A
}
My question is, how can I call from class B the method do_something() from class A? Is it possible?
From your example it is impossible for instance of B to know that it is instantiated and stored by an instance of class A. You need to create that connection explicitly in some way.
I didn't think this would even work, but apparently you can pass instance of A to B before A is even done with its constructor:
class A {
protected $process;
public function __construct() {
$this->process = new B( $this );
}
public function do_something() {
var_dump( 'do_something' );
}
public function test() {
$this->process->test();
}
}
class B {
public function __construct( A $a ) {
$this->a = $a;
}
public function test() {
$this->a->do_something();
}
}
$a = new A();
$a->test(); // do_something
It's hard to give an advice on what the best approach for your particular case would be, as we don't know what either A or B does.
There's a few ways to achieve this. One way would be to make B and extension of A - thereby allowing all methods of the class A to be callable on the object B. Another way is to create a new object of A inside B and call that method. Or you can pass
Here's an example where B is extended from A. By doing this, all properties and methods of A can be called on B, unless overwritten in B.
class A {
public function doSomething(){
echo "doSomething() called in A";
}
}
class B extends A {
public function someMethod() {
$this->doSomething();
}
}
$b = new B();
$b->someMethod();
The above would output doSomething() called in A.
Or, you can create an object A and call that method inside B.
class B {
public function someMethod() {
$a = new A();
$a->do_something();
}
}
$b = new B();
$b->someMethod();
After reading all the answers and doing some research i think that the best method for me was the use of Traits
"Traits are a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies."
So i declared a Trait with the method do_something and call that method from Both class A and Class B
Thanks

Extending classes in PHP - strange behaviour

First, quote from PHP manual (http://php.net/manual/en/keyword.extends.php):
The extended or derived class has all variables and functions of the
base class (this is called 'inheritance' despite the fact that nobody
died) and what you add in the extended definition.
So why is that this simple example doesn't work:
<?php
class A
{
private function a()
{
echo 'a';
}
public function b()
{
echo 'b';
}
}
class B extends A
{
//no extended definition, only what's inherited
}
$object_B = new B();
echo $object_B->b(); // fatal error: Call to private A::a() from invalid context
?>
After some experimenting, it turns out that removing method a from class A
makes it work. And I'm not even calling it anywhere.
You can use a method of the same name as a constructor with a PHP class. So, your method a is acting as a constructor for class A.
Rename your method, and it should work:
class First
{
private function another()
{
echo 'a';
}
public function b()
{
echo 'b';
}
}
See __construct() vs SameAsClassName() for constructor in PHP
"Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP" - Reports PHP 7 after executing the sample code.
I think you can't name the method with the same name as the class. In older PHP-Versions you could define the constructor of the class by naming the method like the class. PHP assumes the functions a to be a constructor. So it won't work that way.
Like Zac Brown said, you have to use the __construct() method.
In class A you have define a() method it with same name of class. so it is constructor method of A class. but in PHP you can not make private constructor method. your code should be like this.
<?php
class A
{
public function a()
{
echo 'a';
}
public function b()
{
echo 'b';
}
}
class B extends A
{
//no extended definition, only what's inherited
}
$object_B = new B();
echo $object_B->b();
Here's the clarification:
You are defining method a() in Class A. They have the same name so method a() is treated as constructor of Class A. Therefore, the moment you initialize Class B in $object_B = new B();, you initialize Class A too since A is extending B and the constructor method is called. Because Classes which have a constructor method call this method on each newly-created object PHP Constructor. and hence the error.
I believe this clarifies your doubt.

static method vs non-static method

Below are the examples of php class code that is static method and non static method.
Example 1:
class A{
//None Static method
function foo(){
if (isset($this)) {
echo '$this is defined (';
echo get_class($this);
echo ")<br>";
} else {
echo "\$this is not defined.<br>";
}
}
}
$a = new A();
$a->foo();
A::foo();
//result
$this is defined (A)
$this is not defined.
Example 2:
class A{
//Static Method
static function foo(){
if (isset($this)) {
echo '$this is defined (';
echo get_class($this);
echo ")<br>\n";
} else {
echo "\$this is not defined.<br>\n";
}
}
}
$a = new A();
$a->foo();
A::foo();
//result
$this is not defined.
$this is not defined.
I am trying to figure out what is the difference between these two Classes.
As we can see on the result of the none static method, the "$this" was defined.
But on the other hand the result on the static method was not defined even they were both instantiated.
I am wondering why they have different result since they were both instantiated?
Could you please enlighten me on what is happening on these codes.
Before we go any further: Please, get into the habbit of always specifying the visibility/accessibility of your object's properties and methods. Instead of writing
function foo()
{//php 4 style method
}
Write:
public function foo()
{
//this'll be public
}
protected function bar()
{
//protected, if this class is extended, I'm free to use this method
}
private function foobar()
{
//only for inner workings of this object
}
first off, your first example A::foo will trigger a notice (calling a non-static method statically always does this).
Secondly, in the second example, when calling A::foo(), PHP doesn't create an on-the-fly instance, nor does it call the method in the context of an instance when you called $a->foo() (which will also issue a notice BTW). Statics are, essentially, global functions because, internally, PHP objects are nothing more than a C struct, and methods are just functions that have a pointer to that struct. At least, that's the gist of it, more details here
The main difference (and if used properly benefit) of a static property or method is, that they're shared over all instances and accessible globaly:
class Foo
{
private static $bar = null;
public function __construct($val = 1)
{
self::$bar = $val;
}
public function getBar()
{
return self::$bar;
}
}
$foo = new Foo(123);
$foo->getBar();//returns 123
$bar = new Foo('new value for static');
$foo->getBar();//returns 'new value for static'
As you can see, the static property $bar can't be set on each instance, if its value is changed, the change applies for all instances.
If $bar were public, you wouldn't even need an instance to change the property everywhere:
class Bar
{
public $nonStatic = null;
public static $bar = null;
public function __construct($val = 1)
{
$this->nonStatic = $val;
}
}
$foo = new Bar(123);
$bar = new Bar('foo');
echo $foo->nonStatic, ' != ', $bar->nonStatic;//echoes "123 != foo"
Bar::$bar = 'And the static?';
echo $foo::$bar,' === ', $bar::$bar;// echoes 'And the static? === And the static?'
Look into the factory pattern, and (purely informative) also peek at the Singleton pattern. As far as the Singleton pattern goes: Also google why not to use it. IoC, DI, SOLID are acronyms you'll soon encounter. Read about what they mean and figure out why they're (each in their own way) prime reasons to not go for Singletons
Sometimes you need to use a method but you don't want call class, because some functions in a class called automatically like as __construct, __destruct,... (Magic Methods).
called class:
$a = new A();
$a->foo();
Don't called class: (just ran foo() function)
A::foo();
http://php.net/manual/en/language.oop5.magic.php

Variables in Classes

I stumbled across a very wired error in php:
class A {
public $var = "test";
public function __construct() {
$this->var = "test2";
$b = new B;
$b->method();
}
}
class B extends A {
public function method() {
$c = new C;
$c->method();
}
}
class C extends B {
public function method() {
echo $this->var;
}
}
$a = new A;
I get the output "test", but I do not know why, cause the variable var should be overwritten in Class A.
If I output $var in Class A it says "test2", if I output it in Class B it says "test"…
The code on your question won't work because of the circular references (eg: $b = new B in A's constructor), which will cause PHP to run out of memory. You really shouldn't be instantiating children classes in a parent class.
That being said, by what you are describing, it sounds like you are defining a constructor in B, which overrides the parent constructor. In PHP children classes don't implicitly call the parent constructor (unlike in languages like Java).
So, it just inherits the original value for $var (ie: "test"), which is never changed. If you are overriding __construct() in B, you'll have to explicitly call the parent constructor, like:
class B extends A {
public function __construct() {
parent::__construct();
}
}
And that should give you "test2" when you do something like:
$b = new B;
echo $b->var;
See this demo: http://ideone.com/Q9Bp8
What is the best way to have 3 classes, where the third and second can access variables of the first class?
The answer is, it depends on what you are doing. It sounds like you are not understanding how OOP works, which is a bigger problem. In general you only use inheritance when the children classes could reuse code from the parent class, and/or there is some sort of is-a or has-a relationship.
If your classes don't fit this model, just make the 3 classes independent, and hold a reference to the first class in your other classes. For example:
class A {
public $n = 0;
public function change($n) {
$this->n = $n;
}
}
class B {
public function __construct($a) {
$this->my_a = $a;
}
public function get() {
return $this->my_a->n;
}
}
$a = new A();
$b = new B($a):
echo $b->get(); // 0
$a->change(10);
echo $b->get(); // 10
See this demo: http://codepad.org/xL1Dzs0W

How to get the class that created the current object?

I would like to prevent foo() from being executed by any other class than B. How can I check which class created object A?
<?php
class A
{
public function foo()
{
if (.... B ) // what should be on the dotts?
echo 'I\'m created by class B, which is fine';
else
echo 'Execution of foo() is not allowed';
}
}
class B
{
public function go()
{
$a = new A;
$a->foo();
}
}
class C
{
public function go()
{
$a = new A;
$a->foo();
}
}
$b = new B;
$b->go(); // result: I\'m created by class B, which is fine
$c = New C;
$c->go(); // result: 'Execution of foo() is not allowed'
A commonly asked question (e.g. How to get called function name in __construct without debug_backtrace), but in a well-designed application it shouldn't be necessary for a class to know where it's being called from, or to prevent being instantiated when requested.
If you need this type of restriction, then make your class a private attribute of the main class that is permitted to access it.
If you absolutely have to do it, pass the caller through as an argument to the method in preference to the horrendously inefficient debug_backtrace method.
Declare foo in class B instead and make it private and, optionally, final. Why would want to define in A a method that can only be called by B?

Categories