


[PHP source code reading]explode and implode functions, explodeimplode_PHP tutorial
[PHP source code reading]explode and implode functions,explodeimplode
explode and implode functions are mainly used for string-array operations, such as obtaining a parameter and splitting it according to a certain character String, or combine the results of an array into a string output using one character. These two functions are often used in PHP, so it is necessary to understand their principles.
explode
<p>array explode ( string $delimiter, string $string, [ , $limit ] )</p>
Returns an array composed of strings. Each element is a substring of string, separated by the string $delimiter as a boundary point.
$limit
If $limit is set and is a positive number, the returned array contains at most $limit elements, and the last element will contain the remainder of $string.
If $limit is a negative number, return all elements except the last -$limit elements.
If $limit is 0, it will be treated as 1.
$delimiter
If $delimiter is empty, the function returns FALSE. If delimiter is not in string and $limit is a negative number, an empty array is returned.
Core source code
<span>//</span><span> 如果delimiter为空字符串,返回FALSE</span> <span>if</span> (delim_len == <span>0</span><span>) { php_error_docref(NULL TSRMLS_CC, E_WARNING, </span><span>"</span><span>Empty delimiter</span><span>"</span><span>); RETURN_FALSE; } </span><span>//</span><span> 初始化返回的数组</span> <span> array_init(return_value); </span><span>if</span> (str_len == <span>0</span><span>) { </span><span>if</span> (limit >= <span>0</span><span>) { </span><span>//</span><span> 如果字符串为空且limit大于等于0,则返回一个包含空字符串的数组,注意此处sizeof("") == 1</span> add_next_index_stringl(return_value, <span>""</span>, <span>sizeof</span>(<span>""</span>) - <span>1</span>, <span>1</span><span>); } </span><span>return</span><span>; } </span><span>//</span><span> 初始化zstr和zdelim的字符串变量</span> ZVAL_STRINGL(&zstr, str, str_len, <span>0</span><span>); ZVAL_STRINGL(</span>&zdelim, delim, delim_len, <span>0</span><span>); </span><span>if</span> (limit > <span>1</span><span>) { </span><span>//</span><span> limit大于1,limit默认是LONG_MAX</span> php_explode(&zdelim, &<span>zstr, return_value, limit); } </span><span>else</span> <span>if</span> (limit < <span>0</span><span>) { </span><span>//</span><span> limit 为负数</span> php_explode_negative_limit(&zdelim, &<span>zstr, return_value, limit); } </span><span>else</span><span> { </span><span>//</span><span> limit为0,被当作1处理,返回整个字符串,add_index_stringl函数将str追加到数组return_value中</span> add_index_stringl(return_value, <span>0</span>, str, str_len, <span>1</span><span>); }</span>
After handling special situations and initializing variables, call the php_explode/php_explode_negative_limit function for the next step. The following is the source code of the php_explode function
php_explode
<span> endp </span>= Z_STRVAL_P(str) +<span> Z_STRLEN_P(str); </span><span>//</span><span> p1指向字符串的开始</span> p1 =<span> Z_STRVAL_P(str); </span><span>//</span><span> p2指向第一个分隔符的位置 ,找出分隔符位置主要用的是php_memnstr函数</span> p2 =<span> php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp); </span><span>if</span> (p2 ==<span> NULL) { </span><span>//</span><span> p2为NULL表示找不到分隔符,直接返回整个字符串</span> add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), <span>1</span><span>); } </span><span>else</span><span> { </span><span>do</span><span> { </span><span>//</span><span> 将p1添加到return_value数组中 ,移动到下一个分隔符的位置</span> add_next_index_stringl(return_value, p1, p2 - p1, <span>1</span><span>); p1 </span>= p2 +<span> Z_STRLEN_P(delim); } </span><span>while</span> ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL && --limit > <span>1</span><span>); </span><span>//</span><span> 将最后一个值追加到return_value</span> <span>if</span> (p1 <=<span> endp) add_next_index_stringl(return_value, p1, endp</span>-p1, <span>1</span><span>); }</span>
In implementation, add_next_index_stringl is called to add each string obtained to the array return_value. add_next_index_string is the core function of this function.
ZEND_API <span>int</span> add_next_index_stringl(zval *arg, <span>const</span> <span>char</span> *str, <span>uint</span> length, <span>int</span><span> duplicate) { zval </span>*<span>tmp; MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); </span><span>return</span> zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, <span>sizeof</span>(zval *<span>), NULL); }</span>The
add_next_index_stringl function calls the zend_hash_next_index_insert function to insert str into the array. Let’s take a look at the source code of the php_explode_negative_limit function
php_explode_negative_limit
<span> //</span><span> 如果delimiter不在string中,且limit为负数,什么都不做,返回空的array,p2为NULL表示delimiter不在string中</span> <span>if</span> (p2 ==<span> NULL) { </span><span>/*<br /> 如果limit <= -1,那么什么都不做,因此如果只有一个字符串,那么- 1 + (limit) <= 0<br /> 返回空数组</span><span>*/</span><span> } </span><span>else</span><span> { </span><span>int</span> allocated = EXPLODE_ALLOC_STEP, found = <span>0</span><span>; </span><span>long</span><span> i, to_return; </span><span>char</span> **positions = emalloc(allocated * <span>sizeof</span>(<span>char</span> *<span>)); </span><span>//</span><span> 第一个单词的位置</span> positions[found++] =<span> p1; </span><span>do</span><span> { </span><span>if</span> (found >=<span> allocated) { allocated </span>= found + EXPLODE_ALLOC_STEP;<span>/*</span><span> 保证有足够的内存空间 </span><span>*/</span><span> positions </span>= erealloc(positions, allocated*<span>sizeof</span>(<span>char</span> *<span>)); } </span><span>//</span><span> positions保存每个单词的起始位置</span> positions[found++] = p1 = p2 +<span> Z_STRLEN_P(delim); } </span><span>while</span> ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) !=<span> NULL); </span><span>//</span><span> to_return 是return_value的数量,其实等于found - |limit|</span> to_return = limit +<span> found; </span><span>/*</span><span> limit至少是-1,因此不需要边界检查:i永远小于found </span><span>*/</span> <span>for</span> (i = <span>0</span>;i < to_return;i++) { <span>/*</span><span> 这个检查是检查to_return大于0 </span><span>*/</span><span> add_next_index_stringl(return_value, positions[i], (positions[i</span>+<span>1</span>] - Z_STRLEN_P(delim)) -<span> positions[i], </span><span>1</span><span> ); } efree(positions); }</span>
php_explode_negative_limit is also a similar operation to php_implode. After finding the separated strings, call the add_next_index_string function to add the limit found strings to the return_value array.
implode
<p>string implode ( string $glue, array $pieces )</p> <p>string implode ( array $pieces )</p>
Convert the value of a one-dimensional array to a string
The implode function can receive two parameter orders.
Core Code
<span>if</span> (arg2 ==<span> NULL) { </span><span>//</span><span> 第二个参数为空,第一个参数必须为数组</span> <span>if</span> (Z_TYPE_PP(arg1) !=<span> IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, </span><span>"</span><span>Argument must be an array</span><span>"</span><span>); </span><span>return</span><span>; } MAKE_STD_ZVAL(delim); </span><span>#define</span> _IMPL_EMPTY "" <span>//</span><span> 默认使用""连接</span> ZVAL_STRINGL(delim, _IMPL_EMPTY, <span>sizeof</span>(_IMPL_EMPTY) - <span>1</span>, <span>0</span><span>); SEPARATE_ZVAL(arg1); arr </span>= *<span>arg1; } </span><span>else</span><span> { </span><span>//</span><span> 根据参数类型设置参数的值</span> <span>if</span> (Z_TYPE_PP(arg1) ==<span> IS_ARRAY) { arr </span>= *<span>arg1; convert_to_string_ex(arg2); delim </span>= *<span>arg2; } </span><span>else</span> <span>if</span> (Z_TYPE_PP(arg2) ==<span> IS_ARRAY) { arr </span>= *<span>arg2; convert_to_string_ex(arg1); delim </span>= *<span>arg1; } </span><span>else</span><span> { php_error_docref(NULL TSRMLS_CC, E_WARNING, </span><span>"</span><span>Invalid arguments passed</span><span>"</span><span>); </span><span>return</span><span>; } } </span><span>//</span><span> 调用php_implode函数进行转换</span> php_implode(delim, arr, return_value TSRMLS_CC);
In the underlying implementation, after the implode function processes the parameters, it calls the php_implode function for conversion.
php_implode
<span> //</span><span> 遍历数组的每一个元素,判断其类型,然后调用smart_str_appendl函数将值追加到字符串中</span> <span>while</span> (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (<span>void</span> **) &tmp, &pos) ==<span> SUCCESS) { </span><span>switch</span> ((*tmp)-><span>type) { </span><span>case</span><span> IS_STRING: smart_str_appendl(</span>&<span>implstr, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); </span><span>break</span><span>; </span><span>case</span><span> IS_LONG: { </span><span>char</span> stmp[MAX_LENGTH_OF_LONG + <span>1</span><span>]; str_len </span>= slprintf(stmp, <span>sizeof</span>(stmp), <span>"</span><span>%ld</span><span>"</span><span>, Z_LVAL_PP(tmp)); smart_str_appendl(</span>&<span>implstr, stmp, str_len); } </span><span>break</span><span>; </span><span>case</span><span> IS_BOOL: </span><span>if</span> (Z_LVAL_PP(tmp) == <span>1</span><span>) { smart_str_appendl(</span>&implstr, <span>"</span><span>1</span><span>"</span>, <span>sizeof</span>(<span>"</span><span>1</span><span>"</span>)-<span>1</span><span>); } </span><span>break</span><span>; </span><span>case</span><span> IS_NULL: </span><span>break</span><span>; </span><span>case</span><span> IS_DOUBLE: { </span><span>char</span> *<span>stmp; str_len </span>= spprintf(&stmp, <span>0</span>, <span>"</span><span>%.*G</span><span>"</span>, (<span>int</span><span>) EG(precision), Z_DVAL_PP(tmp)); smart_str_appendl(</span>&<span>implstr, stmp, str_len); efree(stmp); } </span><span>break</span><span>; </span><span>case</span><span> IS_OBJECT: { </span><span>int</span><span> copy; zval expr; zend_make_printable_zval(</span>*tmp, &expr, &<span>copy); smart_str_appendl(</span>&<span>implstr, Z_STRVAL(expr), Z_STRLEN(expr)); </span><span>if</span><span> (copy) { zval_dtor(</span>&<span>expr); } } </span><span>break</span><span>; </span><span>default</span><span>: tmp_val </span>= **<span>tmp; zval_copy_ctor(</span>&<span>tmp_val); convert_to_string(</span>&<span>tmp_val); smart_str_appendl(</span>&<span>implstr, Z_STRVAL(tmp_val), Z_STRLEN(tmp_val)); zval_dtor(</span>&<span>tmp_val); </span><span>break</span><span>; } </span><span>//</span><span> 添加glue字符</span> <span>if</span> (++i !=<span> numelems) { smart_str_appendl(</span>&<span>implstr, Z_STRVAL_P(delim), Z_STRLEN_P(delim)); } zend_hash_move_forward_ex(Z_ARRVAL_P(arr), </span>&<span>pos); } </span><span>//</span><span> 在尾部添加字符0</span> smart_str_0(&implstr);
As you can see, the php_implode function traverses each element of the array, determines its type, performs necessary type conversion, and then calls the smart_str_appendl function to append the value to the string. smart_str_appendl is the core function in the implode implementation code.
smart_str_appendl
<span>#define</span> smart_str_appendl(dest, src, len) \<span> smart_str_appendl_ex((dest), (src), (len), </span><span>0</span><span>) </span><span>#define</span> smart_str_appendl_ex(dest, src, nlen, what) do { \<span> register size_t __nl; \ smart_str </span>*__dest = (smart_str *<span>) (dest); \ \ smart_str_alloc4(__dest, (nlen), (what), __nl); \ memcpy(__dest</span>->c + __dest-><span>len, (src), (nlen)); \ __dest</span>->len =<span> __nl; \ } </span><span>while</span> (<span>0</span>)
smart_str_appendl_ex mainly calls the memcpy function to copy strings.
Original article with limited writing style and limited knowledge. If there is anything wrong in the article, please let me know.
If this article is helpful to you, please give it a recommendation, thank you^_^.
More PHP source code reading articles:
[PHP source code reading]strlen function
[PHP source code reading] strpos, strstr and stripos, stristr functions

TomakePHPapplicationsfaster,followthesesteps:1)UseOpcodeCachinglikeOPcachetostoreprecompiledscriptbytecode.2)MinimizeDatabaseQueriesbyusingquerycachingandefficientindexing.3)LeveragePHP7 Featuresforbettercodeefficiency.4)ImplementCachingStrategiessuc

