This's my second question, even thought, i answered the previous one, on my own. Anyway, I have a basic problem with OOP, on how to call a non-static method from another class. example:
We have a class named A in a file A.class.php
class A {
public function doSomething(){
//doing something.
}
}
and a second class named B on another file B.class.php
require_once 'A.class.php';
class B {
//Call the method doSomething() from the class A.
}
I think now it's clearn. How to : Call the method doSomething() from the class A ?
Class B will need an object of Class A to call the method on:
class B {
public function doStuff() {
$a = new A();
$a->doSomething();
}
}
Alternatively, you can create the instance of A outside of B and pass it into B's constructor to create a global reference to it (or pass it to an individual method, your choice):
class B {
private $a = null;
public function __construct($a) {
$this->a = $a;
}
public function doStuff() {
$this->a->doSomething();
}
}
$a = new A();
$b = new B($a);
How about injecting class A into B, making B dependant on A. This is the most primitive form of dependency injection:
class A
{
public function doSomething()
{
//doing something.
}
}
class B
{
private $a;
public function __construct( A $a )
{
$this->a = $a;
}
//Call the method doSomething() from the class A.
public function SomeFunction()
{
$this->a->doSomething();
}
}
This is constructed like this:
$a = new A();
$b = new B( $a );
You need to instantiate a an object of class A. You can only do this inside a method of class B.
class B{
public function doSomethingWithA(){
$a = new A();
return $a->doSomething();
}
}
class B {
public function __construct()
{
$a = new A;
$a->doSomething();
}
}
I know this is an old question but considering I found it today I figured I'd add something to #newfurniturey's answer.
If you wish to retain access to class B within class A this is what I did:
class A
{
private $b = null
public function __construct()
{
$this->b = new B($this);
if (!is_object($this->b) {
$this->throwError('No B');
}
$this->doSomething();
}
public function doSomething() {
$this->b->doStuff();
}
private function throwError($msg = false) {
if (!$msg) { die('Error'); }
die($msg);
}
}
class B {
public function doStuff() {
// do stuff
}
}
This is constructed like this:
$a = new A();
Related
My question would be best illustrated by the following example:
class a
{
function a()
{
return file_get_contents('http://some/third/party/service');
}
}
class b
{
function b()
{
$a = new a();
return $a->a() . ' Bar';
}
}
class testB extends test
{
function testB()
{
$b = new b();
// Here we need to override a::a() method in some way to always return 'Foo'
// so it doesn't depend on the third party service. We only need to check
// the $b::b() method's behavior (that it appends ' Bar' to the string).
// How do we do that?
$this->assert_equals('Foo Bar', $b->b());
}
}
Let me point out that I don't have the control over where class 'a' is being defined/included.
If you changed class b so that the instance of a can be passed in:
class b
{
function b($a = null)
{
if ($a == null) {
$a = new a();
}
return $a->a() . ' Bar';
}
}
...then for test, you can use a framework like Mockery to pass in a mocked instance of 'a' which always returns 'Foo'
use \Mockery as m;
class testB extends test
{
public function tearDown()
{
m::close();
}
public function testB()
{
$mockA = m::mock('a');
$mockA->shouldReceive('a')->times(1)->andReturn('foo');
$b = new b($mockA);
$this->assert_equals('Foo Bar', $b->b());
}
}
See the full docs and examples for Mockery here: http://docs.mockery.io/en/latest/getting_started/simple_example.html
You can eliminate your dependency like that:
First you create an interface that will list all methods you need:
interface Doer {
function a();
}
Then create an adapter class for you a class:
class ADoer implements Doer
{
protected $dependencyA;
public function __construct(A $dep) {
$this->dependencyA = $dep;
}
public function a() {
$this->dependencyA->a();
}
}
Now make your B class depends on Doer interface, not on A implementation:
class B {
private $doer;
public function __construct(Doer $a) {
$this->doer = $a;
}
public function b() {
$this->doer->a();
}
public function setDoer(Doer $a) {
$this->doer = $a;
}
//getDoer()
}
Now you can switch it at will:
class FooDoer implements Doer {
function a() {
//do whatever you want
}
}
$b->setDoer(new FooDoer());
$b->b();
Say object of class B is attribute of class A. How can I call method of object of class A from method of object of class B? What would be nice solution without passing object link?
Thanks!
Here goes code sample:
class A{
var $b;
function __construct(){
$this->b = new B();
}
function f1(){
$this->b->f3();
}
function f2(){
echo 'hello!';
}
}
class B{
function f3(){
// call f2() method in object $obj(not new A())
}
}
$obj = new A();
$obj->f1();
You can use a static function
public static function f2{
echo 'hello!';
}
with f3 defined as
function f3(){
A::f2();
}
This may not ultimately be the solution you want, however. See more info here.
The only way you can access that instance's function is if you inject it on the B object as a dependency. You can inject it within the constructor, like this:
<?php
class A {
protected $b;
public function __construct() {
$this->b = new B($this);
}
public function f1() {
$this->b->f3();
}
public function f2() {
echo 'hello!';
}
}
class B {
protected $a;
public function __construct($a) {
$this->a = $a;
}
public function f3() {
$this->a->f2();
}
}
$obj = new A();
$obj->f1();
I want to understand what is the difference between these chaining method
$obj->prop_a()->prob_b($y);
and
$obj->prop_a->prob_b($x);
how to define it and how it works.
Thanks in advance
On
$obj->prop_a()->prob_b($y);
you access prop_a() as a function. It return (obviously) an object, which implements an prob_b()-function.
On
$obj->prop_a->prob_b($x);
you access prop_a as a public property which contains an object, which again implements an prob_b() function.
One calls prop_a as a method, the other doesn't.
This:
class A {
public function prop_b($x) {
return 4*$x;
}
}
class B {
public function prop_a() {
$a = new A();
return $a;
}
}
class C {
public $prop_a;
public function __construct() {
$this->prop_a = new A();
}
}
$b = new B();
$c = new C();
$b->prop_a()->prob_b(5);
$c->prop_a->prop_b(5);
I have this code:
class A
{
public $db
}
class B
{
public $cssA
public function __construct()
{
$this->cssA = new A();
}
}
The question is, how can I call a method in class B from class A?
You can't as there is no reference to the object of class B.
class A {
public $db;
private $b;
public function __construct(B $b) {
$this->b = $b;
}
}
class B {
private $a;
public function __construct() {
$this->a = new A($this);
}
}
Methods of object of class B can be now accessed through $this->b->doSomething() within object of class A.
You would have to instantiate class b within class a and then call the method...
$this->aProp = new A();
$this->aProp->classAfunction();
$aVal = $this->aProp->publicProperty;
Basic oo programming stuff.
I got two classes, "A" and "B". In the application logic no one is allowed to create an object of class "B", except for class "A".
But, since I dont want to have the two classes in the same file I cant restrict it with the "private" properity.
Is it possible to create this kind of restriction? If someone other then "A" tries to create an object of class "B", you say piss off!?
This is as hacky as it get's and you should not use it. I only post it, because I like hacky things ;) Furthermore this will throw an error if E_STRICT error reporting is enabled:
class B
{
private function __construct() {}
public function getInstance() {
if (!isset($this) || !$this instanceof A) {
throw new LogicException('Construction of B from a class other than A is not permitted.');
}
return new self;
}
}
class A
{
function someMethod() {
$b = B::getInstance(); // note that I'm calling the non-static method statically!
}
}
The reason why this works is a "feature" which may be seen in the second example of this manual page.
You could inspect the backtrace:
class B
{
public function __construct()
{
$chain = debug_backtrace();
$caller = $chain[1]['class'];
if ('A' != $caller) {
throw new Exception('Illegal instantiation');
}
}
}
In the constructor of B, require that A be passed in. When you then want to get B from A, just create a B and pass in A. When new B is called, it will require A be passed in.
class A
{
private $b;
private function getB()
{
if (null === $this->b)
{
$this->b = new B($this);
}
return $this->b;
}
}
class B
{
public function __construct(A $a)
{
}
}
Maybe you want to use something like this:
class A
{
protected function __construct ()
{
}
}
class B extends A
{
public function __construct ()
{
$a = new A();
}
}
$b = new B();
Use get_called_class to find out which class tries to instantiate an object:
class B
{
public function __construct ()
{
if(get_called_class() != 'A') {
//booboo
}
}
}