This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best practices to test protected methods with PHPUnit
class Footer
{
private $_isEnabled;
public function __construct(){
$this->_isEnabled = true;
}
public function disable(){
$this->_isEnabled = false;
}
}
When I am writing a unit test for the disable function after I set _isEanabled to false, I want to assert whether or not it is false.
But how can I access $_isEnabled?
This is my test function:
public function testDisable(){
$footer = new Footer();
$footer->disable();
$this->assertFalse($footer->_isEnable);
}
Short answer:
You cannot. That's what PRIVATE means...
Long answer:
You can do it using reflection:
http://php.net/manual/en/book.reflection.php
It is a bit complicated, though, and adds another layer prone to fail so it is not the best way for testing...
I rather prefer to create a getter function:
public function getEnabled() {
return $this->_isEnabled;
}
But if you have not done it as simple, I think you do not want to create it... but given the alternatives, you may reconsider it.
An accessible property has to be public, I think that is self explanatory. However, you might encounter code where protected and private properties seem accessible in a way similar to accessing public variables.
This is done using the magic getter method:
class Footer
{
private $_isEnabled;
public function __get($propName)
{
if (!isset($this->{$propName}))
{
throw new Exception($propName.' is not set');
}
return $this->{$propName};
}
}
This magic method is invoked each time you try to access a property that either, doesn't exist or isn't public. In short:
$instance->_isEnabled;//will work.
You can alter this method as you like, so that, for example, the underscore isn't required anymore... there's tons of things you can do with this.Refer to the man pages
I doubt getting points by this: the class is not "algebraically" complete. A public function isEnabled() is missing. If the unit test has no info about the state, then other class clients will also miss this info.
A unit test on something private does not help saying anything on the public API, but checks internal operation which should be obvious.
In general it is bad business having unit tests relying on the implementation; then reimplementation makes maintaining unit tests too.
Related
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!
In PHP there does not seem to be a big disparity between private and protected methods.
I asked why I should use protected in PHP Chatroom and got this answer:
unless you have good reason not to : yes
and good reason is , if you code is closed-source library
and even then , it can be overridden with reflections
So --
If the private method could potentially be overridden with Reflections, what is the point at all in private methods?
private and protected are there to make it easier to write code that does the right thing. As you've noticed, they're not unbreakable -- there's nothing preventing you from bypassing them if you want to. That's because they're meant to protect you from accidentally doing the wrong thing, not from actively trying to.
That you can bypass them with reflection, doesn't mean you should. You can consider private and protected as kinda a "warranty void if broken" sticker; if you ignore them and muck around with stuff yourself directly, the object/class might not behave properly. It has no obligation to at that point, since you've taken it upon yourself to mess with its innards -- and the code that does so is entirely to blame.
Now, as for the question in the title...you use protected to declare the interface specifically for subclasses; you basically declare that you intend for them to use that stuff directly, while private says that you don't. Whether they disregard that is up to them, but if they do, then screw 'em. You tried to warn them.
Yes it can be overridden using reflection but that's not the point, the point is to restrict access to the method under normal use, i.e. if someone is using your class they shouldn't be able to access that method because it violates the contract that class has.
It's private/protected depending on the use of it, so if someone has made a method private then they've done it because you shouldn't need to access it from another class, if they've made it protected then likely they only intended sub classes to be able to access the method.
class GrandPa
{
private $name = 'Mark Henry';
function getName(){
return $this->name;
}
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->getName(); // work
echo $daddy->displayGrandPaName(); // Error Undefined property:
Try change private $name = 'Mark Henry'; to protected
Recently I have been told that static class/methods are evil.
Take for example my class Logger:
class Logger{
private static $logs = array();
public static function add($msg){
self::$logs[]=$msg;
}
public static function echo(){
print_r(self::$logs);
}
}
I can use whenever i want in my appliaction like this:
Logger::add('My log 1');
But reading this developers:
http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/
That Logger class doesn't seem so good.
So: Can I use it statically or I should avoid it at any cost?
Logging classes are the exception.
Since they rarely contain much logic, you don't have the same testing concerns.
Logging is a perfect example of a GOOD place to use static classes.
Think of your alternatives:
A global instance of a logging object?
A singleton logging object?
Pass the logging object around to every single method/class (via in a constructor)?
The above are much worse than using static for logging.
Avoid it. I've seen quite some posts of you now struggling with the issue and people giving you bad advice. I'll repeat what I said in some of my answers/comments.
The way you use static in your logger class is to use it as a globally access point. Whenever you need to logg something you call Logger::log().
1) You will not be able to tell from looking at your class definition that it depends on the Logger class. Change in code thus becomes an adventure: 'I hope I will not break some hidden dependency when I change this tiny little ... OOPS!'.
2) It IS harder to test. You can't realiably test a class that sends a message to the Logger with Logger::log(). When a test fails how will you know it is not because the Logger fails? You would know if you could replace it with a mock, but in your case it is not mockable.
An alternative to explore:
Use the observer pattern and make the Logger an observer, the classes that need logging can be observables. They send messages like $this->observers->nofify('test succeeded').
You could use some other form of events too or dependency injection (automatic or manual). But please please don't call Logger::log() in a method.
I still think that logging is a valid approach to use a static classes. The often stated phrase that it is not testable is imho also not true if you do it right. I want to implement this but did not find the time, however, I thought about something like the following.
class Logger {
protected static $handlerSet = [];
// Pure static class {{{
private function __construct() {}
private function __clone() {}
private function __sleep() {}
private function __wakeup() {}
// }}}
public static function critical($message, array $context = []) {}
// You know the PSR drill...
private static function log($level, $message, array $context) {
foreach ($this->handlerSet as $handler) {
$handler->handle($level, $message, $context);
}
}
}
Of course we do not want to expose the management of the handlers to all classes, hence, we use a child class that has access to the protected handler set.
final class LoggingManager extends Logger {
public static function addHandler(Handler $handler, $name, $level) {
static::$handlerSet[$name] = $handler;
}
public static function removeHandler($name) {
if (isset(static::$handlerSet[$name])) {
unset(static::$handlerSet[$name]);
}
}
public static function resetHandlers() {
static::$handlerSet = [];
}
// Other useful stuff...
}
Testing is now fairly easy, if you actually want to test something like logging (could be that it has some ROI for you, don’t know).
class SomeTest extends YourFrameworksTestCase {
public function testThatSomethingLogsSomething() {
try {
$handler = new TestLogHandler();
LoggingManager::registerHandler($handler, 'test', 'debug');
// Test something.
$this->assertLogRecordExists($handler, '[debug] StackOverflow');
}
finally {
LoggingManager::resetHandlers();
}
}
}
It would also be possible to create a more sophisticated test case to extend that implements all of the log record assertion for you. This approach is imho fairly easy and a class in your system should not care whether a handler is registered or not, nor what it does with the logged messages. Things like that are handled in your application and only there. The advantages are obvious:
Global access to the logger and logging manager.
Easy testing, comparable to dependency injection.
No need for code polluting DIC solutions.
Single logger instance, always.
…
While there is nothing wrong with that approach, I recently moved from a static logging class approach to log4php in one of my own projects myself.
log4php uses a separate instance of a logging class for each class in your project. When looking at that logging framework, the benefits become obvious.
Logged messages always have a context (the class through which the message was logged). That allows for easy filtering (and make the log slightly more helpful).
The only problem with static classes is that they are hard to change.
So it's ok here since you're class doesn't do much.
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();