4

In a messaging project, I have two classes, number and message. The first class does the stuff about numbers and second one does the messages processes.

number->recive() should call message->getPass(). then message->getPass should produce a password, and reply it to user using message->send().

and there are many situations like this that I want this class in that and that in this...

I tried $this->number = new number() in message class's __constructor() and vice versa, but got an Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 65488 bytes).

I think the error reason is obvious, I'm causing an infinite loop of instantiating.

Is There Any Way to Have Two Classes Which Use Each Other? Whats the Right Way to Go?

Thanks

Edit 0: Thanks for super fast answers/comments!

Edit 1: I saw this question How to create two classes in C++ which use each other as data? I don't have any idea what exactly those asterisks mean, and if I can use it in php!

Edit 2: about the codes caused error, simply:

test.php:

include_once './number.php';
$number  = new number();
$number->recive();

number.php:

include_once './message.php';
class number {

    public function __construct($numberId = NULL) {
        $this->message = new message();
        $this->pdo = new PDO("mysql:host=localhost;dbname=madb", "root", "root");
    }
    ...
}

message.php:

class message {

    protected $pdo, $rows, $sql, $number;

    public function __construct($messageId = NULL) {
        $this->number = new number();
        $this->pdo = new PDO("mysql:host=localhost;dbname=madb", "root", "root");
    }
    ...
}

Edid 3:

Some kind of solution maybe this:

Add a load method to each class:

public function load($className) {
    require_once $className . '.php';
    $this->{$className} = new $className();
}

so you should call $this->load('number') to load number class from number.php whenever I need it, and then use it in this way $this->number->numberMethod() .

Community
  • 1
  • 1
Webinan
  • 4,084
  • 5
  • 33
  • 50
  • 6
    Create a 3rd class that uses the other class maybe? – jeff Aug 11 '13 at 15:56
  • Why not using extends? – pregmatch Aug 11 '13 at 15:57
  • @Webinan Don't you mean `number->send()` instead of `message->send()` ? – g4vroche Aug 11 '13 at 16:10
  • @pregmatch then which one should extend the other? number class methods rely on message class methods, and message class methods rely on number class methods! – Webinan Aug 11 '13 at 17:07
  • I used a 3rd class. I also came up with a loader method solution, I will share it in an edit to my question. – Webinan Aug 18 '13 at 13:17
  • why do you create the PDO instance in each of the classes? Why don't you use Dependency Injection? In fact, that would solve your entire problem. – Gordon Aug 18 '13 at 16:09
  • @Gordon Umm, Use What? :D just give me an starting link and I go all the way, Please. – Webinan Aug 18 '13 at 17:09
  • @Gordon I changed these files, now I'm using singleton as I said. Do you mean `$dbh=new PDO(...); $c1=new class1($dbh); $c2=new class2($dbh);` connect to mySql for 3 times, when said instances are not shared? You didn't mean this. – Webinan Aug 18 '13 at 17:18
  • 1
    @Webinan See http://fabien.potencier.org/article/11/what-is-dependency-injection for a good explanation of Dependency Injection. – Gordon Aug 18 '13 at 17:53

2 Answers2

3

I would advise you - as jeff said in a comment - to create a third class which uses them both.

However, a quick solution for your problem:

Message class:

private $number;

public function __construct() {
  $this->number = new Number($this);
}

Number class:

private $message;

public function __construct($msg) {
  $this->message = $msg;
}
ComFreek
  • 27,416
  • 16
  • 97
  • 150
  • Yes, a third class. In quick solution, what should be $msg? an instance of message class? – Webinan Aug 11 '13 at 16:25
  • @Webinan If you get a fatal error it's your own fault for just copy / pasting without thinking. – Bart Aug 11 '13 at 16:31
  • @Bart I know it's my fault, I'm not reporting a PHP bug! I copy/pasted nothing, I just wanted to know how should I have such a functionality, and this code was my approach. – Webinan Aug 11 '13 at 16:48
  • @Webinan Yes, $msg is an instance of the *Message* class. Have you already tried my code? In *test.php*, you must instantiate a *Message* object, not a *Number* object! (@Bart: Did I miss any comments? Why do you comment on my answer? I'm just curious.) – ComFreek Aug 11 '13 at 17:43
  • I just went with the 3rd class! – Webinan Aug 18 '13 at 13:09
-1

You could have one or both classes be singleton, which would prevent the need to construct either one of them more than once... add a static getInstance() method to both which either returns a previously constructed instance or a new one... look up "singleton pattern" and you'll see how this works.

Michael Steuer
  • 377
  • 2
  • 7
  • I looked up and used the singleton pattern for my PDO instance and in some other cases, thanks for suggestion. – Webinan Aug 18 '13 at 13:12
  • [Friends don't let use friends use Singletons](http://stackoverflow.com/questions/4595964/who-needs-singletons/4596323#4596323) /cc @Webinan – Gordon Aug 18 '13 at 16:06
  • That's a terrible suggestion – Evert Aug 18 '13 at 16:29
  • @Evert realy? :D ok, I'm new to oop principles and after searching and reading different practices my brain is halting! I've found many DON'Ts , DON't use singleton, DON'T use static, ... so what is the right way? Is it ok to get PDO $connection and use `$dbh = new PDO($connection)` in each class? – Webinan Aug 18 '13 at 17:08
  • 1
    The right way is "don't use [singletons](http://blog.gordon-oheim.biz/2011-01-17-Why-Singletons-have-no-use-in-PHP/), [statics](http://kore-nordmann.de/blog/0103_static_considered_harmful.html) or [globals](http://stackoverflow.com/questions/5166087/php-global-in-functions)" Avoid them like the plague. You can experiment with them once you got a better grasp on object oriented programming to figure out why they are bad, but for now just forget they exist. – Gordon Aug 18 '13 at 17:58
  • @Gordon Big thanks for saving me from this plague, and I'm reading Fabien's series on dependency injection, and I've met his Pimple (simple Dependency Injection Container) project, but isn't there a temporary quick way for working with my PDO instance? An example with pimple or other simple DI is also appreciated. – Webinan Aug 18 '13 at 18:20
  • @Webinan: The answer you accepted is perfect actually. If it's not entirely clear I can add another answer with a more detailed explanation. – Evert Aug 18 '13 at 18:36
  • @Evert It'll be very nice if you do so, or provide a link. You friends are increasing my responsibility to this community :) – Webinan Aug 18 '13 at 18:44
  • @Evert Isn't that answer a singleton pattern? it is passing an instance to the constructor. – Webinan Aug 18 '13 at 18:54
  • 1
    @Webinan, no a singleton pattern implies that only one instance of a given class can exists, and effectively prevents subclassing / substition which is the whole reason anyone would want to use OOP in the first place. – Evert Aug 18 '13 at 22:06
  • @Evert Yes, got it, I also quote Fabien Potencier's similar answer to a similar question in his DI container article: _A singleton is when you can only have one instance of an object. Moreover, the singleton pattern is implemented by the class itself by protecting the constructor and providing a static method to access the only available instance. For the mail object, things are totally different. The Zend_Mail class is not a singleton and you have a different instance per container. As the container itself is not a singleton, the objects contained inside the container are not singletons._ – Webinan Aug 19 '13 at 13:57