When should I use Static functions/classes/fields in PHP? What are some practical uses of it?
you should not, it's rarely useful.
common usage for statics are factory methods and singleton::instance()
factory:
class Point{
private $x;
private $y;
public function __construct($x, $y){
...
}
static function fromArray($arr){
return new Point($arr["x"], $arr["y"]);
}
}
singleton:
class DB{
private $inst;
private function __construct(){
...
}
static function instance(){
if ($this->inst)
return $this->inst;
return $this->inst = new DB();
}
}
Usage of static methods in same in languages like Java/PHP.
One simple example can be that you want to use a variable across all instances of your class and any instance can change its value and you want it to get reflected in other instance as well.
class Foo{
static $count=0;
public function incrementCount(){
self::$count++;
}
public function getCount(){
return self:$count;
}
}
Without static you can't set count value via one object and access it in others.
I occasionally use STATIC Methods when I need simple functions in a Class that I also use outside the Class such as:
in a UserProfile class I have an method that returns an array that is used to pass data back to the class after the array is populated from the html page.
Class UserProfile{
Public Static get_empty_array(){
return array('firstname'=>'',lastname=>''); //usually much more complex multi-dim arrays
}
}
This way the empty array can be used within the class/object and outside as a starting template.
I also use Static Methods for functions that would normally be standalone functions but I want to keep them in the class so it is all together but also make them available outside as a static method such as:
public static convert_data($string){
//do some data conversion or manipulating here then
return $ret_value;
}
$converted_data = class::convert_data($string);
I do maintain an library of common user defined functions but I have found it handy to include some in the class to which it is closely related.
Related
Im working on a project where we're creating many objects throughout the code base.
For some objects thus we decided to use factories to control the process of creating the objects and all their dependencies. This is an example of what we are trying to do:
class CreateBranchFactory implements CreateBranchInterface {
private $branch;
public function __construct() {
$this->branch = new Branch();
$this->branch->scenario = 'create';
}
public function createBranch($branchForm) {
$this->branch->attributes = $branchForm->attributes;
//Example of all the things that I need to do after creating my object
$this->setOfficialNameAndPrinterName($branchForm->official_name, $branchForm->printer_name, $branchForm->name);
$this->createDependencies1();
$this->someOtherFunction();
return $this->branch;
}
public function setOfficialNameAndPrinterName($offName, $printerName, $branchName) {
$this->branch->official_name = $offName ?? $branchName;
$this->branch->printer_name = $printerName ?? $branchName;
$this->branch->save();
}
public function createDependencies1() {
}
And to have a proper contract I created an interface for this. This interface specifies the functions that should be defined
interface CreateBranchInterface {
public function setOfficialNameAndPrinterName(String $offName, String $printerName, String $branchName);
public function createDependencies1();
}
My problem though, is that the contract is specifying all the functions that should be defined, but isnt controlling which functions should get called. Is there any design pattern that I can use, that makes sure that those functions get called??
You can't create such contract by using interfaces - interfaces specifies which methods and how you can call. Calling all these methods is part of implementation, which cannot be provided by interface. You need to create abstract class with implementation and use final keyword to disallow overriding it:
abstract class CreateBranch {
abstract protected function getBranch(): Branch;
final public function createBranch($branchForm) {
$this->getBranch()->attributes = $branchForm->attributes;
//Example of all the things that I need to do after creating my object
$this->setOfficialNameAndPrinterName($branchForm->official_name, $branchForm->printer_name, $branchForm->name);
$this->createDependencies1();
$this->someOtherFunction();
return $this->getBranch();
}
abstract public function setOfficialNameAndPrinterName(String $offName, String $printerName, String $branchName);
abstract public function createDependencies1();
abstract public function someOtherFunction();
}
I'm working on a project using graphql-php. There is an example which suggests creating a class like this:
use Project\CategoryType;
use Project\PageType;
class Types {
private static $page;
private static $category;
public static function page() {
return self::$page ?: (self::$page = new PageType());
}
public static function category() {
return self::$category ?: (self::$category = new CategoryType());
}
}
Later I can use this class methods like so:
Types::page() or Types::category()
This works fine. However, I think this is an anti-pattern and could be optimised. As the project grows, the number of similar functions and private class fields grows and this becomes inconvenient.
Is there any way to refactor the class so I don't have to manually add a function for each type but still call the class methods as I do it now? (Types::page()).
Please use __callStatic or __call magic methods. http://php.net/manual/en/language.oop5.overloading.php#object.callstatic
public static function __callStatic($name, $arguments)
{
//$name is your type
}
So far, when I wanted to know if the user is logged in or not I used Yii::app()->user->isGuest.
However, there is a method called getIsGuest(), which returns the isGuest variable.
if (!Yii::app()->user->getIsGuest())
My question is, should I use getIsGuest() instead? Using getIsGuest() is the proper way? Or it does not matter and they both correct ways?
Actually, there is no difference between $class->getAttribute() and $class->attribute. But this is good to know what is going on in behind.
Yii widely uses php magic methods. In this case, it uses __set and __get magic methods to implement getters and setters. As php's official documents defines __get() :
__get() is utilized for reading data from inaccessible properties.
Consider an example:
class Test{
private $attribute;
private $attribute2;
private $attribute3;
public function getAttribute(){
return $this->attribute;
}
public function getAttribute2(){
return $this->attribute2;
}
public function getAttribute3(){
return $this->attribute3;
}
}
If you want to get the attribute property value you must call getAttribute() method and you can not get attribute like below (since you have no access to attribute property):
$test=new Test();
echo $test->attribute;
But with __get magic method it can be implemented as:
class Test{
private $attribute;
private $attribute2;
private $attribute3;
//__GET MAGIC METHOD
public function __get($name)
{
$getter='get'.$name;
if(method_exists($this,$getter))
return $this->$getter();
}
public function getAttribute(){
return $this->attribute;
}
public function getAttribute2(){
return $this->attribute2;
}
public function getAttribute3(){
return $this->attribute3;
}
}
Now, you are able to get attribute value like below:
$test=new Test();
echo $test->attribute;
To find more about php's magic methods take a look at the php's official document:
Magic Methods
It doesn't really matter. If you call user->isGuest the method user->getIsGuest() gets internally called. It's just kind of an alias.
Due to the fact that you can not use $this-> inside a static functio, how are you supposed to access regular functions inside a static?
private function hey()
{
return 'hello';
}
public final static function get()
{
return $this->hey();
}
This throws an error, because you can't use $this-> inside a static.
private function hey()
{
return 'hello';
}
public final static function get()
{
return self::hey();
}
This throws the following error:
Non-static method Vote::get() should not be called statically
How can you access regular methods inside a static method? In the same class*
Static methods can only invoke other static methods in a class. If you want to access a non-static member, then the method itself must be non-static.
Alternatively, you could pass in an object instance into the static method and access its members. As the static method is declared in the same class as the static members you're interested in, it should still work because of how visibility works in PHP
class Foo {
private function bar () {
return get_class ($this);
}
static public function baz (Foo $quux) {
return $quux -> bar ();
}
}
Do note though, that just because you can do this, it's questionable whether you should. This kind of code breaks good object-oriented programming practice.
You can either provide a reference to an instance to the static method:
class My {
protected myProtected() {
// do something
}
public myPublic() {
// do something
}
public static myStatic(My $obj) {
$obj->myProtected(); // can access protected/private members
$obj->myPublic();
}
}
$something = new My;
// A static method call:
My::myStatic($something);
// A member function call:
$something->myPublic();
As shown above, static methods can access private and protected members (properties and methods) on objects of the class they are a member of.
Alternatively you can use the singleton pattern (evaluate this option) if you only ever need one instance.
I solved this by creating an object of the concerning class inside a static method. This way i can expose some specific public functions as static function as well. Other public functions can only be used like $object->public_function();
A small code example:
class Person
{
public static function sayHi()
{
return (new Person())->saySomething("hi");
}
public function saySomething($text)
{
echo($text);
}
private function smile()
{
# dome some smile logic
}
}
This way you can only say hi if using the static function but you can also say other things when creating an object like $peter->saySomething('hi');.
Public functions can also use the private functions this way.
Note that i'm not sure if this is best practice but it works in my situation where i want to be able to generate a token without creating an object by hand each time.
I can for example simply issue or verify a token string like TokenManager::getTokenToken(); or TokenManager::verifyToken("TokenHere"); but i can also issue a token object like $manager = new TokenGenerator(); so i can use functionality as $manager->createToken();, $manager->updateToken(updateObjectHere); or $manager->storeToken();
What's the difference between these object callings?
Non Static:
$var = new Object;
$var->function();
Static:
$var = User::function();
And also inside a class why should I use the static property for functions?
example:
static public function doSomething(){
...code...
}
Static functions, by definition, cannot and do not depend on any instance properties of the class. That is, they do not require an instance of the class to execute (and so can be executed as you've shown without first creating an instance). In some sense, this means that the function doesn't (and will never need to) depend on members or methods (public or private) of the class.
Difference is in the variable scope. Imagine you have:
class Student{
public $age;
static $generation = 2006;
public function readPublic(){
return $this->age;
}
public static function readStatic(){
return $this->age; // case 1
return $student1->age; // case 2
return self::$generation; // case 3
}
}
$student1 = new Student();
Student::readStatic();
You static function cannot know what is $this because it is static. If there could be a $this, it would have belonged to $student1 and not Student.
It also doesn't know what is $student1.
It does work for case 3 because it is a static variable that belongs to the class, unlike previous 2, which belong to objects that have to be instantiated.
Static methods and members belong to the class itself and not to the instance of a class.
Static functions or fields does not rely on initialization; hence, static.
Questions regarding STATIC functions keep coming back.
Static functions, by definition, cannot and do not depend on any instance properties of the class. That is, they do not require an instance of the class to execute (and so can be executed.
In some sense, this means that the function doesn't (and will never need to) depend on members or methods (public or private) of the class.
class Example {
// property declaration
public $value = "The text in the property";
// method declaration
public function displayValue() {
echo $this->value;
}
static function displayText() {
echo "The text from the static function";
}
}
$instance = new Example();
$instance->displayValue();
$instance->displayText();
// Example::displayValue(); // Direct call to a non static function not allowed
Example::displayText();