In-depth understanding of PHP arrays (traversal order)
People often ask me, if a PHP array is accessed using foreach, is the order of traversal fixed? In what order?
For example:
. The code is as follows:
$ arr['laruence'] = 'huixinchen';
$arr['yahoo'] = 2007;
$arr['baidu'] = 2008;
foreach ($arr as $key => $val) {
/ /What is the result?
}
Another example:
. The code is as follows:
$arr[2] = 'huixinchen';
$arr[1] = 2007;
$ arr[0] = 2008;
foreach ($arr as $key => $val) {
//What is the result now?
}
To fully understand this issue, I think we should first ask everyone Understand the internal implementation structure of PHP arrays...
PHP arrays
In PHP, arrays are implemented using a HASH structure (HashTable). PHP uses some mechanisms to make it possible in O(1) time complexity It realizes the addition and deletion of arrays at a high speed, and supports linear traversal and random access at the same time.
We have also discussed PHP’s HASH algorithm in previous articles. Based on this, we will make further extensions.
Before getting to know HashTable, let us first look at it Looking at the structure definition of HashTable, I added comments for everyone to understand:
. The code is as follows:
typedef struct _hashtable {
uint nTableSize; /* Hash table size, range of Hash values*/
uint nTableMask; /* Equal to nTableSize -1, used for quick positioning*/
uint nNumOfElements; /* The number of actual elements in the HashTable*/
ulong nNextFreeElement; /* The numeric index of the next free available position*/
Bucket *pInternalPointer; /* Internal The position pointer will be reset and current. These traversal functions use */
Bucket *pListHead; /* Head element, used for linear traversal*/
Bucket *pListTail; /* Tail element, used for linear traversal*/
Bucket ** arBuckets; /* Actual storage container */
dtor_func_t pDestructor; /* Element destructor (pointer) */
zend_bool persistent;
unsigned char nApplyCount; /* Loop traversal protection */
zend_bool bApplyProtection;
#if ZEND_DEBUG
int inconsistent;
#endif
} HashTable;
Regarding the meaning of nApplyCount, we can understand it through an example:
. The code is as follows:
$arr = array(1, 2,3,4,5,);
$arr[] = &$arr;
var_export($arr); //Fatal error: Nesting level too deep - recursive dependency?
This field is for prevention and control Established to prevent infinite loops caused by circular references.
Looking at the above structure, we can see that for HashTable, the key element is arBuckets, which is the actual storage container. Let us take a look at its structure definition:
. The code is as follows:
typedef struct bucket {
ulong h; /* Numeric index/hash value*/
uint nKeyLength; /* Length of character index*/
void *pData; /* Data*/
void *pDataPtr ; /* Data pointer*/
struct bucket *pListNext; /* Next element, used for linear traversal*/
struct bucket *pListLast; /* Previous element, used for linear traversal*/
struct bucket *pNext; / * The next element in the same zipper */
struct bucket *pLast; /* The previous element in the same zipper */
char arKey[1]; /* Tips to save memory and facilitate initialization*/
} Bucket;
We noticed that the last element, this is a flexible array technique, which can save memory and facilitate initialization. Friends who are interested can google flexible array.
h is the Hash value of the element, for numerical indexing Element, h is the direct index value (numeric index represented by nKeyLength=0). For string index, the index value is stored in arKey, and the length of the index is stored in nKeyLength.
In the Bucket, the actual data It is stored in the memory block pointed to by the pData pointer. Usually this memory block is allocated separately by the system. But there is an exception, that is, when the data saved by the Bucket is a pointer, the HashTable will not request the system to allocate space to save the pointer, but directly save the pointer to pDataPtr, and then point pData to the member of this structure. the address of. This improves efficiency and reduces memory fragmentation. From this we can see the subtleties of PHP HashTable design. If the data in the Bucket is not a pointer, pDataPtr is NULL (this paragraph comes from Altair's "Zend HashTable Detailed Explanation")
The pListhHead of the HashTable points to the first element in the linear list form. In the above picture, it is element 1, and pListTail points to The last element is 0, and for each element pListNext is the next element of the linear structure drawn by the red line, and pListLast is the previous element.
pInternalPointer points to the position of the current internal pointer, when sequentially traversing the array , this pointer indicates the current element.
When linear (sequential) traversal is performed, it will start from pListHead, follow pListNext/pListLast in Bucket, and move pInternalPointer to achieve linear traversal of all elements.
For example, for foreach, if we look at the opcode sequence it generates, we can find that before foreach, there will first be a FE_RESET to reset the internal pointer of the array, which is pInternalPointer (for foreach, you can see In-depth Understanding of PHP Principles: foreach ), and then increment pInternalPointer each time FE_FETCH is used to achieve sequential traversal.
Similarly, when we use the each/next series of functions to traverse, we also achieve sequential traversal by moving the internal pointer of the array. Here is A question, for example:
. The code is as follows:
$arr = array(1,2,3,4,5);
foreach ($arr as $v) {
//Okay Get
}
while (list($key, $v) = each($arr)) {
//Cannot get
}
?>
Understanding the knowledge I just introduced, then this question It is very clear, because foreach will automatically reset, but the while block will not reset, so after foreach ends, pInternalPointer points to the end of the array, and of course the while statement block cannot be accessed. The solution is to reset before each. The internal pointer of the array.
During random access, the head pointer position in the hash array will be determined by the hash value, and then the characteristic element will be found through pNext/pLast.
When adding an element, the element will be inserted in The head of the same Hash element chain and the tail of the linear list. In other words, the elements are traversed according to the order of insertion during linear traversal. This special design makes it so that when using numerical indexes in PHP, the elements The order is determined by the order of addition, not the index order.
In other words, the order of traversing the array in PHP is related to the order of adding elements. So, now we clearly know that the beginning of the article The output of the problem is:
. The code is as follows:
huixinchen
2007
2008
So, if you want to iterate according to the index size in a numerically indexed array, then you should use for, not foreach
. The code is as follows:
for($i=0,$l=count($arr); $i<$l; $i++) {
//At this time, it cannot be considered as sequential traversal (linear traversal )
}
The above is an in-depth understanding of PHP arrays (traversal order). For more related articles, please pay attention to the PHP Chinese website (www.php.cn)!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

PHP and Python each have their own advantages, and choose according to project requirements. 1.PHP is suitable for web development, especially for rapid development and maintenance of websites. 2. Python is suitable for data science, machine learning and artificial intelligence, with concise syntax and suitable for beginners.

PHP is widely used in e-commerce, content management systems and API development. 1) E-commerce: used for shopping cart function and payment processing. 2) Content management system: used for dynamic content generation and user management. 3) API development: used for RESTful API development and API security. Through performance optimization and best practices, the efficiency and maintainability of PHP applications are improved.

