1

I have a language class with public data members:

class language {
    public $error = "There was an error";
}

Then I have many different classes that uses this class. How can I access this class from within other classes? You could of course instantiate an object of it inside all the classes that uses it, but I suppose that would drastically decrease the performance, if I were to do that with multiple classes.

I do only need one object, since I don't change them anyway. So, I've done

$language = new language();

class name {
    private $language;

    public function __construct() {
        global $language;
        $this->language = $language;
    }


    public function method() {
        mysql_query(...) or die($this->language->error);
    }
}

Is this a good way to do it? Now I have to instantiate it in every "mother" script. And I suppose by doing __construct() I'm only passing a refrence, since I don't use the clone word?

0

5 Answers 5

2

Basically your language object is a dependency of your other objects. There are a number of factors you need to consider: - performance (how wise it is to instantiate a new language object each time you need it, or whether that is even possible) - testing - how you could test your classes if each one has a hard-coded dependency on your language class - maintainability/readability.

There are various different solutions to the problem. The one that seems to be most in fashion in the PHP community is the Dependency Injection Container. This can be a good solution if you are in a greenfield situation.

A good article on the general subject is one by Martin Fowler (who else?).

EDIT: To explain a bit more the article deals with the Inversion of Control principle. I won't explain it in depth as I don't think I could do it as well as Martin Fowler amongst others but the nub of it is that your classes do not manage their own dependencies; that is done elsewhere (hence the name Inversion of Control). There are broadly two different ways of doing it - Dependency Injection (which may or may not involve a Container) and Service Locator. This section of Martin Fowler's article deals with some of the differences between the two.

Sign up to request clarification or add additional context in comments.

4 Comments

Can you please briefly explain it here?
@StudentofHogwarts I've added a bit more explanation.
Can you add an example in PHP?
That's,probably beyond the scope of SO. Maybe go and read some articles about it, have a go and post a new question if you get stuck.
1

I do only need one object

This is the Singleton pattern.

Here is a quick example of a way to have only one instance of your Language class:

class Language {
  public $error = "text";

  private static $instance = null;

  public static function getInstance() {
    if (self::$instance == null)
      self::$instance = new self();
    return self::$instance;
  }

  private function __construct() {}
}

$lang = Language::getInstance();
$text = $lang->error;

You can also use dependency injection:

interface ILanguage {
  public function getError();
}

class Language implements ILanguage {
  private $error = "error";
  public function getError() {
    return $this->error;
  }
}

class name {
  private $language;

  public function __construct(ILanguage $lang) {
    $this->language = $lang;
  }

   public function method() {
     mysql_query(...) or die($this->language->getError());
   }
}

$language = new Language();
$n = new name($language);

This example of dependency injection is called constructor injection.

14 Comments

Aha, is this a common known "rule" or "pattern"? $lang = Language::getInstance(); passes a reference, not the object itself?
Yes this is a common Design Pattern: en.wikipedia.org/wiki/Singleton_pattern Here the object is not copied because as mentioned in this page: php.net/manual/en/language.oop5.references.php 'When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.'
@DanLee this is a highly subjective point of view, you should have it phrased it differently: "some people, such as dependency injection advocates, consider the singleton pattern as an anti-pattern"
@SirDarius yeah you are right it is my point of view. But I can't take "making everything global" (that's what it basically is) as a serious pattern. Then we all could stick to functions and the global keyword. I like the hierarchies in OOP, because you know on what you can rely and on what not.
@DanLee Well said. See my answer!
|
1

Instantiate the Language object in the constructor of your class:

public function __construct() {
  $this->language = new Language();
}

4 Comments

Yes, but wouldn't that slow down the script, and use unnecessary amounts of memory? I don't need to change what's inside the language class at run time anyway.
So it'll make a separate object for every class that have errors or outputs anything.
If what you need is a "global" object, you might consider to write Language class as static.
Accept one answer and you'll get 2 rep points, then you will have 15
1

If you do not want to have instances of this class, consider making its properties and methods static:

class language {
    static public $error = "There was an error";
}

then use them statically:

$error = language::$error;

2 Comments

Hmm, that is interesting. I didn't know that it worked that way. I thought a static was something that the objects shared.. What do you think is the best method? I'm completely new to OOP, and just thought about that instantiating an object more times than nececcary would slow down the script?
static properties and methods belong to the class itself, not to its instances. They are "shared" between the instances only in the sense that they can access them via the self pseudo-class. You access static properties as Class::$property and static methods as Class::method(). What you need in your case is either a Sintlegon, or a class with static properties like this.
1

Instead of using global variable, you could pass it via constructor.

public function __construct($language) {
    $this->language = $language;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.