Contacts

Static class members. Do not give them to ruin your code. Static PHP Methods Primsel Static PHP P

It's no secret that you love to ask tricky questions on the interviews. Not always adequate, not always related to reality, but the fact remains a fact - asks. Of course, the question is a problem, and sometimes the question, at first glance, seemingly stupid, is actually aimed at checking how well you know the language you write.

Let's try to disassemble "bone" one of these questions - what does the word "static" mean in PHP and why is it applied?

The keyword static has three different values \u200b\u200bin PHP. We will analyze them in chronological order, as they appeared in the language.

The first value is a static local variable

FUNCTION FOO () ($ a \u003d 0; echo $ a; $ a \u003d $ a + 1;) foo (); // 0 foo (); // 0 foo (); // 0.

In PHP Variables Local. This means that the variable defined and the value inside the function (method) exists only during the execution of this function (method). When leaving the method, the local variable is destroyed, and when re-entry, it is proceeded. In the code above such a local variable is $ A variable - it exists only inside the Foo () function and each time you call this function is prohibited. The increment of the variable in this code is meaningless, because on the next same line of the code the function will finish its operation and the value of the variable will be lost. How many times we did not cause the function foo (), it will always take 0 ...

However, everything changes, if we put the keyword static before assigning:

FUNCTION FOO () (static $ a \u003d 0; echo $ a; $ a \u003d $ a + 1;) foo (); // 0 foo (); // 1 foo (); // 2.

The static keyword written before assigning the value of the local variable leads to the following effects:

  1. The assignment is performed only once, when you first call the function
  2. The value marked in this way variable is saved after the operation is completed.
  3. With subsequent function calls, instead of assignment, the variable receives the previously saved value
Such use of the word static is called static local variable.
Static variable underwater stones
Of course, as always in PHP, it does not cost without "pitfalls".

The stone is the first - static variable to assign only constants or constant expressions. Here is the code:
Static $ A \u003d BAR ();
With inevitability will lead to a parser error. Fortunately, starting with version 5.6, it became permissible to assign not only constants, but also constant expressions (for example - "1 + 2" or ""), that is, such expressions that do not depend on the other code and can be calculated at the compilation stage

Stone second - methods exist in a single copy.
Everything is more complicated here. To understand the essence, I will give the code:
Class A (Public FUNCTION FOO () (static $ x \u003d 0; echo ++ $ x;)) $ a1 \u003d new a; $ a2 \u003d new a; $ a1-\u003e foo (); // 1 $ a2-\u003e foo (); // 2 $ A1-\u003e foo (); // 3 $ a2-\u003e foo (); // four
Contrary to intuitive wait for "different objects - different methods" we visually see this example that dynamic methods in PHP "do not multiply." Even if we have a hundred objects of this class, the method will exist only in one instance, just with each call to it will be minted different $ this.

Such behavior may be unexpected for the developer unprepared for it and serve as a source of errors. It should be noted that the inheritance of the class (and method) leads to the fact that a new method is created:

Class A (Public FUNCTION FOO () (static $ x \u003d 0; echo ++ $ x;)) Class B Extends A () $ A1 \u003d new A; $ b1 \u003d new b; $ a1-\u003e foo (); // 1 $ b1-\u003e foo (); // 1 $ A1-\u003e foo (); // 2 $ b1-\u003e foo (); // 2.

Conclusion: Dynamic methods in PHP exist in the context of classes, not objects. And only in the ranktime there is a substitution "$ THIS \u003d Current_Object"

Meaning Second - Static Properties and Class Methods

In the PHP object model, it is possible to set properties and methods not only for objects - class instances, but also for a class as a whole. To do this, also serves the keyword static:

Class A (Public Static $ x \u003d "Foo"; Public Static Function Test () (Return 42;)) Echo A: $ x; // "Foo" Echo A :: Test (); // 42.
For access to such properties and methods, structures with a double colon ("Paamayim Nekudotayim") are used, such as the name_name :: $ Purpose and name_name :: NameMode ().

It goes without saying that static properties and static methods have its own characteristics and their "pitfalls" that you need to know.

Feature is the first, banal - no $ this. In fact, this stems from the very definition of the static method - since it is associated with the class, and not an object, it is not available to the pseudo-temperature $ THIS, indicating in dynamic methods to the current object. What is completely logical.

