PHP static methods vs non-static methods/standard functions - php

I am working on a web app and writing pure OOP based PHP for the first time. And I have a question about static method VS standard function:
Here is an example scenario:
class Session
{
public function start_new_session()
{
session_start();
//other code here like token generator
}
}
VS
class Session
{
static function start_new_session()
{
session_start();
//other code here like token generator
}
}
Questions
What is the difference in both?
Which is better for my case?
Any application? (I mean, what are the best scenario to use static method and standard function)
My Research:
I spent some time to find the answer but don't found relevant answer however I found a lot of debate and useful material. Believe me it is super hard to decide (Who is right/wrong?) for a beginner like me:
In this question Someone said, It's horrible idea to use cookies in static functions and someone's saying It's a great idea
And in this question: Everyone is debating on performance and some experts are saying, the static functions execute faster and some saying; functions are faster. And result also vary because of different versions of php.
Some useful stat:
PHP 5.2 : static methods are ~10-15% faster.
PHP 5.3 : non-static methods are ~15% faster
PHP 5.4 : static methods are ~10-15% faster
PHP 5.5 : static methods are ~20% faster

To call a non-static method you need to instantiate the class (use the new keyword to create a new instance of the class).
When calling a static method you don't have to "new it up" but it won't have direct access to any of the non-static properties or methods. There are dozens of use-cases / scenarios where you might want to use one over the other.
To be quite honest it has never even crossed my mind to think about performance of using one over the other. If it got to a point where it made that much of a noticeable difference (and all major steps had been taken to increase efficiency) then I would imagine that either the maintenance costs of such a big application would outweigh the need for the increased efficiency or the logic behind the app is fairly flawed to begin with.
Examples for static and non-static
If I was going to use a class for the example in your question then I would use the static version as nothing in the method is reliant on other properties of the class and you then don't have to instantiate it:
Session::start_new_session()
vs
$session = new Session();
$session->start_new_session();
Also, static properties on a class will remember state that would have otherwise been lost if you were to use a non-static property and instantiation:
class Session
{
protected static $sessionStarted = false;
static function start_new_session()
{
if (!static::$sessionStarted) {
session_start();
static::$sessionStarted = true;
}
}
}
Then even if you did:
$session = new Session();
$hasStated = $session::sessionStarted;
$hasStarted would still be true.
You could even do something like:
class Session
{
protected static $sessionStarted = false;
public function __construct()
{
$this->startIfNotStarted();
}
function startIfNotStarted()
{
if (!static::$sessionStarted) {
session_start();
static::$sessionStarted = true;
}
}
}
This way you don't need to worry about starting the session yourself as it will be started when you instantiate the class and it will only happen once.
This approach wouldn't be suitable if you had something like a Person class though as the data would be different each time and you wouldn't want to use the same data in difference instantiations.
class Person
{
protected $firstname;
protected $lastname;
public function __construct($firstname, $lastname)
{
$this->firstname = $firstname;
$this->lastname = $lastname;
}
public function getFullname()
{
return "{$this->firstname} {$this->lastname}";
}
}
$person1 = new Person('John', 'Smith');
$person2 = new Person('Jane', 'Foster');
$person1->fullname(); // John Smith
$person2->fullname(); // Jane Foster
If you were to use static methods / properties for this class then you could only ever have one person
class Person
{
protected static $firstname;
protected static $lastname;
static function setName($firstname, $lastname)
{
static::$firstname = $firstname;
static::$lastname = $lastname;
}
static function getFullname()
{
return static::$firstname . ' ' . static::$lastname;
}
}
Person::setName('John', 'Smith');
Person::setName('Jane', 'Foster');
Person::getFullname(); //Jane Foster
The debates
You are probably going to see a lot of debates over which is better and what the best practices are when it comes to PHP (not just about static and not-static methods).
I wouldn't get bogged down with it though! If you find that one side makes more sense to you (and whatever you're building at the time) then go with that one. Standards and opinions change all the time in this community and half of the stuff that was a problem 5 years ago (or even less) will actually be non-issues today.
Take the Laravel framework as an example -- one of the (many) debates is that Facades are bad because they're static and make use of magic methods which is hard to test and debug. Facades are actually very easy to test and with the use of stack trace error reporting it isn't hard to debug at all. That's not to say their aren't caveats when it comes to testing static methods, but this is more to do with mocking/spying -- this answer goes into it in a little more detail.
That being said, if you find the majority of people are saying the same thing and there isn't really a debate for the other side, there is probably a reason e.g. don't use mysql_ functions or don't run queries inside a loops.

