I built some the following i18n function which is called several times when rendering view :
function e_($text)
{
$t = Translate::Instance();
vprintf($t->_($text), array_slice(func_get_args(), 1)); // outputs translated text
}
Currently, I get the instance of the Translate singleton Class inside the function.
I've read that dependency injection should be used instead.
But If I do use dependency injection, I will have to pass the Translate object each time into the function, right ?
This would became :
<?php e_('my text', $this->Translate);
and not simply <?php e_('my text'); ?>
Well I'd like to avoid that.
The way you use the e_ function is actually using an alias. That's fine as long as you can live with it. You don't need to use a singleton to implement an alias:
function e_($text)
{
return $GLOBALS['e_alias']->alias(func_get_args());
}
When setting up the view layer, set the dependency:
$GLOBALS['e_alias'] = $translate;
In application context, set the global variable $translate. This will allow you to move away from the singleton (which are liars), and you actually only need a global variable.
Additionally it allows you to test views with the e_ alias against different translation implementations.
The downside is that you need to manage a list of all these special global variables, like you need to maintain for the global functions like e_.
See as well this answer to the Getting $this inside function question.
True. The reason you would use dependency injection instead is so that you could swap out the translation method for any particular use of e_().
In this particular case, I'm not sure it would be worth it unless you wish to test different translation methods during testing.
One thing you could do to help a little with performance is make $t static so that Translate::Instance() is only ever called once no matter how many calls to e_() are made.
Related
For my latest website I’ve been trying to use classes. Mainly to teach myself more about OOP and learn through experience.
Whenever I needed a ‘variable’ within my class I created a property, for instance:
class someClass
{
var $valueToUseHere; // Only used internally - can I just use a variable?
public function doStuff()
{
$this->valueToUseHere = 60;
// Do more stuff here...
}
}
It is only now when I’ve been looking more into the code and trying to do some optimisation that I’ve noticed that my functions and classes are passing around some large objects. A lot of that bulk could be stripped away if I made all the properties that are only used inside the class into normal variables.
Are properties only used for variables that are needed outside the class and is it then acceptable to just use ‘normal’ variables within the class itself ?
Sorry if this question illustrates a lack of understanding on the subject. Unfortunately, this is where my learning is up to at this point. I’ve done some searching around “class properties vs variables” etc but not found a comprehensive answer to this.
Many thanks
It's somewhat vague what you're asking, but if valueToUseHere is not used outside of doStuff, then don't make it a property!
class someClass {
public function doStuff() {
$valueToUseHere = 60;
// Do more stuff here...
}
}
If there's no reason to share that value with other methods of the class or with the outside world, then there's no reason to clutter up your object with all sorts of properties. Not only may this cause tricky bugs with preserved state, it also forces you to be unnecessarily careful with your variable names across all object methods.
Actually class properties are variables as well. Basically you have three options:
Global variable, available everywhere, but not recommended because all parts of your code may depend on such a varialbe, changes can easily break stuff everywhere.
Class property (Note: you should define a visibility - public/protected/private) these properties are bound to the object instance and should be used for any state that the object needs to keep for further processing. Usually those might be used in more than one metohd of your class.
Variables inside a method like just
public function doStuff()
{
$valueToUseHere = 60;
// Do more stuff here...
}
The variable is just available inside the method and is thrown away at the end of the method execution.
That depends on your needs. If you are going to simply hold a value in a variable it's the best to keep it's simplicity and not define functions for setting or getting it's value. But sometimes you may need to have more controls on a variable in your class. For example you have defined an integer variable and you want it's values to be always between 10 and 1000 and also it should not be in 100,200,300,..,900. So here there is a good reason to set your variable access to private and create a public function to check what is required before setting a new value. Or in another example you may want to call another function or change another depended variable in your class exactly after this variable changed. Or if you want to make a variable read-only or write-only always you can define properties for controlling the variable value.
In brief you may prefer to use:
Properties: When you want to have control about get and set values
Variables: When you want to set or use a variable as its nature
I'm trying to improve my website engine. So I can stop setting global $vars inside functions
So now I'm setting all my global site vars with this instead:
define('ROOT_prefix', 'mysitename_');
define('ROOT_support', 'support#mysite.com');
I can access them anywhere. But it does not feel as good (or smart) practice..
I know very little about classes.. but couldn't/should't I use a class for this instead?
This works:
class ROOT {
public static $prefix = 'mysitename_';
public static $support = 'support#mysite.com';
}
And then anywhere on my site I can use this (even inside functions):
echo '<h1>Please contact support at: '.ROOT::$support.' </h1>';
Is this a good way, or is there a better way?
If the value of these "globals" will not be changed for the entire run-time of the script, then you absolutely should use constants, as this is exactly what they are for.
You should keep them all centralized in a common include file for readability.
(Edit based on comments follows)
Since it looks like you're using constants for some kind of localization of content, it might be prudent to use a class for this. As I have said: using constants for non-changing values in a procedurally oriented script isn't bad practice in itself, but in the context of localization, there are better ways.
One such would be to create a class with some static methods to translate a string based on the passed ini file, this would be in line with the dependency injection mentioned in other comments and answers here.
An example of such a class would look something like this:
class Localizer {
public static function localize($langFile, $string) {
if (!file_exists($langFile)) {
throw new Exception($langFile . 'not found!');
}
$lang = parse_ini_file($langFile);
return (!empty($lang[$string])) ? $lang[$string] : false;
}
}
You can use it like this:
echo Localizer::localize('./english.ini', 'hello') . "\n";
echo Localizer::localize('./english.ini', 'email') . "\n";
This assumes an ini file that looks like this:
; english.ini
hello = 'Hello!'
email = 'test#test.com'
Realistically, this is probably a more "proper" way than declating a boat load of constants for each language your application runs in, but it is going to open the file every time you need to localize a string, which wouldn't be optimal for a very high volume application on a large system. But, as with a constant, you will be able to access the static methods of a class in the scope of any function in your application so long as the class was included beforehand. No need to use constants or declare globals.
The most proper and efficent way to do it would be to instantiate a class instead of using static methods, which would load the files into memory once and keep them there, eliminating the need to open the file for every string translated. But this would require that you are able to pass the variable containing the instantiation of this class to every function in your code that requires it, or declare it as global, which was exactly what you were trying to avoid in the first place.
So in order to do this, you would probably need to re-structure your code to allow for dependency injection throughout.
To continue with your current code and structure, you can continue using generated constants, which will be much messier, less "proper", and not expandable, but the advantage is that you will only read the ini files once, and keep them in memory.
Or you can use a static method, which is more "proper" but needs to read a file every time you localize a string, meaning that on large systems, it could cause some inefficiency. Realistically though, if your application in low volume, you will likely never see problems arise from this.
The main advantages of this method are expandability, and clean code. While declaring constants might be more efficient in terms of file opening and memory usage in the very short term, in most cases, it's not as expandable, because you can have an unlimited number of strings and language files, which means you could end up in a situation in the future where your loading thousands and thousands of constants every time your application loads.
If you use a class, and only load the files/strings that are needed by that specific user at run time, you can avoid this, no matter how many languages and strings you support.
Static class variables aren't any better than constants. They're still globally accessible values. There's no real change.
If you want to be improving your style, you should be using dependency injection. This simply means that you pass all variables that a function or class needs into the function/class as parameters. It's that simple, really. If you want to decouple your code, you need to create borders between different pieces. That means one piece does not "reach out" and get a global variable; instead you define that piece as accepting a parameter and write another piece that passes it that parameter.
Please read How Not To Kill Your Testability Using Statics for an in-depth explanation of this topic.
You may set variable to global when you need it. Just use global ${$variablename};.
where $variablename contain name of needs variable. For example it may be array keys or values.
Declaring your properties as public allows for their modification.
If you want them to be constants, as they were when created with define, you'll have to declare them as protected and use methods to access them :
class ROOT {
protected $prefix = 'mysitename_';
protected $support = 'support#mysite.com';
public static getPrefix(){
return $this->prefix;
}
public static getSupport(){
return $this->getSupport;
}
}
This way is actually quite better than using define() actually.
It's a step forward to singleton patterns (http://en.wikipedia.org/wiki/Singleton_pattern).
Next step is the building of an Application class (ROOT name sounds fine) which would contain these constants, and perhaps load them from a configuration file.
In this Application singleton, you can build some main function, like an init() for a bootstrap, inclusion of other classes, database configuration, logging system, templating system, and so on...
I have custom config items in application/config/config.php.
Samples of my custom config items:
$config['website_title'] = 'ABC Website'; //Assume website title is fixed
.
.
.
etc
Now i can call $this->config->item('website_title') any where in my application. However, i don't find it efficient enough because i might have multiple $this->config->item('website_title') within the project. I came up with the following solution:
1.Create a function, within a helper, that return the config item as the following:
public function website_title() {
return $this->config->item('website_title');
}
2.Now i can call website_title() as many as i want.
Is this a good solution? Do you see any downsides?
Note: I try to avoid using global variables because i tried it and i
faced many unnecessary problems such as undefined variables,
surprised!
What do you mean by "efficient"? Runtime efficiency? Coding efficiency? Clarity?
In terms of runtime efficiency Truth's suggestion of using is perhaps the simplest and best. However, I prefer to code using a strict class/object implementation, and in reality defines are just global constants.
If you profile the vast majority of scripts, you will find that however you code your configuration referencing makes an immaterial impact on runtime, so I would suggest going for simplicity and clarity of coding every time.
One approach is to use a singleton class (there are lots of tutorials on doing this) and use the magic method __get() to allow you to dynamically overload parameter access. This is one case where I feel that you have to use a single class as these property methods only work with object (non-static) parameter references. Hence you can simply use:
$cfg = Configuration::get();
...
... $cfg->someConfigParam ... // to refer to a config parameter
...
... /* or even */ ... Configuration::get()->someOtherParameter ...
Note that $cfg in the above example essentially stores an object handle, so there is no material runtime cost in doing this, and you can put this statement at the top of each function or class constructor that references a config item if you don't want to litter your code with Configuration::get()->someOtherParameter type calls.
The Configuration::__get() access function , plus the class constructor can handle all the complexities of caching and access of the individual parameters. This also means that you con also encapsulate the source of the configuration: some application-specific D/B config table; one or more config files, ...; even cookies or URI parameters (so long as you include appropriate validation).
I personally don't recommend over loading with the __set() magic method as, IMO, overriding or setting a config parameter should be an explicit action, e.g. $cfg->setConfigItem( 'someValue', TRUE );
Here is a link to the documentation on my config class if you want some ideas.
I asked this sort of question on programmers once. I got a very good answer, simply use constants.
I.e. WEBSITE_TITLE
Let's say you have a object that is unique, and it's used by all other classes and functions ...something like $application.
How would you access this object in your functions?
using a global variable in each of you functions:
global $application;
$application->doStuff();
creating a function, like application() that instantiates the object into a static variable and returns it; then use this function everywhere you need to access the object:
application()->doStuff();
create a singleton thing, like a static method inside the object class which returns the only instance, and use this method to access the object:
Application::getInstance()->doStuff();
KingCrunch & skwee: Pass the application object as argument to each function/class where is needed
...
public function __construct(Application $app, ...){
....
If there are other options please post them. I'm wondering which of these options is the most efficient / considered "best practice".
I'd pass it to all the needed methods.
i.e.
function doFoo(Application $app) {
$app->doStuff();
}
Both global and singleton considered bad and ties your code too much and this makes unit testing more difficult.
There is one rule when you are allowed to use singleton, if you answer "yes" to the following statement:
Do I need to introduce global state to my application AND I must have a single instance of given object AND having more than one instance will cause error
If you answer yes to all the 3 parts then you can use singleton. In any other case just pass all the instances to all the method who needs them. If you have too much of them, consider using something like Context
class Context {
public $application;
public $logger;
....
}
========
$context = new Context();
$context->application = new Application();
$context->logger = new Logger(...);
doFoo($context);
========
function doFoo(Context $context) {
$context->application->doStuff();
$context->logger->logThings();
}
(you can use getters/setters if you need to protect the data or manipulate it or if you want to use lazy initiation etc).
Good luck!
Singletons, God Classes, monolithic classes, etc. are all anti patterns, so I would suggest a fourth option: dependency injection. You can create an instance of application in your application via a factory (or perhaps even new if it has no dependencies, but this can end up complicating things later).
Then, any class that needs access to application can get it as a member, helpfully via the constructor. I'm sure that not every class needs access to application. Remember the Law of Demeter.
If you need some generic functionality like converting one static string to another, I suggest using php's global functions (as opposed to, for instance, a faux static class). I believe they were designed for that purpose.
Or just give it to the ones, that are interested in it. All the suggestions you made are like global variables, even if you call it not that in 2 of 3 variants.
Before it comes to that: If you want to say "Thats not possible, because everything needs it", than maybe it does too much, can too much, and/or knows too much.
I just want to tell you that I am newbie to OOP and it is quite hard to me, but here is my code:
class functions
{
function safe_query($string)
{
$string = mysql_escape_string(htmlspecialchars($string));
return $string;
}
}
class info
{
public $text;
function infos($value)
{
echo functions::safe_query($value);
}
}
Is there any way to make this sentence : echo functions::safe_query($value); prettier? I can use extends, than I could write echo $this->safe_query($value);, but is it a best way? Thank you.
edit: and maybe I even can to not use class functions and just make separate file of functions and include that?
Yes, just define your function outside of a class definition.
function safe_query($string){
return mysql_escape_string(htmlspecialchars($string));
}
Then call it like this
safe_query($string);
Using a functional class is perfectly fine, but it may not the best way to design your application.
For instance, you might have a generic 'string' or 'data' class with static methods like this (implementation missing, obviously):
class strfunc{
public static function truncate($string, $chars);
public static function find_prefix($array);
public static function strip_prefix($string);
public static function to_slug($string); #strtolower + preg_replace
etc.
}
The point of a class like this is to provide you with a collection of generic, algorithmic solutions that you will reuse in different parts of your application. Declaring methods like these as static obviates their functional nature, and means they aren't attached to any particular set of data.
On the other hand, some behaviors, like escaping data for a query, are more specific to a particular set of data. It would probably be more appropriate to write something like this, in that case:
class db_wrapper{
public function __construct($params); #connect to db
public function escape($string);
public function query($sql);
public function get_results();
}
In this case, you can see that all of the methods are related to a database object. You might later use this object as part of another object that needs to access the database.
The essence of OOP is to keep both the data and its relevant behavior (methods) in one place, called an object. Having behavior and data in the same place makes it easier to control data by making sure that the behavior attached to the data is the only behavior allowed to change it (this is called encapsulation).
Further, having the data and behavior in one place means that you can easily pass that object (data and behavior) around to different parts of your application, increasing code reuse. This takes the form of composition and inheritance.
If you're interested in a book, The Object-Oriented Thought Process makes for a decent read. Or you can check out the free Building Skills in Object-Oriented Design from SO's S.Lott. (Tip: PHP syntax is more similar to Java than Python.)
Functions outside a class litter the global namespace, and it's an open invitation to slide back to procedural programming. Since you're moving to the OOP mindset, functions::safe_query($value); is definitely prettier (and cleaner) than a function declared outside a class. refrain from using define() too. but having a functions class that's a mix of unrelated methods isn't the best approach either.
Is there any way to make this sentence
: echo functions::safe_query($value);
prettier?
Not really. IMO having a functions class serves no purpose, simply make it a global function (if it's not part of a more logical class, such as Database) so you can do safe_query($value); instead.
and maybe I even can to not use class
functions and just make separate file
of functions and include that?
Create files for logical blocks of code, not for what type of code it is. Don't create a file for "functions", create a file for "database related code".
Starting with OOP can be a real challenge. One of the things I did was looking at how things were done in the Zend Framework. Not only read the manual (http://www.framework.zend.com/manual/en/zend.filter.input.html, but also look at the source code. It will take some effort but it pays of.
Looking at the context of your question and the code example you posted, I would advice you to look at some basic patterns, including a simple form of MVC, and the principles they are based upon.