However, you need to know that in contrast to other languages, PHP does not define the situation "in the static method is written $ this" at the stage of parsing or compilation. A similar error may occur only in Rataryime if you try to perform code with $ THIS inside the static method.

Type code such:
Class A (Public $ ID \u003d 42; Static public FUNCTION FOO () (Echo $ this-\u003e ID;))
It will not lead to any errors, as long as you do not try to use the Foo () method in the inappropriate way:
$ a \u003d new a; $ a-\u003e foo (); (and immediately get "Fatal Error: Using $ This WHEN NOT IN OBJECT CONTEXT")

Feature Two - Static is not an axioma!
Class A (Static Public Function Foo () (Echo 42;)) $ a \u003d new a; $ a-\u003e foo ();
Like this, yes. Static method, if it does not contain in Code $ this, it is possible to call in a dynamic context as the object method. This is not an error in PHP.

The reverse is not quite true:
Class A (Public FUNCTION FOO () (ECHO 42;)) A :: FOO ();
A dynamic method that does not use $ this can be performed in a static context. However, you will receive a warning "Non-Static Method A :: Foo () Should Not Be Called Statically" E_STRICT level. There to solve you - or strictly follow the code standards, or suppress warnings. The first, of course, is preferable.

And by the way, everything written above applies only to methods. Using static properties through "-\u003e" is impossible and leads to a fatal error.

The value is the third, apparent the most difficult - later static binding

The developers of the PHP language did not stop at the two values \u200b\u200bof the keyword "static" and in version 5.3 added another "feature" language, which is implemented by the same word! It is called "Later Static Binding" or LSB (Late Static Binding).

Understand the essence of LSB is the easiest way to be simple examples:

Class Model (Public Static $ Table \u003d "Table"; Public Static Function GetTable () (Return Self :: $ Table;)) Echo Model :: GetTable (); // "Table"
The SELF keyword in PHP always means "class name, where this word is written." In this case, SELF is replaced by the Model class, and self :: $ table - on Model :: $ Table.
Such a language possibility is called "early static binding." Why early? Because the binding of the Self and the specific name of the class is not occurring in the ranktime, but at earlier stages - parsing and compilation of the code. Well, "static" - because we are talking about static properties and methods.

Slightly change our code:

Class Model (Public Static $ Table \u003d "Table"; Public Static Function GetTable () (Return Self :: $ Table;)) Class User Extends Model (Public Static $ Table \u003d "Users";) Echo User :: GetTable () ; // "Table"

Now you understand why PHP behaves in this situation nonintuitively. The SELF was associated with the Model class when the User class has not yet been known, therefore indicates model.

How to be?

To solve this dilemma, the "Late" binding mechanism was invented, at the ranktime stage. It works very simply - enough instead of the word "SELF" write "Static" and the connection will be installed with the class that causes this code, and not with where it is written:
Class Model (Public Static $ Table \u003d "Table"; Public Static Function GetTable () (Return Static :: $ Table;)) Class User Extends Model (Public Static $ Table \u003d "Users";) Echo User :: GetTable () ; // "Users"

This is a mysterious "later static binding."

It should be noted that for greater convenience in PHP, except for the word "static", there is still a special function get_called_class (), which will inform you - in the context of which class is currently your code works.

Successful interviews!



There are two varieties of PHP developers in the world. Some prefer static methods, because it is easy to work with them, others, by contrast, consider static methods - evil and do not use them in their practice.
In this article I will try using the experience with several frameworks, to explain why some developers ignore the best practices and use a whole bunch of static methods.

Who loves static methods?

Especially often they use developers who have ever used in their work framework CodeIGNITER.

Also, the followers of statistical methods include most Kohana- and Laravel developers.
It is impossible not to mention the fact that programmers who decide to start writing their own things usually refuse to use CodeIGNITER.

Why do you ask?

CodeIGNITER supported PHP 4 before static methods were added to PHP 5. In addition, CodeIGNITER uses a "super object", which provides equal access to all classes assigned to the controller. Thus, they become accessible to use throughout the entire system.

This means that classes can be available from any model using the __get () method, which will search for the requested property using get_instance () -\u003e ($ var). Previously, when the support for the function __get () was not in PHP 4, for this was used the Foreach design through the Ci_Controller parameters, and then they were assigned to the $ this variable in the model.

