Viewed   68 times

I need to determine, after all files have been included, which classes extend a parent class, so:

class foo{
}
class boo extends foo{
}
class bar extends foo{
}

and I'd like to be able to grab an array like:

array('boo','bar');

 Answers

1

If you need that, it really smells like bad code, the base class shouldn't need to know this.

However, if you definitions have been included (i.e. you don't need to include new files with classes you possibly have), you could run:

$children  = array();
foreach(get_declared_classes() as $class){
    if($class instanceof foo) $children[] = $class;
}
Thursday, September 1, 2022
1

A base class should really never depend on information about child classes---

To answer your question:

class base {
    public function __construct() {
        print "Class:" . get_class($this) . "n";
    }
}

class child extends base{
    public function __construct() {
        parent::__construct();
    }
}
$c = new child();

Just for future reference -- this can be acheived in a static context using get_called_class(), but this is only available in PHP >= 5.3

Saturday, October 8, 2022
2

You can use the instanceof operator, to check if an object is an instance of :

  • A class
  • Or a child class of that class
  • Or an instance of a class that implements an interface

Which means that it cannot be used to detect if your object is an instance of a specific class -- as it will say "yes" if your object is an instance of a child-class of that class.


For instance, this portion of code :

class ClassA {}
class ClassB extends ClassA {}

$a = new ClassB();
if ($a instanceof ClassA) {
    echo '$a is an instanceof ClassA<br />';
}
if ($a instanceof ClassB) {
    echo '$a is an instanceof ClassB<br />';
}

Will get you this output :

$a is an instanceof ClassA
$a is an instanceof ClassB

$a, in a way, is an instance of ClassA, as ClassB is a child-class of ClassA.

And, of course, $a is also an instance of ClassB -- see the line where it's instanciated.

Friday, August 12, 2022
 
hooked
 
1

It is not possible to prevent the constructor from being called when the object is constructed (line 9 in your code). If there is some functionality that happens in your __construct() method that you wish to postpone until after construction, you should move it to another method. A good name for that method might be init().

Why not just do this?

class Test {
    public function __construct($param1, $param2, $param3) {
        echo $param1.$param2.$param3;
    }
}

$ob = new Test('p1', 'p2', 'p3');

EDIT: I just thought of a hacky way you could prevent a constructor from being called (sort of). You could subclass Test and override the constructor with an empty, do-nothing constructor.

class SubTest extends Test {
    public function __construct() {
        // don't call parent::__construct()
    }

    public function init($param1, $param2, $param3) {
        parent::__construct($param1, $param2, $param3);
    }
}

$ob = new SubTest();
$ob->init('p1', 'p2', 'p3');

This is might make sense if you're dealing with some code that you cannot change for some reason and need to work around some annoying behavior of a poorly written constructor.

Saturday, September 10, 2022
 
4

You may use Factory Pattern. Basket, Billing and Delivery objects should be created by the 3rd-party service API wrapper class:

$svc = new The3rdPartyServiceApiWrapper();
$svc->init();  // connect, get session etc.
if ($svc->fail()) die("halp! error here!");

$basket = $svc->createBasket();
$baskSumm = $basket->getBasketSummary();

$billing = $svc->createBilling();
$billSumm = $billing->getBillingSummary();

$delivery = $svc->createDelivery();
$delSumm = $delivery->getDeliverySummary();

The best way to connect Basket, Billing and Delivery class with the API is storing a reference to the API class, then they can call any method of it, not just getSession().

Another advantage is, that if you have an identified entity, e.g. a User, then the wrapper class can grant you, that there will be no double objects in the scene.

If the main program creates the users, there should be different objects with the same user, which is wrong:

$user1 = new User("fred12");
$user2 = new User("fred12");

VS if the API wrapper creates them, the wrapper class should keep a "cache" of users, and return with the same User object for the same request:

$user1 = $svc->createUser("fred12");
$user2 = $svc->createUser("fred12");  // $user2 will be the same object

(Maybe it's not a best example, if a program creates twice the same User, it means that the program has major design faulty.)

UPDATE: explanation of svc class

The The3rdPartyServiceApiWrapper should look like this:

 function getSessionId() {
   return $this->sessionId;  // initialized by constructor
 } // getSessionId()

 function createBasket() {
   $basket = new Basket($this);
   return $basket;
 } // createBasket()

The Basket:

 function Basket($s) {  // constructor of Basket class

   $this->svc = $s;

   //... the rest part of constructor

 } // Basket() constructor

function doSomethingUseful() {

  // if you wanna use the session:
  $sess = $this->svc->getSessionId();
  echo("doing useful with session $session");

  // you may access other api functions, I don't know what functions they provide
  $this->svc->closeSession();

} // doSomethingUseful()
Tuesday, October 18, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :