1

I am making my own framework and have a translator class that is used in a few places throughout the application.

My concern is that the translator class has a constructor that includes all the necessary files for translation which means that every object that has a translator includes these files possibly multiple times.

This is an example of the translator class.

class Translator{
    protected $translations;

    public function __construct(){
        $this->translations[] = include $this->language . ".php"; //General texts for a language
        $this->translations[] = include $this->language . "-" . $this->controller . ".php"; //General texts for a controller
        $this->translations[] = include $this->language . "-" . $this->controller . "-" . $this->action . ".php"; //Specific texts for an action
    }

    public function translate($key){
        return $this->translations[$key];
    }

}

This would be how to do it by extending. After reading about object composition, this way seems to be strongly discouraged. See http://www.cs.utah.edu/~germain/PPS/Topics/oop.html

class View extends Translator{
    ...
}

With what I read about object composition this is how I understand how it should be made. Wrong? If not, this makes multiple instances of the translator class and still has the problem of multiple includes if I'm not mistaken.

class View{
    protected $translator;

    public function __construct(){
        $this->translator = new Translator();
    }

    ...
}

Instead of creating a new Translator, how about sticking it in a global variable?

$translator = new Translator();

class View{
    protected $translator;

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

    ...
}

Last idea, with public functions instead of a class

$translations = //Include the language array files like in the translator class

function translate($key){
    global $translations;
    return $translations[$key];
}
Alexander Weihmayer
  • 366
  • 1
  • 3
  • 10
  • 1
    Nothing should extend the Translator class unless it *is* a Translator. Nor should something called Translator ever extend something Application. – PeeHaa Nov 13 '15 at 18:48
  • 1
    Learn about object composition. – PeeHaa Nov 13 '15 at 18:48
  • 1
    Also it looks like your classes are doing too much. As in they have too many responsibilities if they all need access to said Translator – PeeHaa Nov 13 '15 at 18:50
  • Alright I'll dip into learn how to better create objects. Any good sources to recommend? Also, say my objects were properly made, what is the standard practice for translators? – Alexander Weihmayer Nov 13 '15 at 18:52
  • Well one could write multiple books about this. As a matter of fact people did. – PeeHaa Nov 13 '15 at 18:56
  • 1
    *"So far, other classes extend the translator class to have access to the translation methods."* => And won't the other classes also want to extend the router to have access to routing methods, and the controller to access the view-related methods, and, and, and? But that's not going to work because you cannot extend multiple classes. Did you think about this? – Jon Nov 13 '15 at 20:01
  • Yes, I think everything is pretty neat and not duplicated except the translator which is being extended a few times (in the classes shown) which I find horrid. I don't want multiple instances or extending it everywhere so I was thinking of making simple public translate functions (will show example in edit). – Alexander Weihmayer Nov 13 '15 at 20:05
  • 1
    @AlexanderWeihmayer: To be clear: the idea of extending translator is horrible and misguided. Before killing it with fire you should of course understand why, but that's another topic. Here I was trying to offer other, more immediately practical reasons why this would not work. Which I still think it won't. But even if it did, that was just my sidenote. **Don't ever do this.** This error is also known as "car extends engine", you might have better results searching for that. – Jon Nov 13 '15 at 20:13
  • Read a bit about it and I understand a little bit more what people are saying about object composition. Made an edit to confirm :O – Alexander Weihmayer Nov 13 '15 at 20:35
  • 1
    @AlexanderWeihmayer: The easiest improvement from there is to make translator a singleton -- multiple instance problem solved. But then you would want to read on what drawbacks this way of doing things has and how it compares to dependency injection. – Jon Nov 13 '15 at 20:48
  • Read what a singleton was and I am happy! Though there are some drawbacks in many situations, but I highly doubt it will be a problem for the purposes of my translator. If you would like to post the answer, I'd be sure to accept it. – Alexander Weihmayer Nov 13 '15 at 20:59

1 Answers1

0

EDIT

I found out that static classes are even easier to use. Basically, you don't need to get an instance of the translator when you need it, you can use it throughout the entire application by using a static class. I thought there was a performance issue with using static classes, but apparently that isn't the case with new PHP releases.

Check this out to get an idea on how to make and use static classes: Is it possible to create static classes in PHP (like in C#)?

OLD

As mentionned by Jon, the method I ended up chosing was a singleton class for the translator. Basically, the translator instance is created only once and everywhere that asks for an instance of the translator gets the same instance. Make sure you learn about the drawbacks of such a method before using it.

Here is a good example of how to do this Creating the Singleton design pattern in PHP5

Quick demo

final class Translator{
    protected $translations;

    public static function getInstance(){
        static $inst = null;
        if ($inst === null){
            $inst = new Translator();
        }
        return $inst;
    }

    private function __construct(){ //Private constructor so nobody else can instance it
        ...//Look at translator class in question
    }
}

To get the instance of the translator, call this where you need it.

$translator = Transaltor::getInstance();
Community
  • 1
  • 1
Alexander Weihmayer
  • 366
  • 1
  • 3
  • 10