In the library you must call Get_instance. The library does not inherit a class in a compulsory order, so there is no way to bypass the __get () function.

Volume ...

It turns out a rather cumbersome design to access the code. Exactly the same functionality without additional efforts can be achieved using a static method.

Yes, and there is no particular sense to argue about such a design. Well, you can access the session data in your model. But why do you need to do it?

"Decision"

Kohana developers were the first to work seriously over static methods. They made the following changes:
// was $ this-\u003e input-\u003e get ("foo"); // became input :: get ("foo");
For many codeigniter developers with their outdated PHP 4, who moved to the framework Kohana to enjoy all PHP 5 charms, there is nothing unusual in this. But, the fewer characters, the better, right?

And what is the problem?

Many PHP developers (especially those who understand the Symfony and Zend) will say: "It is obvious - use the introduction of dependencies!" But not many developers in the CodeIGNITER community have real experience with this process, as it is quite complicated.

Another fact about Fuel PHP framework is still mainly static methods act as an interface. For example, logic still has problems with static, especially when the HMVC concept is activated.

This is a pseudocode that I did not use in Fuelphp, starting with version 1.1:
Class Controllera EXTENDS CONTROLLER (Public Function Action_foo () (Echo Input :: Get ("Param");))
Pretty standard code. This method will output the value ? Bar \u003d. In the method.

What happens when we make a HMVC request to this method?
Class Controllerb EXTENDS CONTROLLER (ECHO INPUT :: GET ("PARAM"); ECHO "&"; Echo Request :: Forge ("Controllera / Foo? Param \u003d Val1") -\u003e execute ();) )
Calling in the browser controllerB / Baz.you will see the "Val1" output, but if you get controllerB / Baz? Param \u003d OverrideYou will receive both challenges to get the method returning the same value.

Relevance

The global code will not give you any relationship. An example is better than any words:
$ this-\u003e Request-\u003e Input-\u003e Get ("Param");
The requested object will contain a completely new instance for each query, then the entry of the object will be created for each request, which contains only input data for a specific query. This is true for FUELPHP 2.0 Plans To Work and solves the problem of adding dependency, as well as problems with HMVC.

How to deal with gross syntax?

Symfony- or Zend developers do not suffer so much, but those who use CodeIGNITER will long be nightmares about "return to PHP 4".

$ This always refers to the "current" object, and it is not exactly necessary to use it to access the global code.

$ this-\u003e request-\u003e input-\u003e get () may look like an elongated codeigniter-syntax form, but in fact we are simply in the controller. When the controller creates an instance of the new query inserted into it, the query constructor also receives an instance at the input.

If you are in a model or other class, then access is the type of $ this-\u003e request-\u003e input-\u003e foo () will not work, because $ this is not the controller.

INPUT :: GET design ("foo") creates a facade for logic instances in the background. But this does not solve issues related to the work of the global code. The lazy when testing applications can switch between two modes without the need to fully use the new framework.

There is a great video from Taylor Oblla (Creator or Laravel 4) in which it describes how you can replace static code with a single instance verified through its DIC container.

Laravel 4 - Ioc Controller Injection & Unit Testing From Userscape On Vimeo.

This is an excellent presentation of how you can do without the use of static methods in Laravel. Although some modern frameworks, at first glance, are very reminded by Kohana, they absolutely solve even the most standard tasks in different ways.

On this sad note ...

Now I am engaged in the Pyrocms conversion with CodeIGNITER on Laravel. I am trying to move directly from the global code PHP 4 to the perfect implementation of dependencies is absolute suicide. Intermediate step Before using the Ci bootloader - the use of PHP 5, auto-loaded PSR-2 code with a bunch of static methods. Well, while we are still in CodeIGNITER.

The transition from the statics to the DIC code can be easily shown when we finally make the transition to Laravel.

The transition from the sublink codeigniter code to the PSR-2 tested is the main task. The PYRO team is already on the way - and it will be epic.

In PHP, it is possible to determine the method as static. The static method does not have access to the properties of the object. Such methods can only be caused in the context of the class, but not in the context of the object.

The most important thing is to understand - static properties and methods are presented by classes, not objects.