Related

Passing Session and Database objects to classes in 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!

OOP - using private properties and public getter

Just a simple question. I've seen many cases where the code is implemented like the following:
class User
{
private $id;
private $firstname;
private $lastname;
public function __construct() { some code }
public function getId() { return $this->id; }
public function getFirstname() { return $this->firstname; }
public function setFirstname($value) { $this->firstname = $value; }
}
// And properties are accessed like:
$user->getFirstname();
$user->getId();
So what is the reason of using private properties and having public getters, instead of making the properties public and accessing them directly like:
$user->firstname;
PS: Is it OK if I use the second method?
EDIT
Seems like I did not research well before asking this question (guess I used wrong keys to search on the topic). Here is another good answer to (almost) the same question: https://stackoverflow.com/a/1568230/1075534
Basically, for my case, one good reason to use getters and setters is to avoid changing 250 classes that directly access the property. So for example, imagine that I was not using a getter:
class User
{
public $firstname = 'abc';
public $lastname = 'cde';
}
$user = new User();
echo $user->firstname . ' ' . $user->lastname;
Now, imagine that I want to change the behavior of my app and I decide to print names as capitalized. In this case then I would search each implementation (250 in this case :) and capitalize the output wherever I called the properties. But, rather If I used a getter then I would just change the getter method:
class User
{
private $firstname = 'abc';
private $lastname = 'def';
public getFirstname()
{
return ucfirst(strtolower($this->firstname));
}
public getLastname()
{
return ucfirst(strtolower($this->lastname));
}
}
Also, bear in mind that a getter might not only gather information from a single property. Imagine the following:
class User
{
private $firstname = 'abc';
private $lastname = 'def';
public function getName()
{
return $this->firstname . ' ' . $this->lastname;
}
}
For those who still have questions on this matter, I suggest them reading the material that Gordon provided and especially the answer that I've linked.
Using Accessors satisfies the Uniform Access Principle.
Quoting Wikipedia:
The Uniform Access Principle was put forth by Bertrand Meyer. It states "All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation." This principle applies generally to object-oriented programming languages. In simpler form, it states that there should be no difference between working with an attribute, precomputed property, or method/query.
In his blog, Fowler explains
It effectively means that a client of the person should neither know nor care whether the age is stored or computed. This gives the person object the flexibility to change between the two easily as well as removing what is usually an unnecessary concern from the client. It's an important part of encapsulation - or at least the data-hiding aspect of encapsulation.
To illustrate the point, imagine a class like this:
class Now
{
public $timestamp;
public function getTomorrow()
{
return strtotime('+1 day', $this->timestamp);
}
// … more code
When you do it this way, you are forcing the developer using that class to know the implementation details. To get the now's timestamp, the developer has to do
echo $now->timestamp;
whereas to get the computed timestamp for tomorrow, the developer has to do
echo $now->getTomorrow();
But the developer shouldn't need to care, so if you want to follow the UAP, you will provide an Accessor to get the timestamp. And funnel all access through methods.
Doing so also has the additional benefit of a more stable API. Imagine you need to change the implementation detail later in the project and turn timestamp into a DateTime object. Your class now looks like this:
class Now
{
public $dateTime; // <-- no longer just a timestamp
public function getTomorrow()
{
return strtotime('+1 day', $this->dateTime->getTimestamp());
}
// … more code
Now any developer that previously used $now->timestamp will have to change their consuming code to accomodate for that change. Whereas when you had used a Getter right from the start, it wouldn't be a problem at all, because the Getter would have made sure that it returned the timestamp. To further prove that point, note how the developer would not have to change anything to consume getTomorrow(). Although internally we changed the details, the public API still behaves the same.
Note that UAP is just a guideline. Modern IDEs make it dirt easy to generate Accessors and Mutators for you, so it's easy to follow. But it's not an absolute truth. If you can reasonably justify not following it, then don't follow it and use public properties. But it should be an informed decision.
However, in general, you want to avoid Getters (and Setters) anyway and just tell your objects what to do. This will give a much slimmer API. If your API has lots and lots of Getters, chances are you are scattering code that really should be inside the object into the consumers.
When a variable is declared public, it is accessible from any class making it easier for you as a programmer to use; thus explaining your desire to use the second method you described. However, some variables need to be declared private for security reasons (also it is sometimes seen as a good practice). The fact that we declare them privatemake them only accessible in their own class. If You however need to use them in a function in another class then you need to follow the first method you described
.
using a getter makes it read-only.
(that's the only conceptual difference. a language could easily allow interfaces to be defined in terms of properties as well as methods. naming conventions are not really fundamental.)

How do I access private attributes in PHP? [duplicate]

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.

How to create a "genuinely extensible" class

I have read a lot of articles on developing classes (I am using php), with the tag lines :
'scalable, robust, maintainable and extensible'.
But as a beginner, I have been creating classes that are, in my words, "just abstracted". Meaning I just separated a bunch or repetitive codes and put them in a class and provide methods for accessing common tasks.
The thing is, I can't find a way to make my class extensible (I know the concept of abstract classes and such, I am even using them, but just to define methods that my other classes will follow). The thing is, I always find myself editing the core class just to add functionlities.
Any tips on making my class extensible? (I have googled on this and everything that pops out are explanations of abstract classes, interfaces and OOP, no discussions on pointers or some tips for making extensible classses).
Oh, btw, go easy on me, I have started "actual" oop programming 9 mos ago (the university I'm from had me going on theories on OOP, but they had us working PROCEDURALLY, because it's faster and it meets damn project deadlines, and that went on for 4 years until I graduated).
You should check out the book Design Patterns: Elements of Reusable Object-Oriented Software
The problem with making extensible classes, as you've discovered, is decomposing the system into useful and reusable objects.
The task is difficult because many factors come into play: encapsulation, granularity, dependency, flexibility, performance, evolution, reusability, and on and on.
Are you trying to model some real world scenario, or are you focusing on communication / collaboration and dependencies inside your application?
Here's an example that I think kinda demonstrates what you are looking for. There are certainly a far more, far better examples:
I wanted to develop a caching system that offered my developers a simple, normalized API no matter what / where they were caching something. What do I want in a caching system (at the basic level)?
I want to be able to cache something (set)
I want to be able to retrieve that something (get)
I want to be able to invalidate the cache (delete)
I came up with this:
abstract class MyNs_Cache
{
abstract public function Set($key, $data, $ttl);
abstract public function Get($key);
abstract public function Delete($key, $ttl);
}
There's my extensible base class. I've then got three caching classes MyNs_Cache_Fs, MyNs_Cache_Apc and MyNs_Cache_Memcache
class MyNs_Cache_Fs
{
...
public function Set($key, $data, $ttl)
{
// here I use fopen/fwrite/etc. to create the cached data
}
public function Get($key)
{
// here I retrieve the file from the filesystem (if it exists)
}
public function Delete($key) { ... }
}
That's fairly straight forward. It implements the cache in terms of a FileSystem. It doesn't offer anything past my original class.
class MyNs_Cache_Apc
{
...
public function Set($key, $data, $ttl)
{
return apc_add($key, $data, $ttl); // NOT A FILESYSTEM CALL
}
public function Get($key) { ... } // you get the idea.
// This is specific to APC, so I add the functionality HERE
// NOT in my main Caching class.
public function PurgeCache()
{
return apc_clear_cache();
}
}
My APC cache does everything I want in a caching system (set/get/delete) but it also offers the ability to clear the entire cache (something that's not useful for my FileSystem cache and impossible with memcached)
class MyNs_Cache_Memcache
{
// Memcached needs a pool of servers. APC and filesystem don't.
private $servers = array(..);
// It also uses a memcached object.
private $conn;
public function __construct()
{
$this->conn = new Memcached;
foreach ($this->$servers as $server)
$this->AddServer($server);
}
... // we do all the standard stuff using memcached methods
// We also want to be able to manage our connection pool
public function AddServer($server)
{
$this->conn->addServer(...);
}
// And in some cases, we use inc/dec from memcached
// APC doesn't have this, and it makes little sense in a filesystem
public function Increment($key) { ... }
}
Now I know that I can always get one of my cache objects and just in with $obj->Get('some_key') and I'll always get a result.
Likewise, I also have access to functionality specific to what I'm currently trying to work with.
You don't need to edit your core class to add functionality you can overwrite a method in a child class, eg:
class A {
public function filter_string($str){
return str_replace ('foo', 'bar', $str);
}
}
class B extends A {
public function filter_string($str){
return str_replace ('machin', 'chose', parent::filter_string ($str));
}
}
$a = new A;
echo $a->filter_string('foo machin'); // echoes 'bar machin'
$b = new B;
echo $b->filter_string('foo machin'); // echoes 'bar chose'

Is it possible to overuse late static binding in PHP?

Starting with version 5.3, PHP supports late binding for static methods. While it's an undoubtedly useful feature, there are only several cases where its use is really necessary (e.g. the Active Record pattern).
Consider these examples:
1. Convenience constructors (::create())
class SimpleObject
{
public function __construct() { /* ... */ }
public static function create()
{
return new static; // or: return new self;
}
}
If this class may be extended (however, it's not extended by any class in the same package), should late static binding be used just to make extending it easier (without having to rewrite the ::create() method, and, more importantly, without having to remember to do that)?
Note: this idiom is used to work around the impossibility to call methods on just constructed objects: new SimpleObject()->doStuff() is invalid in PHP.
2. Class constants
class TagMatcher
{
const TAG_PATTERN = '/\<([a-z\-]+?)\>/i';
private $subject;
public function construct($subject) { $this->subject = $subject; }
public function getAllTags()
{
$pattern = static::TAG_PATTERN;
preg_match_all($pattern, $this->subject);
return $pattern[1];
}
}
The reason to use static:: in this example is similar to the previous one. It's used just because this class can be made to match differently formed tags just by extending it and overriding the constant.
So, to wrap it all up, are these uses (and similar ones) of late static binding are an overkill? Is there any noticeable performance hit? Also, does frequent use of late binding reduce the overall performance boost given by opcode caches?
So, to wrap it all up, are these uses (and similar ones) of late static binding are an overkill? Is there any noticeable performance hit? Also, does frequent use of late binding reduce the overall performance boost given by opcode caches?
The introduction of late static binding fixes a flaw in PHP's object model. It's not about performance, it's about semantics.
For example, I like to use static methods whenever the implementation of the method doesn't use $this. Just because a method is static doesn't mean to say that you don't want to override it sometimes. Prior to PHP 5.3, the behavior was that no error was flagged if you overrode a static method, but PHP would just go ahead and silently use the parent's version. For example, the code below prints 'A' before PHP 5.3. That's highly unexpected behavior.
Late static binding fixes it, and now the same code prints 'B'.
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
static methods (early- or late-bound) create tight coupling and (thus) reduce testability. you can create large programs in PHP without using more than a few static calls. for me, late static methods are a non-feature.
edit to answer Marco Demaio's question, how do static method reduce testability?
i'm sorry if this is all obvious to you, static members (both data and methods) are useful and do no harm if used responsibly, i was alluding to their prevalent misuse.
say you have a web application that uses an SQL database. your business objects may retrieve data using a static interface or through polymorphism. either
class MyBusinessObject
extends...
{
public function doThisOrThat(...)
{
$results = db::query('sql string...');
...
}
}
or
class MyBusinessObject
extends...
{
public function __construct(dbconn $db)
{
$this->db = $db;
}
private $db;
public function doThisOrThat(...)
{
$results = $this->db->query('sql string...');
...
}
}
the latter is easier to test (as in: i want to test that the sql string constructed from such-and-such inputs is such-and-such) because it's easier to create another implementation of the dbconn interface than it is to change the meaning of db::. why you'd want either? because you don't need a real database to test the sql-composing behavior, and in fact it's easier to test for without a real database. also, it's easier to stub out the sql consumer if your tests are concerned with another aspect of the CUT (Code Under Test).
testing always implies lying to the tested code about its collaborators, and abstaining from static interfaces (the "doublecolon" or "quadridot") means the lie need not be a massive surgery, which is a plus, since the farther the tested code is from the production code, the less meaningful the test results are.
Where I find a need to use late static binding is to allow mocking of static methods for unit testing with PHPUnit. The problem I have is that I don't like changing code strictly to allow mocking, but I can get over that.
To answer your question, however, I would bet that whatever performance cost this carries, it will pale in comparison to most program runtimes. In other words, it won't make a noticeable difference.

Categories