Parameters of function
The simplest way to obtain the parameters passed by the function caller is to use the zend_parse_parameters() function. We can directly generate the first few parameters of the zend_parse_parameters() function using macros in the kernel, in the form: ZEND_NUM_ARGS() TSRMLS_CC. Note that there is a space between the two, but there is no comma. As can be seen from the name, ZEND_NUM_ARGS() represents the number of parameters. The next parameter that needs to be passed to the zend_parse_parameters() function is a string used for formatting, just like the first parameter of printf. Several of the most commonly used symbols are represented below.
type_spec is a format string, its common meaning is as follows:
Parameter represents the type
b Boolean
l Integer integer type
d Floating point floating point type
s String string
r Resource resource
a Array array
o Object instance Object
O Object instance of a specified type Object of a specific type
z Non-specific zval Any type ~
Z zval** type
f Represents function and method names. It seems that there is no such thing in PHP5.1... .. .
This function is just like the printf() function. The following parameters correspond to the format in the format string one-to-one. Some basic types of data will be directly mapped to types in the C language.
ZEND_FUNCTION(sample_getlong) {
long foo;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"l", &foo) == FAILURE)
{ RETURN_NULL();
}
php_printf("The integer value of the parameter is: %ldn", foo);
RETURN_TRUE;
}
Generally speaking, the data of the two data types int and long are often the same, but there are exceptions. Therefore, we should not put the long array in an int, especially on a 64-bit platform, which will cause some bugs that are not easy to troubleshoot. Therefore, when receiving parameters through the zend_parse_parameter() function, we should use variables of the types agreed by the kernel as carriers.
Parameter corresponds to the data type in C
b zend_bool
l long
d double
s char*, int The former receives the pointer, the latter receives the length
r zval*
a zval*
o zval*
O zval*, zend_class_entry*
z zval*
Z zval**
Note that all composite type parameters in the PHP language require the zval* type as a carrier, because they are some data structures customized by the kernel. We must confirm that the type of the parameter and the carrier are consistent. If necessary, it can perform type conversion, such as converting the array into a stdClass object. The s and O (capital letter European) types need to be mentioned separately, because they both require two carriers. We will learn about the specific implementation of objects in PHP in the next chapters. So let's rewrite a function we defined in Chapter 5:
function sample_hello_world($name) { echo "Hello $name!n";
}
When writing extensions, we need to use zend_parse_parameters() To receive this string:
ZEND_FUNCTION(sample_hello_world) {
char *name;
int name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",&name, &name_len) == FAILURE)
{
RETURN_NULL() ;
}
php_printf("Hello ");
PHPWRITE(name, name_len);
php_printf("!n");
}
If the number of parameters passed to the function is less than the number of parameters to be received by zend_parse_parameters(), it The execution will fail and FAILURE will be returned.
If we need to receive multiple parameters, we can directly list the receiving carriers in the parameters of zend_parse_paramenters(), such as:
function sample_hello_world($name, $greeting) { echo "Hello $greeting $name !n";
}
sample_hello_world('John Smith', 'Mr.');
It should be implemented like this in the PHP extension:
ZEND_FUNCTION(sample_hello_world) {
char *name;
int name_len;
char *greeting;
int greeting_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",&name, &name_len, &greeting, &greeting_len) == FAILURE) {
RETURN_NULL();
}
php_printf("Hello ");
PHPWRITE(greeting, greeting_len);
php_printf(" ");
PHPWRITE(name, name_len);
php_printf("!n");
}
In addition to the parameters defined above, there are The other three parameters are used to enhance our ability to receive parameters, as follows: Type Modifier Meaning
| The parameters before it are all necessary, and the following parameters are not necessary, that is, they have default values.
! If you receive a null variable in PHP language, it will be directly converted into NULL in C language instead of encapsulating it into a zval of IS_NULL type.
/ If the passed variable shares a zval with other variables and is not a reference, it will be forced to separate. The new zval’s is_ref__gc==0, and refcount__gc==1.
The default value of the function parameter
Now let’s continue Rewrite sample_hello_world(), next we use the default values of some parameters, which is like the following in php language:
function sample_hello_world($name, $greeting='Mr./Ms.') { echo " Hello $greeting $name!n";
}
sample_hello_world('Ginger Rogers','Ms.');
sample_hello_world('Fred Astaire');
At this time, you can only pass one parameter to sample_hello_world, or you can pass Complete two parameters. So how can we implement the same function in the extension function? We need to use the (|) parameter in zend_parse_parameters. The parameters before this parameter are considered necessary, and the parameters after this parameter are considered non-essential. If not passed, the carrier will not be modified.
ZEND_FUNCTION(sample_hello_world) {
char *name;
int name_len;
char *greeting = "Mr./Mrs.";
int greeting_len = sizeof("Mr./Mrs.") - 1;
if ( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
&name, &name_len, &greeting, &greeting_len) == FAILURE) {
RETURN_NULL();
}
php_printf("Hello ");
PHPWRITE(greeting, greeting_len);
php_printf(" ");
PHPWRITE(name, name_len);
php_printf("!n");
}
If you do not pass the second parameter, the extension function will be considered as default without modifying the carrier. Therefore, we need to pre-set the value of the carrier ourselves, which is often NULL, or a value related to function logic. Each zval, including the IS_NULL type zval, needs to occupy a certain amount of memory space, and requires CPU computing resources to apply for memory for it, initialize it, and release it after they complete their work. But a lot of code doesn't realize this. There is a lot of code that wraps a null value into the IS_NULL type of zval. This operation can be optimized in extended development. We can receive the parameter as NULL in the C language. Let’s look at the following code on this issue:
ZEND_FUNCTION(sample_arg_fullnull) {
zval *val;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z",&val) == FAILURE) {
RETURN_NULL();
}
if (Z_TYPE_P(val) == IS_NULL) {
val = php_sample_make_defaultval(TSRMLS_C);
}
...
}
ZEND_FUNCTION(sample_arg_nullok) {
zval *val;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z! ",
val(TSRMLS_C);
}
}
At first glance, these two pieces of code don’t look like much. Different, but the first piece of code does require more cpu and memory resources. Maybe this technique is not very useful in normal times, but it is better to know it than not knowing it.
Forced Separation
When a variable is passed to a function, whether it is referenced or not, its refcoung__gc attribute will be incremented by one to at least 2. One copy is itself and the other is the copy passed to the function. Before changing this zval, sometimes it is necessary to divide it into two actual copies in advance. This is the role of the "/" format character. It will split the copy-on-write zval into two complete and independent copies in advance, so that we can operate on it at will in the following code. Otherwise, we may need to constantly remind ourselves to separate the received parameters and other operations. Like the NULL flag, this modifier goes after the type it means to impact. Also like the NULL flag, you won't know you need this feature until you actually have a use for it.
zend_get_arguments()
If you want If your extension is compatible with older versions of PHP, or if you only want to use zval as a carrier to receive parameters, you can consider using the zend_get_parameters() function to receive parameters. zend_get_parameters() is different from zend_parse_parameters(). As we can see from the name, it obtains directly without parsing. First of all, it will not automatically perform type conversion. The carriers of all parameters in the extended implementation need to be of zval type. Let us look at the simplest example:
ZEND_FUNCTION(sample_onearg) {
zval *firstarg;
if { Do something with firstarg.. . */
}
Secondly, zend_get_parameters() will not throw an error by itself when receiving fails, nor can it conveniently handle parameters with default values. The last point is that it is different from zend_parse_parameters in that it will automatically forcefully separate all zvals that comply with copy-on-write, and generate a new copy and send it to the function. If you want to use its other features but don't need this function, you can try using the zend_get_parameters_ex() function to receive parameters. In order not to separate the variables of copy-on-write, the parameters of zend_get_parameters_ex() are of type zval** instead of zval*. This function is not used very often. You may only think of it when you encounter some extreme problems, but it is very simple to use:
ZEND_FUNCTION(sample_onearg) {
zval **firstarg;
if (zend_get_parameters_ex(1, &firstarg) == FAILURE) {
WRONG_PARAM_COUNT;
}
/* Do something with firstarg... */
}
Note that zend_get_parameters_ex does not require ZEND_NUM_ARGS() as a parameter, because it is added at a later stage, and that parameter has already been No more.
The WRONG_PARAM_COUNT macro is also used in the above example. Its function is to throw an E_WARNING level error message and automatically return it.
Variable parameters
There are two other zend_get_parameter_** functions, which are specially used to solve the problem of many parameters or the number of parameters cannot be known in advance. Think about the usage of the var_dump() function in the PHP language. We can pass any number of parameters to it. Its implementation in the kernel is actually like this:
ZEND_FUNCTION(var_dump) {
int i, argc = ZEND_NUM_ARGS();
zval ***args;
args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE ) {
WRONG_PARAM_COUNT;
efree(args);
}
The program first obtains the number of parameters, and then applies for a corresponding size of memory through the safe_emalloc function to store these zval** type parameters. The zend_get_parameters_array_ex() function is used here to fill the parameters passed to the function into args. You may have immediately thought that there is also a function called zend_get_parameters_array(). The only difference is that it fills zval* type parameters into args and requires ZEND_NUM_ARGS() as a parameter.

ThesecrettokeepingaPHP-poweredwebsiterunningsmoothlyunderheavyloadinvolvesseveralkeystrategies:1)ImplementopcodecachingwithOPcachetoreducescriptexecutiontime,2)UsedatabasequerycachingwithRedistolessendatabaseload,3)LeverageCDNslikeCloudflareforservin