The example will become immediately clear. Let's create a MATH object (abbreviated by mathematics in English).

Static methods PHP.
"; $ Math_1 \u003d New Math (); $ Math_2 \u003d New Math (); $ Math_3 \u003d New Math (); $ Math_4 \u003d New Math (); Echo" created objects: ". Math :: GetCount ();?\u003e

This class provides tools to work with mathematical functions without the need to create an object. The class has a constructor that increases the static property of $ Count per unit. The class remembers the value of this property, as it is static.

By the way, the word STATIC word is used to declave the method or static property, and the word Self with a double colon is used to access a static property "::".

All this is best understood in comparison, especially in comparing the working example with erroneous. Let's slightly expand our example.

Static methods PHP. counter ++; ) Public Static Function Calcsin ($ x) (Return Sin ($ x);) Public Static Function Calcsqrt ($ x) (Return SQRT ($ x);) Public Static Function GetCount (RETURN SELF :: $ Count;) Public Function GetCounter () (Return $ This-\u003e Counter;)) Echo Math :: Calcsin (1); Echo "
"Echo Math :: Calcsqrt (9); Echo"
"; $ Math_1 \u003d New Math (); $ Math_2 \u003d New Math (); $ Math_3 \u003d New Math (); $ Math_4 \u003d New Math (); Echo" created objects: ". Math :: GetCount (); Echo"
"; ECHO" created objects: "$ Math_4-\u003e GetCounter ();?\u003e

In this example, we added the class of the usual $ Counter property, it also increased by one in the constructor. But the usual property belongs to the object, so it is not saved between the challenges of objects. With any creation of an instance of a class (object), the property will be equal to nulo, in the designer it will be increased by one.

Static property belongs to the class, so its value is saved.

Below are some more examples that reveal the work of static properties and methods.

Attempting to use in the static method $ this variable will result in error (Fatal Error: Using $ This WHEN NOT IN OBJECT CONTEXT).

Static methods PHP. age. "OLD."; // This is an error "USING $ THIS WHEN NOT IN OBJECT CONTEXT". )) $ Testclass \u003d new testclass (); $ Testclass-\u003e sayhello (); ? \u003e.

By the way, without a string:

$ Testclass-\u003e sayhello ();

errors will not be, but as soon as you try to start the static method from the $ this variable, you immediately receive an error message.

If in this example, remove the word static, then the errors will not be.

If you refer to the object property from the static method, it will result in an error. You can apply only to static properties using the Self :: $ Age design. Please note that there is a $ sign in front of the variable name, unlike the $ this-\u003e AGE design.

Static methods PHP. sayhello (); ? \u003e.

If in this example, remove the word static in front of the property name, then the "Access to undeclared Static Property" error will occur.

Static properties are absent in class objects.

Static methods PHP. "; Print_r ($ Testclass); Echo""; ?>

Static method can be called using the Self :: method () method. Example:

Static methods PHP. printhello (); ? \u003e.

Static property can be obtained in the context of the class using syntax:

echo Testclass :: $ Age;

Moreover, an attempt to refer to the usual property will thus lead to an error: "Fatal Error: Access to undeclared Static Property".

Static property can be changed in the context of the class using syntax:

TestClass :: $ Age + \u003d 20; // eg

Another example of code with static methods and properties

In this example, more simple options for using static methods and properties. The more simple code you will understand, the better remember the material.

Static methods PHP. ".TestClass :: $ Age; // Echo Testclass :: $ TXT; // Error: Fatal Error: Access to undeclared Static Property. Echo"
"; TestClass :: Sayhi (); Echo"
"TestClass :: Sayhello (); // And so I could get access to a static variable through the object ($ OBJ :: $ Age) ... Echo"
"; $ obj \u003d new testclass; echo" We obtain a degree to a static variable through the object: ". $ OBJ :: $ Age;?\u003e

Note, and this is important, in this example we turned to the non-static method of Sayhi () using the syntax of access to static class elements.

