Delayed assignment of ignored magic--php references (late data delay binding)

Source: Internet
Author: User
Ignored Magic--php Reference delay assignment (late data delay binding)

See this topic you know what I'm going to say today is the PHP variable reference feature, but what about deferred assignment? This is mainly my recent optimization of some features of an idea, I think it is good, I intend to record it. Take a look at the following pseudo-code:

This code someone would say why not use the table, because some business requirements without the efficiency of the table is 3 to 20 times times of the table///My project is basically this kind of writing, more than the efficiency of the table before the increase of $ A = Db::query ("Select ID from a"); $aid = ""; foreach ($a as $v) {$aid. = $v [' id ']. ', ';} $aid = substr ($aid, 0,-1), if ($aid) {$b = Db::query ("select * from B where aid in ({$aid})");//omitted here}

This code is used for example, because there are a lot of code like this, it is easy to understand, but not necessarily suitable for late assignment, because it is more understandable, and efficiency is similar, but can be compared with the late delay assignment, so that people more understanding of the implementation of the following way.

After reading the above example we look at a complex requirement, the data is to get a list of the last 10 articles, and read each article 5 comments, and contains the article initiator and reviewer ID, name, the data is packaged into a specified format JSON returned to the client, see the following code:

This demand with the United table to obtain user information far from the collection of user IDs do in-query efficiency $data = Array (); $article = Db::query ("Select Id,uid,title,content from article where uid={$_get[' UID ']} ORDER BY id desc limit "), foreach ($article as $v) {$uid = $v [' uid ']; $comment = Db::query (" Select Id,ui D,content from comment where aid={$v [' ID ']} ORDER BY ID ASC limit 5 "), foreach ($comment as $value) {$uid. = ', '. $value [' uid ' ];} Here the second parameter we require the DB class to return an array with the UID index $member = db::query ("Select Uid,username from user where uid in ({$uid})", ' uid '); Commentlist = Array (), $data [] = array (' id ' = = $v [' id '], ' title ' + = $v [' title '], ' content ' = $v [' content '], ' uid ' = > $v [' uid '], ' username ' = $member [$v [' uid ']][' username '], ' comment ' = & $commentList); foreach ($comment As $value) {$commentList [] = array (' id ' = + $value [' id '], ' content ' = $value [' content '], ' uid ' = ' + ' $value [' uid '], ' Username ' = $member [$value [' uid ']][' username ']}}echo json_encode ($data); exit;

Looking carefully at this code, you will find that the value of $data[][' comment '] refers to the variable $commentlist at the very beginning, then changes the value of the $commentlist later, and causes the $data[][' comment ' value to be changed along with it. , here is also late assignment, but relatively simple, you can understand the implementation of this principle.

I believe most people have written similar code, and few people think this code is problematic. Let me analyze this piece of logic, comment information because to get 5 per article, this can not be combined into a simple SQL, because the need to only get 10 articles, write complex SQL processing rather than the efficiency of the circular query (if your intranet latency is low), why the complexity of SQL processing efficiency is slow, If you think about thousands of of the data is the same no need to pay attention, but if the processing is tens other data volume, complex SQL in many cases than simple SQL efficiency, then the use of circular query can not continue to optimize. But we look at the user information is also in the loop to query, this is very bad, my project team very do not want to see such a code, 10 posts are a person initiated, nearly 50 comments will have a lot of active users of data, so each cycle query actually query to duplicate user information probability is very high, In a business logic it is best not to get duplicate information from a database but to reuse it. How can we allow users to reuse information? You can cycle through the comments of the article before assembling the final data, then collect the user ID, then get the user information, then assemble the final data. This is a relatively simple solution, not the focus of our day, the following is an elegant way of handling-delay assignment.

This demand with the United table to obtain user information far from the collection of user IDs do in-query efficiency $data = Array (); $article = Db::query ("Select Id,uid,title,content from article where uid={$_get[' UID ']} ORDER BY id desc limit "); $member = Array (); foreach ($article as $v) {$comment = Db::query (" Select Id,u Id,content from comment where aid={$v [' ID ']} ORDER BY ID ASC limit 5 "); $commentList = Array (); $data [] = array (' id ' = $ v[' id '], ' title ' = $v [' title '], ' content ' = ' content ', ' uid ' + $v [' uid '], ' username ' = & $member [$v [' UID '] [' username '], ' comment ' = & $commentList), foreach ($comment as $value) {$commentList [] = array (' id ' = + $value [' Id '], ' content ' = $value [' content '], ' uid ' = ' $value [' uid '], ' username ' = & $member [$value [' uid ']][' Username '])}} $uid = Array_keys ($member), if ($uid) {$uid = implode (', ', $uid); $user = Db::query ("Select Uid,username from User where Uid in ({$uid}) ", ' uid '), foreach ($member as $uid = = $value) {$member [$uid] [' username '] = $user [$uid] [' Username '];} Unset ($member, $user);} Echo Json_encode($data); exit; 

This code is not the same as before, the most obvious is the bottom of a piece of code, and temporarily do not know what it is to do, it seems that no use, we step by step to see, first in the cycle of the article data before the initialization of a variable $member = Array (), and then in the loop less than $uid assignment, And the loop collects the reviewer's ID, and the SQL to query the user data is gone, as if to the bottom part of the code can not understand the place. Look closely at the Something Else Discovery & $member [$v [' uid ']][' username '] and & $member [$value [' uid ']][' username '] place more & reference symbols, That's why there's less code in the loop. Recall that $commentlist was previously assigned after it was referenced and changed $data[][' comment '). This is the same reason, do not query user information, only an empty reference, when referencing a nonexistent variable, PHP will first create this variable, such as & $member [$v [' uid ']][' username '],php detection $ Member is an array that has been declared, but the $member[$v [' uid ']][' username '] does not exist on memory creation and the value is null.

When the data is finished, the print will find that username information is null, and of course, before the user information is not used, PHP gives us a null value when referencing the assignment. Then through $uid = Array_keys ($member); get all the user ID information,

Why Array_keys can get the user ID, because PHP at the time of reference to help us to create a $member array ah, note that the UID here is not repeated yo, after we go to the user table using in to retrieve information, it is important to note that the returned data can not be assigned to the $ member because the previous data are reference $member data, if this is covered $member, memory two variables address is different, equivalent to re-create an array, we here to assign to $user, the following loop is what, Of course it is the assignment of the previously referenced data, and we loop the $member variable to assign the $user[$uid [' username '] to $member[$uid] [' username '] to change the value of the reference variable. After we bind the data to the reference variable, do not ignore the use of Uset to remove the $member, mainly to prevent the code after the operation of $member variable code, careless will be the previously bound data cover out. Why delete $member after binding data is not lost, mainly refers to the attribute, when multiple variables refer to a memory address, delete one of the variables does not affect the other variables, unless all the variables are deleted, will really delete the memory data. The PHP manual explains the " when unset A reference, only the binding between the variable name and the variable content is broken." This does not mean that the contents of the variable have been destroyed . " Unset ($user); just because $user is a temporary variable, it can be freed from memory directly after use.

About this kind of programming I named late data delay binding, the reason that the title is deferred variable assignment is mainly to make it easy for everyone to understand. PHP in the role of reference is very extensive, the example given in this article is only a partial use of a method to solve the programming encountered similar business requirements of a processing method, of course, late data delay binding programming method also has a very wide use, I hope you do not confine themselves in the case of this example scenario. For the example of this article is one of the most common problems in our programming, I have written a function to handle the data delay binding, to reduce the logic of writing data binding everywhere.

/** * Data Delay binding Common method *  * @access public * @param array $bindingVar the variable to be bound * @param array$data data to bind * @param mixed$default Value * @return void  */function bindingdata (& $bindingVar, $data, $default = ") {foreach ($bindingVar as $key = $ TMP) {foreach ($tmp as $k = + $v) {$bindingVar [$key] [$k] = Isset ($data [$key] [$k])? $data [$key] [$k]: $default;}} Unset ($bindingVar);}


Using this function, we can change the code portion of the previously processed data binding to the following:

$uid = Array_keys ($member), if ($uid) {$user = Db::query ("Select Uid,username from User-where UID in ({$uid})", ' uid '); Bindin GData ($member, $user); unset ($member, $user);}


  • 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.