I have some code that often looks like this:
private $user;
public function __construct()
{
$this->user = User::getInstance(); //singleton
}
public function methodOne()
{
return $this->user->foo();
}
public function methodTwo()
{
return $this->user->foo2();
}
public function methodThree()
{
return $this->user->foo3();
}
I figure if I set user property to the instance I can reuse a shorter name in my methods (well in this case it's not that much shorter). I also thought doing it this way might save a little resources (beginning to doubt it), but when I look at other people's code I rarely see people do this. They would usually just call:
User::getInstance()->foo();
User::getInstance()->foo2();
User::getInstance()->foo3();
Is there any sort of best practice for this? Maybe if it's not a singleton class you might do it this way? Or maybe you should never do it this way? Hope to get some clarification, thanks.
Edit:
Incase there is any misunderstanding I'm just wondering if I should the first example with creating a property to store the instance vs this:
public function methodOne()
{
return User::getInstance()->foo();
}
public function methodTwo()
{
return User::getInstance()->foo2();
}
public function methodThree()
{
return User::getInstance()->foo3();
}
Actually now that I think about it this may be less code as I don't need the constructor...
There are indeed some problems with your approach.
It is not clear that your class depends on the User class. You can solve this with adding User as a constructor parameter.
Singletons are often bad practice. Your code demonstrates why: it is globally accessible and hence difficult to track dependencies using it (this points to the above problem).
Static methods are too often used as global access points (in response to what you see people usually do User::method()). Global access points give the same problem as singletons. They are also a tad more difficult to test.
I also don't see the point in repeating the User object with your new object, unless you would use eg the adapter pattern. Maybe if you could clarify this I would be able to come up with a better alternative than the generic:
class Foo {
public function __construct(User $user) {
$this->user = $user;
}
public function doXsimplified() {
$this->user->doXbutMoreComplex($arg1,$arg2, $arg20);
}
}
My personal preference in PHP is to use classes with just static methods for singletons, so you have
User::foo();
User::bar();
I would not create a new class just to wrap around a singleton like that. But if your new class adds some extra logic then your example makes sense. Remember, if you're worried that you're too verbose you can always use a temporary variable for successive function calls.
$user = User::getInstance();
$user->foo();
$user->bar();
But personally, I don't use Singletons anymore. Instead, I use Dependency Injection. I like the sfServiceContainer, but there are others. Have a look at this series of articles: http://fabien.potencier.org/article/11/what-is-dependency-injection
UPDATE
Based on the additional comments, this is how I would do it:
class UserWrapper
{
private $user = null;
public function __construct($user)
{
$this->user = $user;
}
public function foo()
{
return $this->user->foo();
}
...
}
Then use it like this:
$user = new UserWrapper(User::getInstance());
Why? So I can pass in a fake User object if I want to test the UserWrapper class. E.g:
class UserMock { ... } // A fake object that looks like a User
$userTest = new UserWrapper(new UserMock());
I usually go like this, if you have already included the class in a bootstrap of some sort or a config file. I would usually declear the $user variable in a bootstrap that will get called on every page load, then just reference it as a global variable on other php files, this is what I would have in the bootstrap file.
$user = new User();
Then this is what I would have in the calling php file
global $user;
$user->foo();
Related
I was wondering what is the best way to transfer an instanced object into another class for local usage. I am also curious if this makes a differences with regards to memory usage.
I figured, there are mainly two ways:
1.) Transfer instanced objects via referencing to $GLOBALS:
class UserLogHandler {
public function __construct() {
$this->DB = $GLOBALS['DB'];
$this->Security = $GLOBALS['Security'];
}
public function doSomeWork() {
$this->DB->someMethod;
}
}
or
2.) Transfer via handover:
class UserLogHandler($DB,$Security) {
public function doSomeWork() {
$DB->someMethod;
}
}
It seems to me, that option 2 might be better suited for a complicated environment, although I find option 1 more appealing. Anyhow I would prefer a technical and/or logical explanation why to use one option over the other. If there is another, better option please let me know as well.
Thanks in advance and best wishes,
Thomas
This is indeed a good question. I will say it depends upon your need. Lets analyze both your options one by one.
Before starting, keep in mind that your object should always a complete object. It should not have a incomplete state. You can refer to this article for more understanding https://matthiasnoback.nl/2018/07/objects-should-be-constructed-in-one-go/
1.) Transfer instanced objects via referencing to $GLOBALS:
You must never use such methods as they are confusing. $GLOBALS lacks to tell you where and how a particular variable was created so You can't never be sure if this variable exist or what it holds. I will suggest you to use dependency injection for it
use DB;
use Security;
class UserLogHandler
{
public function __construct(DB $DB, Security $Security)
{
$this->DB = $DB;
$this->Security = $Security;
}
public function doSomeWork()
{
$this->DB->someMethod;
}
}
See how you can now be sure that from where $DB and $Security where injected and what they hold. You can even enforce type of variable using type indication like Security $Security.
This method comes handy when your class is heavy dependent on a particular variable. e.g. A model class will always need DB adapter or a PDF generator library will need PDF class essentially.
2.) Transfer via handover
This works as you expected but I think you made mistake while defining it. You need to write it like following.
class UserLogHandler
{
public function doSomeWork($DB, $Security)
{
$DB->someMethod;
}
}
This method comes handy when you need a particular variable in a particular function only. Example for it, will be like we need to get records from a model for some particular condition. So we can pass value in function and get results according to value.
use DB;
use Security;
class UserLogHandler
{
public function __construct(DB $DB, $Security)
{
$this->DB = $DB;
$this->Security = $Security;
}
public function doSomeWork($value)
{
if ($value = 'something') {
$this->DB->someMethod;
}
}
}
As you can see that both methods can be used in conjugation. It only depends what is your requirement
Learning PHP in a OOP way and i often come across people who makes functions like this.
public function getUsername() {
return $this->username;
}
Is there some security reasoning behind this? Instead of just calling the username property of the class directly? Why wrap getting a property around a function.
This type of functions are used for accessing private or protected members of class. You can not access them them directly outside of the class as they can be accessible only inside the class. So what would you do if you want to access a private member? The answer is this.
Lets take an example -
class A {
private $x;
public $y;
public function test() {
echo $this->x;
}
}
$obj = new A();
$obj->x; // Error : You can not access private data outside the class
$obj->y; // Its fine
$obj->test(); // it will print the value of $x
Hope this will help.
In OOP, class should hide its implementation details, and just provide necessary public functions. Users are more concerned with function rather than details.
For example you have class Test. You are using direct access to property and you have hundred place like $obj->date = 'now' etc.
class Test {
public $date;
}
But what if you need to insert some code before updating value or modificate input value? In this case you have to find all usage of the property and update it. But if you will use getters/setters you can insert some code into them.
class Test {
private $date;
public getDate() { return $this->date; }
public setDate($date) {
// here some modification value or something else
$this->date = $date;
}
}
A quick reason is that you be writing a piece of code and want to prevent a user from overwriting a value in an object instance (a good example is configuration data).
Writing functions in the way you have stated also provides a standard interface which is essential when developing complex programs. It would be crazy to have a team of developers working with the one class and not defining access to variables!
Here is a good explanation of the PHP OOP basics and explains private, public and protected
http://php.net/manual/en/language.oop5.basic.php
Through my multiple studies I have come across the factory method of setting session and database objects which I have been using while in development. What I am wondering is, putting aside personal preference (although I will soak in any opinions anyone has), does this general method work, and is it efficient (meaning, am I using it correctly)? If it is not, do you have suggestions for how to improve it?
Background
I created the code this way so as to pass a database and session object to the class upon calling the class. I wanted to be able to pass along the relevant objects/references so that they could be used.
The Call Class
This class is meant to call static functions, like so:
class CALL {
public static $_db, $_session;
public status function class1() {
$function = new class1();
$function->set_session(self::$_session);
$function->set_database(self::$_db);
return $function;
}
public status function class2() {
...
}
...
}
The _set class
class _set {
public $_db, $_session;
public function __construct() { ... }
public function set_database($_db) {
$this->_db = $_db;
}
public function set_session($_session) {
$this->_session = $_session;
}
}
Now the classes referenced.
class class1 extends _set {
function __construct() { ... }
function function1() { return "foo"; }
...
}
So, moving forward, the classes would be called using CALL::class1 or CALL::class2. After that, they can be accessed as per usual, aka:
CALL::$_db = $database->_dbObject;
CALL::$_session = $_SESSION;
$class1 = CALL::class1;
echo $class1->function1(); //prints "foo".
Read about Dependency Injection . Small suggestion from my point of view, you should never create objects like $db or $session inside other objects. You should rather inject them through constructor or setter method. It will make your code less dependant on a specific classes and it will be easier to replace all dependencies almost without refactoring (actually without one if you know hot to use interfaces).
If anyone stumbles on this, I will share with you what my solution was.
Although this exercise helped me to learn a lot, and I am sure I could take the time to create a VERY highly functional factory/Container, because this is not integral to my program and not even unique, I finally bowed to the age old wisdom of not repeating something that has already been done.
I utilized Pimple, a lightweight library that uses PHP closures to create function calls. Now, I can haave the flexibility of determining which dependency injections I want, but I also only need to inject them once. Future calls, even when they create new instances, will replicate them. While I think that, in theory, my project was workable as it was, it did indeed have the unfortunate issue of requiring you to go into the container to make changes. With Pimple I do not need to do that. So I've tossed by Container class and picked up a lightweight program from the maker of Symfony. While this may not be the best answer for everyone, it was for me. Cheers!
I want to set initial values of fields in an object, using $config. Which approach is better in terms of cleaner and more maintainable code?
Also, I would like to add that object will be initialized in a factory and not directly by client.
1. I pass $config to the object
<?php
class UserGreeting {
private $config;
public function __construct($config){
$this->config=$config;
}
public function greetings(){
echo 'Hello, '.$this->config->get('username');
}
}
?>
Pros:
Easy to pass multiple parameters
Cons:
The class is coupled with $config ( is it?). What I mean is that
apart from particular $config interface and parameters naming
conventions, I can't just plug this class into another program
without introducing $config
Client code doesn't have to know which parameters are used by the
object, but that is more general thought
2. I set fields manually outside the object
<?php
class UserGreetingFactory{
public function __construct($config){
$this->config=$config;
}
public function getUserGreeting(){
$userGreeting=new UserGreeting();
$userGreeting->setUserName='John Doe';
return $userGreeing;
}
}
class UserGreeting {
private userName;
public function setUserName($userName){
$this->userName=$userName;
}
public function greetings(){
echo "Hello, {$this->userName}";
}
}
?>
Pros:
The class doesn't care where his parameters are coming from
Can reuse easily
Easier to test(is it?). I mean that I don't have to deal with setting
up $config
Cons:
Factory\Builder has to know which parameers to pass
Lots of extra code for setters and passing parameters
First solution with ctor injection. But instead of a special config i would just pass the actual objects. In your case an User object.
<?php
class UserGreeting
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function greet()
{
printf('Hello, %s!', $this->user->getName());
}
}
Considering your idea's, I'd stick to a single variable. If you want to pass the variables per-method you'll have a lot of excessive code.
From an OOP point of view, you shouldn't put it in a single variable. An object has properties. An username is in fact a property so you should use it as property. That means that in PHP classes you'd need to make it a public variable and set the variables when you create the object.
The first way is better because of dependency injection. This code will be easier to test and to maintain.
The third way is to use Visitor pattern to inject dependencies.
You could use a static class with static methods. In effect they are like CONSTS, but you can enforce all kinds of rules within the static config class - that they conform to an interface for example.
Config::getUserName();
That way if you are going to be faced with a family of config objects, you can be assured they all have at least an entry for each expected value - otherwise a warning is chucked.
Might depend on your situation of course, and I expect there are many situations where you would not want to do this - but I will offer it up all the same.
I have this User class
class User{
private $logged = false;
private $id;
public function User() {
//> Check if the user is logged in with a cookie-database and set $logged=true;
}
public function isLogged() {}
public function editPerms() {}
//> other methods
}
Well now considering I can't have more than 1 user logged (of course because we are talking for a single http request) in Where should i store the ref of my istance?
This is the case where singleton would be useful but these days everyone say singleton is evil (like static methods).
http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/
I could do a $GLOBALS['currentUser'] = new User(); and having it accesible everywhere but I think this is worse than a singleton.
So what Can I do?
Please note I don't need to save this instance between requests. I just need a way to access this instance in my framework within the same request.
If you want to know what i do now for all of my Helper Objects is a Service Container (that's considered as well bad):
function app($class) { //> Sample
static $refs = array();
if (!isset($refs[$class]))
$refs[$class] = new $class();
return $refs[$class];
}
//> usage app('User')->methods();
(IE what symfony does)
Patterns are supposed to be a helpful guide, like a library of previously successful software abstractions. Too often these days people view patterns as being some kind of religion where things are either "right" or "wrong" regardless of the context of the program.
Think about what you want to achieve and map in out in a way that makes sense to you. Fuggering about with minute distinctions between this pattern and that pattern misses the point, and it won't get your program written. Learn by doing!
HTH.
Singletons are not evil. Bad usages of singletons are evil. The reason people have come to dislike this pattern so much (even going to the extent of calling it an anti-pattern, whatever that is), is due to improper use:
Too many inexperienced people make a class a singleton when they find they don't need more than one instance of a class. But the question isn't if you need only a single instance of the class, but whether more than one instance would break your code. So ask yourself this question: would your code break if there were more User instances? If not, then maybe you shouldn't bother. :)
There are legitimate uses of singletons. There are those people who fear this pattern like the plague and consider it always to be bad, without realizing that sometimes it can be very helpful. In the words of a much more experinced programmer than me, "singletons are like morphine: they can give you a real boost, but use them the wrong way and they an become a problem themselves". If you want me to go into some details as to when singletons could be a good choice, leave a comment to this answer. :)
It is always hard to answer architectural questions without the context. In this case it is pretty important how the User objects are persisted (where do they come from?) and how is the client code organized. I will assume a MVC architecture because it's trendy this days. Also I suppose your user objects will have more responsibility as only authentication (you mention some permission control here, but it's still not clear enough).
I would push the authentication responsibility to a service and just pass it around as needed. Here is some sample code.
class AuthenticationService {
/**
* #var User
*/
private $currentUser;
public function __construct(Request $request) {
// check if the request has an user identity
// create a user object or do nothing otherwise
}
public function getCurrentUser() {
return $this->currentUser;
}
}
class User {
public function editPerms(){}
}
// the client code
class Controller {
private $auth;
public function __construct(AuthenticationService $auth) {
$this->auth = $auth;
}
public function handleRequest() {
$currentUser = $this->auth->getCurrentUser();
if ($currentUser === null) { // of course you could use Null Object Pattern
// no user is logged in
}
// do something with the user object
}
}
So the answer to your question is: you need proper dependency injection through out your whole application. The only object you get from the server is a request. The dependency injection container injects it into the AuthenticationService and the latter gets injected into your controller. No singletons, no static methods, no global variables. The dependencies are tracked in the DI container and are injected as needed. Also the DI container makes sure your service is instantiated only once.
The article "Container-Managed Application Design, Prelude: Where does the Container Belong?" may clarify some DI concepts.
Not sure why all the arguing up top. Seems like a perfectly reasonable question to me.
The key here is to use static members of the User class. Static methods are your friends, regardless of what some may say:
class User
{
private $logged = false;
private $id;
private static $_currentUser;
public static function currentUser()
{
if (empty(self::$_currentUser))
{
#session_start();
if (array_key_exists('current_user', $_SESSION))
{
self::$_currentUser = $_SESSION['current_user'];
}
else
{
// force login in or whatever else.
// if you log in, make sure to call User::_setCurrentUser();
return null; //or some special 'empty' user.
}
}
return self::$_currentUser;
}
// you may consider making this public, but it is private because it is a bit
// more secure that way.
private static function _setCurrentUser(User $user)
{
self::$_currentUser = $user;
$_SESSION['current_user'] = $user;
}
public function User() {
//> Check if the user is logged in with a cookie-database and set $logged=true;
}
public function isLogged() {}
public function editPerms() {}
//> other methods
}
// Usage
$pUser = User::currentUser();
The influence of Misko Hevery is pretty strong on me. So is his newable - injectable distinction. A user is not an injectable but a newable. What are the responsibilities of a user: should he be able to tell of himself whether he is logged in or not? There's a post of him where he talks about a similar problem: a credit card and charging it(self?). It happens to be a post about singletons, what you would like to make it:
http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
That would leave it to an service to check whether the user is logged in or not, what rights he has on the site.
It also means your architecture would change, your problem will become different (passing around the user?, where is it needed?, how will you have access to the 'checking user is logged in' service, ...).
since everyone else is weighing in on this, singletons are not evil.
i even read the "liars" article, and he's using a contrived example of non-modular design and poor dependency inheritance.
i think you should consider a singleton factory pattern, where a singleton factory (Auth) provides a login() method which returns a User class, as well as methods for saving state between HTTP requests on that User.
This will have the benefits of separating the security and session functionality from the User functionality. Additionally using the factory, you can have multiple types of users without the rest of the system needing to understand which object to request before the db is examined
class auth {
private static $auth = null;
private $user = null;
// must use getAuth();
private __construct(){};
public getAuth() {
if (is_null($this->auth) {
$this->auth = new auth();
}
return $this->auth;
}
public function login($user,$pass) {
... // check db for user,
if ($dbrow->user_type == 'admin') {
$this->user = new admin_user($dbrow);
} else {
$this->user = new normal_user($dbrow);
}
$this->user->setSession($db->getsession());
}
public function getUser() {
return $this->user;
}
public function saveSession() {
// store $this->user session in db
}
public function saveUser() {
// store $this->user changes in db
}
...
}
the user class itself become a data structure, simply enforcing security and business rules, and maybe formatting some data for output purposes.
class normal_user extends user {
... getters and setters
public function getName() {}
public function setEmail() {}
public function setprofile() {}
}
all db, state and security concerns are centralized in the auth.
the only way to create a user object (legally) is to run auth->login().
you are still allowed to do
$me = new normal_user();
$me->setName();
echo $me->getName();
but there is no way for a new coder to save this in the db since it's not referenced in $auth->user;
you can then create a function in auth to consume user objects to create new users (on signup)
...
public function create(user $user) {
// validate $user
$this->user = $user;
$this->saveUser();
}
...
you just need to make sure you run the save functions at the end of execution...
possibly in a destructor()
simple