Summary

  • Main: Static properties belong to classes, not objects.
  • From the static method, it is impossible to contact the usual properties and methods of class, $ this-\u003e NAME does not work here.
  • From the static method, you can refer to static properties using Self :: $ Name.
  • Static class properties are not available to objects.
  • The usual method can refer to a static property using self :: $ name.
  • Static property can be obtained in the class context using syntax: TestClass :: $ Age.
  • The usual method can be called in the context and object ($ Object-\u003e method ()), and the class using the TestClass syntax :: method ().
  • Using the syntax of $ Object :: $ Age I managed to access the static property through the object.

Parallel with JavaScript

JavaScript has such a Math class containing a lot of different mathematical functions.

To carry out mathematical calculations (calculation of sinus or exhibit) in JavaScript, it is not necessary to create an object of class Math, since its methods are static. Before studying PHP, I could not understand what it was, and only having studied classes and objects in PHP in my head everything fell onto my shelves.

In fact, it is very convenient, have direct access to mathematical methods of the Math class, avoiding the object creation.

I have long wanted to write on this topic. The first shock was the article Miško Hevery "Static Methods Are Death to Testability." I wrote a response article, but never published it. But recently saw something that can be called "class-oriented programming". This refreshed my interest in the topic and here's the result.

"Class-oriented programming" is when classes consisting only of static methods and properties are used, and the class instance is never created. In this article, I will talk about:

  • it does not give any advantages compared to procedural programming.
  • do not give up objects
  • availability of static members of the class! \u003d Death Tests
Although this article about PHP, concepts apply to other languages.

Dependencies

Usually, the code depends on the other code. For example:

$ Foo \u003d Substr ($ Bar, 42);
This code depends on the $ BAR variable and the Substr functions. $ Bar is just a local variable defined slightly higher in the same file and in the same scope. Substr is the PHP kernel function. Everything is simple here.

Now, such an example:

Class BloomFilter (... public function __construct ($ m, $ k) (...) Public Static Function Getk ($ m, $ n) (RETURN CEIL ((($ M / $ n) * log (2)); ) ...)
This small auxiliary function simply provides a wrapper for a specific algorithm that helps to calculate a good number for the $ k argument used in the constructor. Because It must be caused before creating a class instance, it must be static. This algorithm has no external dependencies and is unlikely to be replaced. It is used like this:

$ m \u003d 10,000; $ n \u003d 2000; $ B \u003d New BloomFilter ($ M, BloomFilter :: Getk ($ m, $ n));
It does not create any additional dependencies. The class depends on myself.

  • Alternative designer. A good example is the DateTime class built into PHP. Its instance can be created in two different ways:

    $ Date \u003d New DateTime ("2012-11-04"); $ Date \u003d DateTime :: CreateFromFormat ("D-M-Y", "04-11-2012");
    In both cases, the result will be an instance of DateTime and in both cases the code is tied to the DateTime class one way or another. Static method DateTime :: CreateFromFromat is an alternative object of the object that returns the same as New DateTime, but using additional functionality. Where you can write New Class, you can write and Class :: Method (). No new dependencies occur.

  • The remaining use of static methods affect binding and can form implicit dependencies.

    Word about abstraction

    Why does this break with dependencies? Ability to abstract! With the growth of your product, it grows its complexity. And the abstraction is the key to the management of complexity.

    For example, you have an Application class, which presents your application. He communicates with the user class, which is the prevention of the user. Which receives data from Database. Database class needs databasedriver. Databasedriver need connection settings. Etc. If you simply call the Application :: start () statically, which will cause the user :: getdata () statically, which will cause the database statically and so on, in the hope that each layer will deal with its dependencies, you can get a terrible mess if something goes not this way. It is impossible to guess whether the application :: start () call will work, because it is not obvious how internal dependences will behave. It is even worse that the only way to influence the behavior of the Application :: Start () is to change the source code of this class and the class code that it calls and the class code that the classes appear ... in the house that Jack built.

    The most effective approach, when creating complex applications, is the creation of individual parts that can be rejected in the future. Parts that can be stopped thinking in which you can be sure. For example, when calling static Database :: Fetchall (...), there are no guarantees that the connection to the database is already installed or will be installed.

    FUNCTION (Database $ Database) (...)
    If the code within this feature is executed - this means that the Database instance has been successfully transferred, which means that the instance of the Database object has been successfully created. If the Database class is designed correctly, you can be sure that the presence of an instance of this class means the ability to perform requests to the database. If the class instance is not, the body of the function will not be executed. This means that the function should not take care of the state of the database, the Database class will do it himself. This approach allows you to forget about dependencies and concentrate on solving problems.

    Without the possibility, do not think about dependencies and dependencies of these dependencies, it is almost impossible to write at least a complex application. Database can be a small wrapper class or a giant multi-layer monster with a bunch of dependencies, it can begin as a small wrapper and mutate in a giant monster with time, you can inherit the Database class and transfer to the descendant function, it's not all important for your function (Database $ Database), as long as the Database public interface does not change. If your classes are properly separated from the other parts of the application by implementing dependencies, you can test each of them using the plugs instead of their dependencies. When you tested a class enough to make sure that it works as it should, you can throw out more unnecessary from the head, just knowing that you need to use the Database instance to work with the database.

    Class-oriented programming is nonsense. Learn to use OOP.

    REG.RU: Domains and Hosting

    The largest recorder and hosting provider in Russia.

    More than 2 million domain names for maintenance.

    Promotion, mail for a domain, business solutions.

    More than 700 thousand customers worldwide have already made their choice.

    * Mouse over to suspend scroll.

    Back forward

    Static Methods and Properties in PHP

    In previous materials, we mastered the main possibilities of object-oriented programming in PHP and now go to the study of more complex and interesting aspects.

    Before that, we always worked with objects. We described classes as templates with which objects are created, and objects - as active components, the methods of which we call and whose properties we get access.

    From here, it followed the conclusion that in object-oriented programming the actual work is performed using instances of classes. And the classes ultimately are just templates for creating objects.

    But in fact, not everything is so simple. We can access both methods and properties in the context of a class, and not an object. Such methods and properties are called "static" and must be announced using a keyword static..

    Class StaticeXample (Static Public $ Anum \u003d 0; Static Public Function Sayhello () (Print Hello! ";))

    Static Methods - These are functions used in the context of the class. They themselves cannot receive access to any common class properties, because such properties belong to objects.

    However, from static methods, as you probably guessed, you can refer to static properties. And if you change the static property, then all instances of this class will be able to access a new value.

    Since access to the static element is carried out through the class, and not through an object instance, we do not need a variable that refers to the object. Instead, a class name is used, after which two colors are indicated "::".

    Print StaticeXample :: $ Anum; StaticeXample :: Sayhello ();

    With this syntax, you must already be familiar on the basis of the OOP in PHP. We used the design "::" in combination with a keyword parent. In order to gain access to the redefined parent class method.

    Now, like then, we appeal to the class, and not to the data contained in the object. In the class code, you can use a keyword parent. In order to access the superclass, without using the class name.

    To access the static method or property from the same class (and not from a child class), we will use the keyword self..

    Keyword self. Used to appeal to the current class, and pseudo-destroyed $ THIS - To the current object. Therefore, from outside the class Staticexample we appeal to property $ Anum Using his class name.

    StaticeXample :: $ anum;

    And inside the class Staticexample You can use a keyword self..

    Class StaticeXample (Static Public $ Anum \u003d 0; Static Public Function Sayhello () (Self :: $ Anum ++; Print "Hi! (". Self :: $ Anum. ") \\ N";))

    Note: In addition to cases of appeal to the redefined parent class method, the "::" design should always be used only to access static methods or properties.

    By definition, static methods are not invoked in the context of the object. For this reason, static methods and properties are often called variables and class properties. As a result, it is impossible to use pseudo-destroyed $ THIS inside the static method.

    Why use the static method or property?

    So we reached the most important issue. The fact is that static elements have a number of useful characteristics.

    FirstlyThey are available from any point of the script (provided that you have access to the class). This means that you can access the functions without sending an instance of the class from one object to another or, even worse, saving an instance of an object in a global variable.

    Secondly, Static property is available to each instance of the object of this class. Therefore, you can define the values \u200b\u200bthat should be accessible to all objects of this type.

    And finally thirdThe fact that does not need to have an instance of a class to access its static property or method will avoid creating instances of objects solely for the sake of calling a simple function.

    To demonstrate this, let's create a static method for class ShopProduct.which will automatically create instances of objects ShopProduct.. C using SQLite Determine the table products. in the following way:

    Create Table Products (ID Integer Primary Key AutoIncrement, Type Text, FirstName Text, Mainname Text, Title Text, Price Float, Numpages Int, PlayLength int, Discount Int)

    Now create a method getInstance ()which passes the line identifier and an object of type PDO. They will be used to extract the row from the database table, on the basis of which the type object is then formed. ShopProduct.returned to the calling program.

    We can add these methods to the class ShopProduct.which was created to us in earlier materials. As you probably know, PDO is decrypted as PHP Data Object (PHP data objects). The PDO class provides a universal interface for various database applications.

    // class ShopProduct Private $ id \u003d 0; Public Function Setid ($ ID) ($ this-\u003e id \u003d $ id;) // ... Public Static Function GetInstance ($ ID, PDO $ PDO) ($ STMT \u003d $ PDO-\u003e Prepare ("SELECT * from Products Where id \u003d? "); $ result \u003d $ STMT-\u003e EXECUTE (Array ($ ID)); $ ROW \u003d $ STMT-\u003e Fetch (); if (Empty ($ ROW)) (RETURN NULL;) if ($ ROW ["Type"] \u003d\u003d "Book") ($ Product \u003d New BookProduct ($ Row ["Title"], $ row ["firstName"], $ row ["MainName"], $ row ["Price"] , $ row ["numpages"]);) ELSE if ($ Row ["Type"] \u003d\u003d "CD") ($ product \u003d new cdproduct ($ row ["title"], $ row ["firstname"], $ Row ["MainName"], $ row ["Price"], $ row ["Playltength"]);) ELSE ($ product \u003d new shopProduct ($ row ["title"], $ row ["firstName"], $ row ["MainName"], $ row ["Price"]);) $ product-\u003e setid ($ row [ID "]); $ product-\u003e setDiscount ($ row [" discount "]); Return $ Product;) // ...

    As you can see, the method getInstance () Returns object type ShopProduct., and it is enough "smart" in order to be based on the field value type Create an object with the desired characteristics.

    I specifically lowered the error handling code so that the example was simpler. For example, in the actual version of this code, we can not be too trusting and assume that the transmitted PDO object was correctly initialized and connected to the required database.

    In fact, we are likely to conclude a PDO object in a class that guarantees such behavior. We will back to this question in one of the future materials.

    Method getInstance () More useful in the context of the class than in the context of the object. It makes it easy to convert data that are in the database to the object, and for this we do not need to have a separate instance of the type object ShopProduct..

    This method does not use any methods or properties that require a separate instance of the object, so there is no reason to not declare it static. Then, having a correct PDO object, we can call this method from any application location.

    $ dsn \u003d "sqlite: //home/bob/projects/products.db"; $ PDO \u003d NEW PDO ($ DSN, NULL, NULL); $ PDO-\u003e SETATITRIBUTE (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); $ OBJ \u003d ShopProduct :: GetInstance (1, $ PDO);

    Such methods work as a "factory", as they take "raw" materials (for example, data obtained from the database string or configuration file) and use them to create objects.

    The term "factory" refers to code designed to create instances of objects. With examples of such "factories" we will meet with you further.


    Permanent properties

    Some properties should not change. For example, elements such as error codes or program status codes are usually set manually in classes. Although they must be publicly available and static, the client code should not be able to change them.

    To do this, you can define the constant properties within the class. Like global constants, the class constants cannot be changed after they have been identified. Permanent property declare using a keyword const..

    Unlike conventional properties, the dollar sign is not put before the name of the permanent property. According to the adopted agreement, they are often prescribed names consisting of only capital letters, as in the following example:

    Class ShopProduct (Const Available \u003d 0; Const Out_of_stock \u003d 1; // ...

    Permanent properties may contain only values \u200b\u200brelated to elementary type. Constant can not be assigned an object.

    As with static properties, access to permanent properties is carried out through the class, and not through an instance of the object. Just as a constant is determined without a dollar sign, when accessing it, it also does not need to use any symbol in front.

    Print ShopProduct :: Available;

    Attempting to assign a constant to the value after it was declared, will result in an error at the stage of the syntactic analysis ..

    Constants should be used when the property must be accessible to all instances of the class and when the property value must be fixed and unchanged.

    I complete this article, and next we will talk about.

    Did you like the material and want to thank?
    Just share with friends and colleagues!




    Did you like the article? Share it