PHP is still dynamic and still occupies an important position in the field of modern programming. 1) PHP's simplicity and powerful community support make it widely used in web development; 2) Its flexibility and stability make it outstanding in handling web forms, database operations and file processing; 3) PHP is constantly evolving and optimizing, suitable for beginners and experienced developers.

PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

PHP is suitable for web development, especially in rapid development and processing dynamic content, but is not good at data science and enterprise-level applications. Compared with Python, PHP has more advantages in web development, but is not as good as Python in the field of data science; compared with Java, PHP performs worse in enterprise-level applications, but is more flexible in web development; compared with JavaScript, PHP is more concise in back-end development, but is not as good as JavaScript in front-end development.

PHP and Python have their own advantages and disadvantages, and the choice depends on project needs and personal preferences. 1.PHP is suitable for rapid development and maintenance of large-scale web applications. 2. Python dominates the field of data science and machine learning.

PHP uses MySQLi and PDO extensions to interact in database operations and server-side logic processing, and processes server-side logic through functions such as session management. 1) Use MySQLi or PDO to connect to the database and execute SQL queries. 2) Handle HTTP requests and user status through session management and other functions. 3) Use transactions to ensure the atomicity of database operations. 4) Prevent SQL injection, use exception handling and closing connections for debugging. 5) Optimize performance through indexing and cache, write highly readable code and perform error handling.
