How to use global variables in PHP in a detailed way

Source: Internet
Author: User
This article is a detailed analysis of several methods of using global variables in PHP, which requires a friend's reference

Brief introduction
Even if you develop a new large PHP program, you will inevitably need to use global data, because some of the data needs to be used in different parts of your code. Some common global data are: Program setting class, database connection class, user profile and so on. There are many ways to make this data global, the most common is to use the "global" keyword declaration, later in the article we will explain in detail.
The only drawback to using the "global" keyword to assert global data is that it is actually a very poor programming style and often leads to bigger problems in the program since the global data links the original pieces of code in your code. The consequence is that if you change some part of the code, it may cause other parts to go wrong. So if you have a lot of global variables in your code, your entire program must be hard to maintain.

This article will show you how to prevent this global variable problem with different techniques or design patterns. Of course, first let's look at how to use the "global" keyword to make global data and how it works.

Using global variables and the "global" keyword
PHP By default defines some "super Global (Superglobals)" variables, which are automatically global and can be called anywhere in the program, such as $_get and $_request, and so on. They usually come from data or other external data, and using these variables is usually not a problem because they are basically non-writable.

But you can use your own global variables. Using the keyword "global" You can import global data into the local scope of a function. If you do not understand the "variable use range", please refer to the instructions in the PHP manual for yourself.
Here's a demo example that uses the "global" keyword:

The code is as follows:

