3

I wonder how i can call a method of a class inside of a method in other classes that called method is in a class that declared after the classes that use inside. Let me show you an example:

Database.php:

class Database{
    modifyUser($field,$change){
        global $logging;
        if($database->query('MYSQL QUERY')){
            $logging->modifyUser($field,$change);
        }
    }
}
$database = new Database;

Logging.php:

class Logging{
    modifyUser($field,$change){
        global $database;
        $database->query('Mysql Query for Logging');
    }
}
$logging = new Logging;

now problem is if use top classes in included file like this:

user.php

include('database.php');
include('logging.php');

php shows an error that you use $logging variable which is not declared as class yet. and if I change like this:

user.php

include('logging.php');
include('database.php');

same error but for $database; I don't know how to use it that PHP doesn't conflict for sequences.

1ry
  • 77
  • 10
  • Try to think of another solution in which you don't need global variables. You could also put your classes in single files, and place the lines `$logging = new Logging()` and `$database = new Database()` below the includes. – user254875486 Aug 09 '13 at 08:05
  • You are creating an object named $database of the class Database. And also defined another global variable named $database. Same thing is happening for $logging. Give them a separate name. If you want to access a method inside another function which resides in the same class, you can use scope resolution operator. For eg. $this::query(); – Debashis Aug 09 '13 at 08:08
  • `if (!instanceof ...)` – u_mulder Aug 09 '13 at 08:09
  • 2
    Have `Logging` `extend` `Database`, so you can use an internal reference rather than globalling a standard variable – MDEV Aug 09 '13 at 08:12
  • @SmokeyPHP : better to let `database extend logging` not ? – DarkBee Aug 09 '13 at 08:13
  • 1
    @DarkBee No, the core functionality is `Database`, an extension of that is the ability to log (from what i can gather) - `Logging` would use the connection of `Database` to make/read logs – MDEV Aug 09 '13 at 08:14
  • If u put it like that It make sense yes. I would rather see something like `$database = new Database(new Logging());` tho, so u can easily change how something is logged – DarkBee Aug 09 '13 at 08:17
  • 1
    @SmokeyPHP: That is a very bad approach. – Jon Aug 09 '13 at 08:24
  • @Jon Depending on what exactly these classes are doing, no it's not. Granted it's not an answer for everything, but if he's trying to do what I think he is, then it's just fine.. – MDEV Aug 09 '13 at 08:27
  • 1
    @SmokeyPHP: If these classes are even remotely named appropriately then it is not. It is *much* more likely that `Database` should aggregate a `Logging` object instead. – Jon Aug 09 '13 at 08:29
  • possible duplicate of [Reference: What is variable scope, which variables are accessible from where and what are "undefined variable" errors?](http://stackoverflow.com/questions/16959576/reference-what-is-variable-scope-which-variables-are-accessible-from-where-and) – deceze Aug 09 '13 at 09:29
  • This is precisely one of the reasons you *inject dependencies*, not *pull* them in. See [How Not To Kill Your Testability Using Statics](http://kunststube.net/static/) (same problem, but focused on static calls). – deceze Aug 09 '13 at 09:33
  • @Lex Unfortunately your offered way doesn't work because two classes use each other methods. So in your way I will face error again. – Pejman Ghasemi Aug 09 '13 at 09:35
  • @Debashis Your solution doesn't work for my question because I have no problem for global variable. the global logging variable will declare after database class so php doesn't know that variable as a class at that moment. – Pejman Ghasemi Aug 09 '13 at 09:38
  • @deceze I think you solution is one of the best choice which I have. Why don't you post it as an answer to tick your answer as accepted? – Pejman Ghasemi Aug 09 '13 at 09:41

2 Answers2

2

I don't think it is possible, if you run the following code with command line you'll get "Segmentation fault" error;

class A
{
    private $b;
    public function __construct()
    {
        $b = new B();
    }
}

class B
{
    private $a;
    public function __construct()
    {
        $a = new A();
    }
}

$x = new A();


it is like an infinite loop.

Soosh
  • 812
  • 1
  • 8
  • 24
1

First of all you can use include_once / require_once, so only the first time the file is needed, it will be loaded

Also, you can use autoloading

And instead of using global variables, either pass the instance or provide some sort of factory. Relying on global variables is bad for your encapsulation and it's ugly in an OO code

Maxim Krizhanovsky
  • 26,265
  • 5
  • 59
  • 89
  • So how to use logging class in database? I don't want to do like this:`$database->modify($field,$change);$logging->modify($change,$field)`. I want to if anyone call modify then add a log in database. (Regards to ugly an OO Code) – Pejman Ghasemi Aug 09 '13 at 09:49