You should care about DependencyInjection(DI) because it makes your code clearer and easier to maintain. 1) DI makes it more modular by decoupling classes, 2) improves the convenience of testing and code flexibility, 3) Use DI containers to manage complex dependencies, but pay attention to performance impact and circular dependencies, 4) The best practice is to rely on abstract interfaces to achieve loose coupling.

Yes,optimizingaPHPapplicationispossibleandessential.1)ImplementcachingusingAPCutoreducedatabaseload.2)Optimizedatabaseswithindexing,efficientqueries,andconnectionpooling.3)Enhancecodewithbuilt-infunctions,avoidingglobalvariables,andusingopcodecaching

ThekeystrategiestosignificantlyboostPHPapplicationperformanceare:1)UseopcodecachinglikeOPcachetoreduceexecutiontime,2)Optimizedatabaseinteractionswithpreparedstatementsandproperindexing,3)ConfigurewebserverslikeNginxwithPHP-FPMforbetterperformance,4)

APHPDependencyInjectionContainerisatoolthatmanagesclassdependencies,enhancingcodemodularity,testability,andmaintainability.Itactsasacentralhubforcreatingandinjectingdependencies,thusreducingtightcouplingandeasingunittesting.

Select DependencyInjection (DI) for large applications, ServiceLocator is suitable for small projects or prototypes. 1) DI improves the testability and modularity of the code through constructor injection. 2) ServiceLocator obtains services through center registration, which is convenient but may lead to an increase in code coupling.

PHPapplicationscanbeoptimizedforspeedandefficiencyby:1)enablingopcacheinphp.ini,2)usingpreparedstatementswithPDOfordatabasequeries,3)replacingloopswitharray_filterandarray_mapfordataprocessing,4)configuringNginxasareverseproxy,5)implementingcachingwi

PHPemailvalidationinvolvesthreesteps:1)Formatvalidationusingregularexpressionstochecktheemailformat;2)DNSvalidationtoensurethedomainhasavalidMXrecord;3)SMTPvalidation,themostthoroughmethod,whichchecksifthemailboxexistsbyconnectingtotheSMTPserver.Impl


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 Linux new version
SublimeText3 Linux latest version

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.

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

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