Tag: internal

  • How To Create Custom Table List In WordPress Admin Page

    Introduction

    1. In this tutorial, you will learn how to add an admin table which is similar to admin posts or pages or comments table list
    2. Our table list is a merged list of all searchable post types post which are in draft mode i.e. not yet published or still work in progress posts
    3. Based on this tutorial you will learn how to implement the following features
      1. Search box
      2. Filter dropdown (Post type)
      3. Bulk action (Trash multiple posts at a time)
      4. Action quick links (Each post have edit, trash & view)
      5. Pagination
    4. Our custom table is a child class of the official table class: WP_List_Table
    5. We will explore each and every method in its individual section
    6. GitHub link to directly activate as a plugin while learn/play with the source
    Sample Admin Table

    Complete Source Code

    Include Base Class

    1. In the complete source code gist (from now onwards we call it as main gist/file), you can find that we included our base class at line no: 24 though most of the time the class Drafts_List_Table directly extend the class WP_List_Table without the include once but WordPress functioning based on hooking process so sometimes our class may be called before hooked and globally included the WP_List_Table therefore it’s always better to check if it’s included or not and included the class file
    2. Also instead of hopping here and there, we can add the snippet which is related to the current context so we include partial code gist like this

    Extend Base Class

    1. We extend our table class Drafts_List_Table from core WordPress class WP_List_Table at line no: 35 like this

    Class Constant & Property

    1. The class Drafts_List_Table have one constant POSTS_PER_PAGE and one private property $allowed_post_types (main source code line no: 40)
    2. The POSTS_PER_PAGE is to stores an integer value which is the number of maximum posts to be shown in the table per page
    3. The property $allowed_post_types have an array of post types that can be queried and used to list out all posts that come under these post types

    Constructor

    1. Our constructor (main source code line no: 52) is not that much fancy it has two simple statement one is a parent constructor call with three arguments singular, plural both for labeling purpose and ajax accepts boolean to decide whether HTTP calls are ajax based or not
    2. The other one calls the class method allowed_post_types() and stores the return value in the private property allowed_post_types

    Get Allowed Post Types

    1. This method is placed inside this class is for tutorial purpose only (but for the real-life project, my suggestion is to create a utility or helper module which may have more helper classes like one for UI works, another API services, and other for wrapping commonly used DB queries likewise we can build n-number of classes for different common purposes)
    1. Let’s place the architectural suggestions aside and focus on this tutorial, the method allowed_post_types ( main source code line no: 71 ) will return the post types in the array
    2. Line no 9: by using WP core function get_post_types we fetch the post types in our web application here we pass an argument public with the boolean value true therefore it returns only publicly accessible post types
    3. Visit documentation for more details about the function get_post_types
    4. We unset the attachment post type to exclude that kind of posts from the table list and finally returned the remaining post type as an array

    Convert Slug String To Human Readable

    1. Yes, this method (main source code line no: 85) also another good candidate for the utility method
    2. This method converts the slug to readable format i.e. it replaces all underscore symbol with white space and title cased the words

    Convert Post Types Human Readable

    1. The method allowed_post_types_readable (main source code line no: 94) is iterate on all allowed post type and convert the post type’s slug into human-readable
    2. The inner working of this method is using the PHP function array_map we pass our human_readable as a callback that applies on each value of the private array property allowed_post_types
    3. The newly generated array is assigned to the variable $formatted and the same is returned

    Create Custom WP_Query Object

    1. This method get_posts_object (main source code line no: 108) is the data fetching method of this custom admin table class
    1. As this method is a little lengthier let’s try to refer to each statement using its gist line number for easier understanding, here all the line numbers pointing to the gist get_posts_object.php
    2. Line no 9: fetching private array property allowed_post_types then assign it to the method’s local variable $post_types
    3. Line no 11: we declare a local variable $post_args which holds initial argument we pass to the WP_Query instance constructor call
    4. The $post_args is an associative array with the following key-value pair
      1. The key post_type holds the array of post types
      2. The key post_status holds the array of statuses to fetch here we pass only one value i.e. draft
      3. The key posts_per_page holds the integer value which controls how many posts to show on the page
    5. Line no 17: the local variable $paged is fetch page number from query string by using the PHP function filter_input to validate if it’s an integer or not using the filter id FILTER_VALIDATE_INT
    6. Line no 19: if the variable $paged having truth value then assign the value stored in $paged to $post_args array key paged
    7. Line no 23: the local variable $post_type is fetching post type (which we can use to filter the table to show only specific post type posts only) from query string by using the PHP function filter_input, sanitized the incoming string using the id FILTER_SANITIZE_STRING
    8. Line no 25: if the variable $post_type having truth value then assign the value stored in $post_type to $post_args array key post_type
    9. Line no 29: the variable $orderby accepts the table column name, as the value get from the query string it’s good to sanitize it
    10. WordPress provided a sanitize function sanitize_sql_orderby which is specifically deal with the order by clause with or without sort order
    11. Using the sanitize_sql_orderby function we sanitized the column name
    12. Line no 30: the filtered query string order’s value is passed to WordPress function esc_sql for escaping if any SQL injection character present
    13. Don’t accept user’s data blankly always do escaping, sanitization, and validation (skip sub-points if you need)
      1. Four years back got a chance to audit a project, the theme is adding a music file name and it’s CDN path to DB in the insert query without escaping or doing some other alternative like a prepared statement or PDO the source code inserts the file name
      2. When sending back the review to the concerned team they asked “why we need to escape? it’s just a filename of an MP3 file”
      3. I replied that we need to escape the filename because various bands have an apostrophe in their band name like Guns N' Roses therefore please escape the user input
      4. Thank god the application is Indian based music and running happily without unintentional SQL injection by the web application user because most of the Indian name or band name doesn’t have an apostrophe
      5. But the piece of advice is, in order to break your web application no need to hire a hacker just make it famous, and more user using it you will get to know why I’m insisting this
    14. Line no 32: if the variable $orderby is empty then set a default value date, then our posts are sorted by the date column
    15. Line no 36: if the variable $order is empty then set a default value desc, then our posts are sorted in descending order i.e. reverse chronological order
    16. Line no 40: assigning the order by value into the variable $post_args associative index orderby which we pass an argument to the WP_Query class first parameter
    17. Line no 41: this statement also similar to the previous one at line no 40
    18. Line no 43: in the variable $search fetching the query string s and passed it to the esc_sql function, this query string s only available when the user did a search
    19. Line no 44: as said in the previous point the s available only on search therefore before assigning we doing a conditional check to verify it’s not empty
    20. Line no 45: once the not empty condition passed we assign the search value into the associative index s of the variable $post_args
    21. Line no 48: finally we pass the $post_orgs to the class WP_Query and return the query class object

    No Items Text Display

    1. The method no_items is overridden method of the base class WP_List_Table
    2. The purpose of this method is to display the information when no posts are available
    3. Line no 7: displaying the message about no posts which properly escaped for HTML and can be translated by using the WordPress function esc_html_e

    Display Default Column

    1. Line no 10: the overridden method column_default is used to handle the column output
    2. Internally this method is called for each column this method accepts two parameters
      1. $item have all the current row’s columns values in associative key-value pair
      2. $column_name current column name
    3. Line no 11: declared and initialized the variable $result with empty string which we use to assign the column data to be shown
    4. Line no 12: switch statement will switch and create the column value based on the passed column name
      1. Line no 13: the date case is used to display date in two variant either by date if the post created date is more than one day else returns how human saying the date for e.g. 10 minutes ago
      2. Line no 14: using the WordPress template function get_the_time retrieve the post created time with formatting, get_the_time to learn more
      3. Line no 15: the function get_post_timestamp is used to retrieve the draft post published time in unix timestamp format, get_post_timestamp to learn more
      4. Line no 16: took the seconds difference of current unix timestamp (using PHP function time) and post created time and assign it to the variable $time_diff
      5. Line no 18: we’re checking the time is less than a day if so then display the time in human readable format using the WordPress formatting function human_time_diff
      6. Line no 22: else will show the date in the format Y/m/d
      7. The remaining cases ( author and type) are self explanatory
    5. Line no 37: return the variable $result which have the value to show in the specific column

    Display Table Header

    1. The method get_columns ( main source code line no: 200 ) is an inherited must overridden method which is responsible for displaying the table headers
    2. For a quick view please see the snippet of the main source below
    1. This method simply returns the array of key-value pair of columns which have a set of an internal name as key and it’s display value as the value

    Title Column Callback

    1. The method column_title (main source code Line no: 216) is used to display the HTML in the table column Title
    2. Internally this method is called by the parent method single_row_columns elseif is called the column_title method dynamically using the callback logic
    1. Line no 10: using the WordPress function get_edit_post_link we fetch the edit link for the current post in the table row looping flow
    2. Line no 11: get_permalink is used to fetch the current post permalink
    3. Line no 12: get_delete_post_link is used to fetch the delete link of the current post
    4. Line no 14 – 36: is simple HTML generation to display in the Title column by returning the variable $output, in these statements, the only thing we need to focus on is a template function _post_states
    5. The function _post_states is used to display post states as HTML for e.g. in the Introduction section if you see the sample image there are two things displayed in post states Draft, Elementor
    6. The state Draft is fetched by core WordPress whereas Elementor fetched by Elementor plugin to notate this post is formed by Elementor page builder

    Column Checkbox

    1. The method column_cb (main source code line no: 251) is a simple method to display a checkbox in each row to select the post for bulk action like trashing an unneeded post

    Build Table Data

    1. The method prepare_items (main source code line no: 264) is the core part to create the data for the table note here I’m saying about an array of information to show on the table, not the HTML design part
    1. Line no 9: called the method get_columns to fetch an array of column names to be shown in the header of the table
    2. Line no 10: called the method get_sortable_columns to fetch an array of sortable data in the format of an internal name as key and sorting option as a value such as array( column_internal_name, sorting_type) and assign it to the variable $sortable (don’t worry we will see more detail when we explain this method we will see the detailed way)
    3. Line no 13: the parent class property _column_headers accepts an array of arrays as in this order first array of columns to be shown in the table, second an array of columns which are hidden one, third array of sortable columns, fourth a string denote which column is primary one
    4. Line no 16: called the method process_bulk_action which is responsible for bulk actions like trashing the posts
    5. Line no 18: called the method get_posts_object which return the WP_Query instance with whatever filters and sorting options are applied, that instance is assigned to the variable $get_posts_obj
    6. Line no 20: check if the queried WP_Query instance have posts object using the method $get_posts_obj->have_posts()
    7. Line no 22: if posts are available then begin the looping while ( $get_posts_obj->have_posts() )
    8. Line no 24: the WP_Query method the_post is used to retrieve the next post internally which sets WP_Query property in_the_loop to true and retrieves the next post
    9. Line no 26: form the array of data therefore each index have an array of values to show in each row of the table, the formation of this array mostly using WordPress template functions
    10. Line no 34: the function wp_reset_postdata is used to reset the global variable $post to the main query’s current post after completing our custom query loop
    11. Line no 37: Assign our looped collection of table data to the parent class WP_List_Table property items therefore other methods that require data can access from this property
    12. Line no 39: the parent class method set_pagination_args is responsible to set pagination related information to the parent class property _pagination_args here we basically set up our pagination using three items
      1. total_items we pass the WP_Query property found_posts
      2. per_page we pass the WP_Query property post_count
      3. total_pages we pass the WP_Query property max_num_pages

    Create Bulk Action Dropdown

    1. This method (main source code line no: 309) return array of key-value pairs which is used to show in the bulk action dropdown (if you like to know how the HTML formed by retrieving the return value of this method then please check bulk_actions method of the parent class WP_List_Table)

    Process Bulk Actions

    1. This method process_bulk_action (main source code line no: 320) is used to do bulk actions like trashing the post likewise you can change the state of many posts (for e.g. change the set of posts from draft to publish) or process many posts data altogether (for e.g. trigger email to multi-selected users and change the custom state pending to invited)
    1. Line no 9: in the conditional statement, we check whether the current action is trash if so then execute the inner block
    2. Line no 10: the variable $post_ids hold get query value draft_id which is a collection of ids of the posts that need to be trashed
    3. Line no 12: verify is the variable $post_ids is an array
    4. Line no 13: convert all elements in the array into an integer value the reason is we received it from the get query therefore it will be a string and sometimes may have illegitimate data if the user intentionally add some junk data, here we iterated over each element using array_map
    5. Line no 15: we check this in if condition to confirm at least one element present in the $post_ids array
    6. Line no 16: pass all the ids to the WordPress function wp_trash_post which will trash the posts

    Display Actions, Filters, and Pagination

    1. The method display_tablenav (main source code LINE NO: 341) is an overridden method that is responsible for displaying bulk actions, filters dropdown, and pagination which accepts a single argument with a value of either top or bottom based on that display the block of HTML at the top or bottom of the table
    1. Line no 12: created the navigation wrapper div with a dynamic class top or bottom based on the argument $which value
    2. Line no 14: verify is the table has items to display
    3. Line no 16: if has items then display the bulk action dropdown
    4. Line no 20: the method extra_tablenav is used to display additional filter we will see more detail about this method in the next section
    5. Line no 21: the method pagination is the parent class method that handles the pagination of the table

    Extra Table Navigation HTML

    1. The method extra_tablenav (main source code line no: 367) is used to display additional filter controls here using the argument $which we controlled our filter to display only at the top of the table
    1. Line no 12: conditionally show our filter only at the top by checking the $which argument value is equal to top
    2. Line no 13: create a multidimensional associative array $drafts_dropdown_arg which we pass to the method html_dropdown we will see more about this method in the next section
    3. In the variable $drafts_dropdown_arg the options index has the value to show in the dropdown
    4. The container index has the class name to add to the dropdown component’s container div
    5. The next two indexes label and select represents its tag name, and it holds attributes of that tag in the inner array as key-value pair
    6. Line no 31: using the WordPress function submit_button echoes our submit button

    UI Helper HTML Dropdown

    1. The method html_dropdown (main source code line no: 399) is used to generate HTML dropdown dynamically which is wrapped inside container div also to be clear this method needs to be added to the utility class Helper therefore the same method can be used in many other places too but for this tutorial, I added this inside the same class
    1. This method is simple string interpolation of passed argument into the custom HTML it’s pretty easy to understand, and I believe there is no need for a very detailed explanation

    Sortable Column

    1. The method get_sortable_columns (main source code line no: 434) is an overridden method that simply returns an associative array
    1. Line no 11: the key is the column internal name and the value is an array that represents the behavior of the sorting
    2. Here we followed the format 'internal-name' => array( 'column', 'is_descending')
    3. The boolean false is no need to pass explicitly (see implementation logic) but for clarity here I passed instead of that if you alter it to true means on initial page load that column will be sorted in descending order

    Column CSS

    1. This anonymous function (main source code line no: 448) inject custom HTML in the header part because we used the admin_head tag (this snippet only load in the admin part, not for the user-facing frontend pages if you would like to load on frontend then use the tag wp_head)
    1. Line no 9: fetch the current page name from the global get query string
    2. Line no 10: check the page name is not equal to all-drafts then bypass the upcoming execution by executing the void return statement
    3. Line no 15: add CSS width property to the column type i.e. post type column therefore which will give more space or real-estate to the column Title

    Admin Menu For Drafts Table

    1. Using the hook admin_menu (main source code line no: 465) we hooked our drafts table admin page
    1. add_menu_page for more details about each argument and its purpose

    Instantiate Draft Table

    1. The function bootload_drafts_table (main source code line no: 483) is a callback function attached to the add_menu_page, we pass this as a second from the last argument
    1. Line no 7: instantiate custom admin table class Drafts_List_Table
    2. Line no 12: pass draft table page menu slug all-drafts as hidden value therefore whenever the user does a submit action like searching, after every new request the filtered table is shown at the right page
    3. Line no 15: the method prepare_items is the workhorse of this class which handles all table data generation and processing logic
    4. Line no 16: search_box is the overridden method that accepts two parameters are a label of the submit button and an HTML id attribute for the search input field here we pass the first argument i.e. label as Search and the second argument i.e. id as search
    5. Line no 17: display is a parent class method that is responsible for displaying or echoing the HTML table with dynamic data, actions, filters, and pagination

    Conclusion

    1. Through this tutorial, you learned how we can create a custom admin table on WordPress
    2. Simultaneously using this knowledge you understand how WordPress posts, pages, and comments table are formed
    3. Not only WordPress core many plugins like WooCommerce, SEO by Rank Math, and many other plugins more or less follow the same procedure therefore it’s easy for you to understand their admin table source
    4. By learning this tutorial now you’re comfortable with WordPress core class WP_List_Table

  • Inside the PHP

    Introduction

    1. Ever wonder what’s inside the PHP. How every language construct, function works.
    2. How optional parameters handled. Why certain functions behave weird and want know their inner working.
    3. That’s why I bring this tutorial to how easily navigate to the function declaration and understand it easily.
    4. Since PHP is opensource you can see all source code easily in github (clone of official git repository) but quickly finding the desired function in github is cumbersome but don’t worry we will find some alternative solution in this tutorial
    5. The PHP compiler/interpreter which is written in C and C++ which uses Lexical analyser, Yacc (Yet another compiler compiler), configurator to identify computer hardware and operating system finally virtual machine such as zend virtual machine shortly ZVM which runs our code

    Lets Explore Directory Structure and Pattern

    1. Most of the PHP source which is in C language looks very similar to PHP so understanding the code won’t be difficult.
    2. If the official documentation is more abstract you can get this procedure as a handy tool to understand the function very well.
    3. To explore the PHP source we are going to use Adam Harvey‘s PHP source browser. Lexer link: https://php-lxr.adamharvey.name/source/
    4. The PHP lexer’s home page have a search form in the left and source selection box in the right for simplification going to select php-7.3 in selection box.
    5. In selection box please double click the php-7.3 to goto the source listing.
    6. In the directory listing you will find some important directory like ext which contains core functions with the function’s name as sub-directories name, main comprises memory allocation code, directory scanning code, etc., Zend is the zend engine code which contains compiler, language features and VM (Virtual Machine).
    7. As you explored the ext and Zend directory it’s clear that in official documentation items which are found under “Language Reference” are related to zend directory and “Function Reference” are related to ext directory.
    8. Let’s we go into the Zend directory’s file zend_builtin_functions.c please click here which will redirect you to function lists in that c file.
    9. As you note down the code, you will see list of very familiar functions like zend_version, func_num_args, strlen, property_exists, class_exists, etc.,
    10. To dive deep into the internal code understanding process we chosen the string function explode.
    11. Here is the explode documentation link: explode()

    Explode() overview

    1. The function explode supports PHP 4, 5, 7 (Newbie Hint: There is no PHP 6 because core team planned to release PHP 6 long back with unicode support but not released. So to avoid confusion and marketing advantage PHP 7 is released after PHP 5).
    2. Explode function has two required parameters and one optional parameter totally three parameters.
    3. It return either boolean false or Array.
    4. From version 5.1.0 negative limit also supported.
    5. For more details about this function please review official document which is linked in last point of the previous section.
    6. Let’s we move to the internal working of this function.

    Search using LXR utility

    1. Go to the lexer home page. Link: https://php-lxr.adamharvey.name/source/
    2. In HTML form’s first field (Field Label: Full Search) type explode and click the button Search.
    3. It will show many matched results to narrow down we have to change the search term to "PHP_FUNCTION explode". Note: must enclose search term with double quotes.
    4. The search result lists the two files php_string.h and string.c
    5. The file php_string.h is similar to interface/ abstract class for a complete class. The file extension h denotes it’s a header file for main c file.
    6. Lets move on to our main objective file string.c by clicking the line number in the search result it will redirect us to the explode function’s declaration. Link: Line no: 1155.

    Explode() internal function call chain

    1. Explode function declaration starts with PHP_FUNCTION(explode) on line 1155.
    2. The declaration is enclosed inside between the markers {{{ and }}}. Note: Scroll up to see the marker.
    3. We can easily identify where the function declaration starts and ends using this markers.
    4. Here the PHP_FUNCTION is not a c inbuilt syntax it’s a C macro.
    5. The macro always start with #define
    6. So we will search in the lxr home page with search term "#define PHP_FUNCTION" or directly click here
    7. Once searched, the search list have the file name php.h in that click the line number 409
    8. In redirected source code page you will find that #define PHP_FUNCTION is points to other macro ZEND_FUNCTION
    9. Even though the hyperlink on ZEND_FUNCTION redirects you to the search form with filtered list it shows more records
    10. We will use alternative search term to filter more accurately for our need
    11. Once we used "#define ZEND_FUNCTION" as search term the utility page will list a file: zend_API.h in that list click the line number 64 or click here to redirect directly
    12. click here to redirect to lxr utility with search term
    13. The zend_API.h file’s line number 64 contains the following code
      #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
    14. As you noted the 64th line have another two macros ZEND_NAMED_FUNCTION and ZEND_FN
    15. Lets we see inner function ZEND_FN
    16. In lxr search form add this search term "#define ZEND_FN" in full search field and click the search button or click here to go directly
    17. In result list you will find a file name zend_API.h with line no 61, please click the line number or click here to redirect
    18. Which have the following code #define ZEND_FN(name) zif_##name (in C the operator ## is for concatenation and it is called as token concatenation operator so it will return the concated string zif_explode)
    19. The ZEND_FN is passed as argument to the macro function ZEND_NAMED_FUNCTION
    20. In lxr search form add this search term "#define ZEND_NAMED_FUNCTION" in full search field and click the search button or click here to go directly
    21. It contains the following code #define ZEND_NAMED_FUNCTION(name) void ZEND_FASTCALL name(INTERNAL_FUNCTION_PARAMETERS)
    22. The function ZEND_FASTCALL will be interpreted as void ZEND_FASTCALL zif_explode(INTERNAL_FUNCTION_PARAMETERS)
    23. If we search for "#define ZEND_FASTCALL" it shows a list of search results in that click the first one’s line number or click here to go directly
    24. After redirected scroll up little and you will see the full block of C preprocessor conditional block
    25. This block is set of conditional call to choose the type of compiler as we know for windows, linux and other supported OS the compiler will be different
    26. Lets we arrange functions chain as a sequence block for easy mind map have a look on it
      PHP_FUNCTION(explode)ZEND_FUNCTION(explode)ZEND_NAMED_FUNCTION(ZEND_FN(explode))ZEND_NAMED_FUNCTION((zif_##explode))
    27. Readers thanks for your patience to follow the flow
    28. The reason to see the above steps before your eagerly expected internal flow of explode or name any core function is to understand that the PHP execute the core function in some better optimised way than the standard userland functions
    29. So our explode function starts the journey from PHP_FUNCTION(explode) to optimised call zif_explode

    Explode() function definition in C language

    1. As in previous section the explode code starts at the line number 1153 with the markup {{{ and ends at the line number 1192 with the markup }}}
    2. Line 1155 : is the macro call and that call itself has a separate section which is explained in the previous section
    3. The lines 11571159: are the C local variables and some of the variables are used for arguments we passed in explode function’s parameters
    4. The lines 11611166: are used to copy the runtime input parameters to the local variables
      1. Line 1161: is a macro call ZEND_PARSE_PARAMETERS_START(2, 3) this function is used to initiate the process of copying runtime value into the local variable which defined just above this macro call
      2. This function has two parameters the first one for number of mandatory parameters and the second one is total number of parameters
      3. Line 1162: is macro function Z_PARAM_STR(delim) which accepts string value
      4. This macro copy the delimiter string value passed as first parameter in the explode function to the local variable delim
      5. Line 1163: Z_PARAM_STR(str) copy the string value passed as second parameter in the explode function to the local variable str
      6. Line 1164: Z_PARAM_OPTIONAL is used indicate from here to end of parse parameter block all the variables are optional one
      7. Line 1165: Z_PARAM_LONG(limit) is a function used to copy the PHP’s int datatype value to the C’s long datatype variable
      8. explode function’s third parameter $limit which is optional whose value is copied to the C variable limit
      9. If not passed then ZEND_LONG_MAX macro’s constant will be set, it’s based on 32 bit or 64 bit system the value’s size may vary
      10. Line 1166: ZEND_PARSE_PARAMETERS_END(); denotes the end of the parameters parsing and copying to local C variable and this is end of this block, note in this block this line only ends with semicolon to denote the block’s completion
    5. The lines 11681171 is a block which check delim is a empty string by checking the length and throws error
      1. Line 1168: if (ZSTR_LEN(delim) == 0) uses the macro function ZSTR_LEN which counts the character in the string and returns it’s length which compares with integer 0
      2. If boolean comparison is true, then code execution move into the block else if false then it skips the block completely
      3. Line 1169: php_error_docref(NULL, E_WARNING, "Empty delimiter"); is a error throwing macro function which throw warning error
      4. The first parameter of function php_error_docref is char datatype with NULL as a value and the remaining two parameters are self explanatory
      5. Line 1170: is a macro which compare it to constant macro value 2 which is for zend false type IS_FALSE you can find it by going upto the beginning of this macro’s call by clicking and follow the hyperlink from RETURN_FALSE which redirects it to ZVAL_FALSE and go on
    6. Line 1173: array_init(return_value) is an array API function which initialize a hash table for an array, additional info: internally PHP array itself a hash map (If possible in future will put a tutorial on Array’s internal!)
    7. The lines 11751181 is a block which is used to free up zval when the source string which need to be explode but passed as empty string and execute return to return result from the PHP_FUNCTION macro function
      1. Line 1175: if (ZSTR_LEN(str) == 0) checks if the passed string (to explode) length is equal to zero
      2. Line 1176: if (limit >= 0) checks the optional third parameter of the explode function (in C it’s local variable is limit) is greater than or equal to zero
      3. If limit variable’s boolean comparison is true then calls the inner block
      4. Line 1177: ZVAL_EMPTY_STRING(&tmp); which empties the tmp zval
      5. Line 1178: zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp); first using Z_ARRVAL_P is used to fetching the value of array type and passed it to the function zend_hash_index_add_new which is hash table API wrapper around the function _zend_hash_index_add_or_update_i for reference document doxygen document
      6. 1180: is a simple return to return empty array
    8. The lines 11831190 is a decision logic block based on the limit value it will split the string from left to right upto the limit lastly it have the whole left out string in last index or right to left upto the limit and remaining string will be neglected and the final else part is to handle limit of 0 or 1 which return the complete string as an array with whole string in first index
      1. Line 1183: if (limit > 1) which is straightforward boolean logic which checks is local variable limit is greater than integer 1
      2. Line 1184: php_explode(delim, str, return_value, limit); is the PHPAPI macro call with all parameters easy to understand except the third one return_value which is zval* provided by the macro function PHP_FUNCTION
      3. Line 1185: else if (limit < 0) which is straightforward boolean logic which checks is local variable limit is lesser than integer 0 i.e. negative number
      4. Line 1186: php_explode_negative_limit(delim, str, return_value, limit); is the PHPAPI macro call with all parameters same as php_explode but this API is for negative limit
      5. Line 1187: is the last block of this if-else ladder
      6. Line 1188: ZVAL_STR_COPY(&tmp, str); is a macro which is used to copy the string in the local variable str to zval generic pointer type local variable tmp
      7. Line 1189: is similar to the point 7.5 of this section

    Conclusion

    1. Now you are ready to explore any PHP function easily by applying the same procedure we discussed
    2. You learned the directory structure of the PHP source
    3. You learned how to use lxr utility
    4. You learned how PHP_FUNCTION macro is working