<?php$my_var = ' Hello world '; Test_global (), function Test_global () {    //Now in local scope    //the $my _var Variab Le doesn ' t exist    //produces error: "Undefined variable:my_var"    echo $my _var;    Now let's important the variable    global $my _var;    Works:    echo $my _var;}? >

As you can see in the example above, the "global" keyword is used to import global variables. It seems to work well, and it's simple, so why worry about using the "global" keyword to define global data?
Here are three good reasons:

1, code reuse is almost impossible.
If a function relies on global variables, it is almost impossible to use this function in a different environment. Another problem is that you cannot extract this function and then use it in other code.

2, debugging and solve the problem is very difficult.
Tracking a global variable is more difficult than tracking a non-global variable. A global variable may be redefined in some of the less obvious include files, even if you have a very Good program editor (or IDE) to help you, it will take you a few hours to discover the problem.

3. It will be very difficult to understand the code.
It's hard to figure out where a global variable comes from and what it does. In the process of development, you may know that every global variable is known, but about a year later, you may forget at least the general global variables, which you will regret for using so many global variables.
So what should we use if we don't use global variables? Let's take a look at some of these solutions.
Using function parameters
One way to stop using a global variable is simply to pass the variable as a function parameter, as shown here:

The code is as follows:

<?php$var = ' Hello world '; test ($var); function test ($var) {    echo $var;}? >

If you only need to pass a global variable, then this is a very good or even excellent solution, but what if you want to pass a lot of values?
For example, if we want to use a database class, a program settings class and a user class. In our code, these three classes are used in all components, so they must be passed to each component. If we use the method of function arguments, we have to do this:

The code is as follows:

<?php$db = new DBConnection; $settings = new Settings_xml; $user = new User;test ($db, $settings, $user); function test (&am p; $db, & $settings, & $user) {    //do something}?>


Obviously, this is not worth it, and once we have new objects to join, we have to add one more function parameter to each function. So we need to use another way to solve this problem.

One way to solve a function parameter problem with a single piece (singletons) is to use a single piece (singletons) instead of a function parameter. A single piece is a special class of objects that can only be instantiated once and contain a static method to return an interface to an object. The following example shows how to build a simple single piece:

The code is as follows:

<?php//Get instance of dbconnection$db =& dbconnection::getinstance ();//Set user property on object$db->user =  ' sa ';//Set second variable (which points to the same instance) $second =& dbconnection::getinstance ();//should print ' Sa ' echo $second->user; Class DBConnection {    var $user;    function &getinstance () {        static $me;        if (Is_object ($me) = = True) {            return $me;        }        $me = new DBConnection;        return $me;    }    function Connect () {        //TODO    }    function query () {        //todo    }}?>


The most important part of the above example is the function getinstance (). This function returns an instance of this class by using a static variable $me, ensuring that only one instance of the DbConnection class is available.
The advantage of using a single piece is that we do not need to explicitly pass an object, but simply use the getinstance () method to get to the object as follows:

The code is as follows:

<?phpfunction Test () {    $db = dbconnection::getinstance ();    Do something with the object}?>


However, the use of a single piece also has a series of deficiencies. First, how do we need to globally multiple objects in a class? Because we use a single piece, so this is impossible (as its name is a single piece). Another problem is that a single piece cannot be tested with individual tests, and it is completely impossible, unless you introduce all the stacks, and this is obviously something you don't want to see. This is why the single piece is not the main reason for our ideal solution.

Registration mode
The best way to get some objects to be used by all the components in our code (the Translator notes: Global objects or data) is to use a central container object that contains all of our objects. Typically, this container object is called a registrar by people. It's very flexible and it's very simple. A simple Registrar object is as follows:

The code is as follows:

<?phpclass Registry {    var $_objects = array ();    function set ($name, & $object) {        $this->_objects[$name] =& $object;    }    function &get ($name) {        return $this->_objects[$name];    }}? >

The first step in using a Registrar object is to use method set () to register an object:

The code is as follows:

<?php$db = new DBConnection; $settings = new Settings_xml; $user = new user;//Register objects$registry =& New Regis try; $registry->set (' db ', $db); $registry->set (' Settings ', $settings); $registry->set (' user ', $user);? >

Now that our Register object holds all of our objects, we refer to the need to pass this registrar object to a function (instead of passing three objects separately). Look at the following example:

The code is as follows:

<?phpfunction Test (& $registry) {    $db =& $registry->get (' db ');    $settings =& $registry->get (' Settings ');    $user =& $registry->get (' user ');    Do something with the objects}?>

A big improvement of the registrar compared to other methods is that when we need to add a new object to our code, we no longer need to change everything (the translator notes: All the code that uses the global object in the program), we just need to register a new object in the Registrar, Then it (the translator note: The newly registered object) can be called immediately in all components.

To make it easier to use the Registrar, we changed its invocation to one-piece mode (translator Note: Do not use the previously mentioned function pass). Because only one registrar is required in our program, the single-piece mode makes it ideal for this task. Add a new method to the Registrar class as follows:

The code is as follows:

<?function &getinstance () {    static $me;    if (Is_object ($me) = = True) {        return $me;    }    $me = new Registry;    return $me;}? >

This allows it to be used as a single piece, such as:

The code is as follows:

<?php$db = new DBConnection; $settings = new Settings_xml; $user = new user;//Register objects$registry =& registry: : getinstance (); $registry->set (' db ', $db); $registry->set (' Settings ', $settings); $registry->set (' user ', $ User), function test () {    $registry =& registry::getinstance ();    $db =& $registry->get (' db ');    $settings =& $registry->get (' Settings ');    $user =& $registry->get (' user ');    Do something with the objects}?>

As you can see, we don't need to pass the private stuff to a function, nor do we need to use the "global" keyword. So the Registrar mode is the ideal solution for this problem, and it's very flexible.

Request Wrapper
Although our registrar has made the "global" keyword completely redundant, there is still one type of global variable in our code: The Super global variable, such as the variable $_post,$_get. Although these variables are very standard, and there is no problem in your use, but in some cases, you may also need to use the Registrar to encapsulate them.
A simple workaround is to write a class that provides an interface to get these variables. This is often referred to as the "request wrapper", and here is a simple example:

The code is as follows:

<?phpclass Request {    var $_request = array ();    function Request () {        //Get request variables        $this->_request = $_request;    }    function Get ($name) {        return $this->_request[$name];    }}? >

The example above is a simple demo, but you can do a lot of other things in the request wrapper (for example: Automatically filter data, provide default values, and so on) wrapper.
The following code shows how to invoke a request wrapper:

The code is as follows:

<?php$request = new request;//Register object$registry =& registry::getinstance (); $registry->set (' request ' , & $request), test (), function test () {    $registry =& registry::getinstance ();    $request =& $registry->get (' request ');    Print the ' name ' querystring, normally it ' d be $_get[' name ']    echo htmlentities ($request->get (' name '));}? >

As you can see, now we are no longer dependent on any global variables, and we completely keep these functions away from global variables.
Conclusion
in this article, we demonstrate how to fundamentally remove the global variables in the code and replace them with appropriate functions and variables. Registration mode is one of my favorite design patterns because it is very flexible and it prevents your code from becoming a mess.
In addition, I recommend passing a Registrar object using a function parameter rather than a single-piece pattern. Although it is easier to use a single piece, it may cause problems later, and it is easier to understand the use of function parameters to pass.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.