ToimprovePHPapplicationspeed,followthesesteps:1)EnableopcodecachingwithAPCutoreducescriptexecutiontime.2)ImplementdatabasequerycachingusingPDOtominimizedatabasehits.3)UseHTTP/2tomultiplexrequestsandreduceconnectionoverhead.4)Limitsessionusagebyclosin

Dependency injection (DI) significantly improves the testability of PHP code by explicitly transitive dependencies. 1) DI decoupling classes and specific implementations make testing and maintenance more flexible. 2) Among the three types, the constructor injects explicit expression dependencies to keep the state consistent. 3) Use DI containers to manage complex dependencies to improve code quality and development efficiency.

DatabasequeryoptimizationinPHPinvolvesseveralstrategiestoenhanceperformance.1)Selectonlynecessarycolumnstoreducedatatransfer.2)Useindexingtospeedupdataretrieval.3)Implementquerycachingtostoreresultsoffrequentqueries.4)Utilizepreparedstatementsforeffi

PHPisusedforsendingemailsduetoitsbuilt-inmail()functionandsupportivelibrarieslikePHPMailerandSwiftMailer.1)Usethemail()functionforbasicemails,butithaslimitations.2)EmployPHPMailerforadvancedfeatureslikeHTMLemailsandattachments.3)Improvedeliverability

PHP performance bottlenecks can be solved through the following steps: 1) Use Xdebug or Blackfire for performance analysis to find out the problem; 2) Optimize database queries and use caches, such as APCu; 3) Use efficient functions such as array_filter to optimize array operations; 4) Configure OPcache for bytecode cache; 5) Optimize the front-end, such as reducing HTTP requests and optimizing pictures; 6) Continuously monitor and optimize performance. Through these methods, the performance of PHP applications can be significantly improved.

DependencyInjection(DI)inPHPisadesignpatternthatmanagesandreducesclassdependencies,enhancingcodemodularity,testability,andmaintainability.Itallowspassingdependencieslikedatabaseconnectionstoclassesasparameters,facilitatingeasiertestingandscalability.

CachingimprovesPHPperformancebystoringresultsofcomputationsorqueriesforquickretrieval,reducingserverloadandenhancingresponsetimes.Effectivestrategiesinclude:1)Opcodecaching,whichstorescompiledPHPscriptsinmemorytoskipcompilation;2)DatacachingusingMemc


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

SublimeText3 English version
Recommended: Win version, supports code prompts!

Zend Studio 13.0.1
Powerful PHP integrated development environment

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft
