目次
深入理解PHP内核(六)函数的定义、传参及返回值,深入理解内核
ホームページ バックエンド開発 PHPチュートリアル 深入理解PHP内核(六)函数的定义、传参及返回值,深入理解内核_PHP教程

深入理解PHP内核(六)函数的定义、传参及返回值,深入理解内核_PHP教程

Jul 12, 2016 am 08:59 AM
messagebox

深入理解PHP内核(六)函数的定义、传参及返回值,深入理解内核

一、函数的定义

  用户函数的定义从function 关键字开始,如下

<span>function</span> foo(<span>$var</span><span>) {
    </span><span>echo</span> <span>$var</span><span>;
}</span>
ログイン後にコピー

  1、词法分析

  在Zend/zend_language_scanner.l中我们找到如下所示的代码:

<ST_IN_SCRIPTING><span>"</span><span>function</span><span>"</span><span> {
    </span><span>return</span><span> T_FUNCTION;
}</span>
ログイン後にコピー

  它所表示的含义是function将会生成T_FUNCTION标记。在获取这个标记后,我们开始语法分析。

  2、语法分析

  在Zend/zend_language_parser.y文件中找到函数的声明过程标记如下:

<span>function:
    T_FUNCTION { $$.u.opline_num </span>=<span> CG(zend_lineno); }
;
 
is_reference:
        </span><span>/*</span><span> empty </span><span>*/</span> { $$.op_type =<span> ZEND_RETURN_VAL; }
    </span>|   <span>'</span><span>&</span><span>'</span>         { $$.op_type =<span> ZEND_RETURN_REF; }
;
 
unticked_function_declaration_statement:
        function is_reference T_STRING {
zend_do_begin_function_declaration(</span>&$<span>1</span>, &$<span>3</span>, <span>0</span>, $<span>2</span><span>.op_type, NULL TSRMLS_CC); }
            </span><span>'</span><span>(</span><span>'</span> parameter_list <span>'</span><span>)</span><span>'</span> <span>'</span><span>{</span><span>'</span> inner_statement_list <span>'</span><span>}</span><span>'</span><span> {
                zend_do_end_function_declaration(</span>&$<span>1</span><span> TSRMLS_CC); }
;</span>
ログイン後にコピー

    关注点在function is_reference T_STRING,表示function关键字,是否引用,函数名

  T_FUNCTION标记只是用来定位函数的声明,表示这是一个函数,而更多的工作是与这个函数相关的东西,包括参数,返回值。

  3、生成中间代码

  语法解析后,我们看到所执行编译函数为zend_do_begin_function_declaration。在Zend/zend_complie.c文件找到其实现如下:

<span>void</span> zend_do_begin_function_declaration(znode *<span>function_token, znode 
</span>*<span>function_name,
 </span><span>int</span> is_method, <span>int</span> return_reference, znode *fn_flags_znode TSRMLS_DC) <span>/*</span><span> {{{ 
</span><span>*/</span><span>
{
    ...</span><span>//</span><span>省略</span>
    function_token->u.op_array =<span> CG(active_op_array);
    lcname </span>=<span> zend_str_tolower_dup(name, name_len);
 
    orig_interactive </span>=<span> CG(interactive);
    CG(interactive) </span>= <span>0</span><span>;
    init_op_array(</span>&<span>op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE 
TSRMLS_CC);
    CG(interactive) </span>=<span> orig_interactive;
 
     ...</span><span>//</span><span>省略</span>
 
    <span>if</span><span> (is_method) {
        ...</span><span>//</span><span>省略,类方法 在后面的章节介绍</span>
„!<span>ǶGH
    } </span><span>else</span><span> {
        zend_op </span>*opline =<span> get_next_op(CG(active_op_array) TSRMLS_CC);
 
 
        opline</span>->opcode =<span> ZEND_DECLARE_FUNCTION;
        opline</span>->op1.op_type =<span> IS_CONST;
        build_runtime_defined_function_key(</span>&opline-><span>op1.u.constant, lcname,
            name_len TSRMLS_CC);
        opline</span>->op2.op_type =<span> IS_CONST;
        opline</span>->op2.u.constant.type =<span> IS_STRING;
        opline</span>->op2.u.constant.value.str.val =<span> lcname;
        opline</span>->op2.u.constant.value.str.len =<span> name_len;
        Z_SET_REFCOUNT(opline</span>->op2.u.constant, <span>1</span><span>);
        opline</span>->extended_value =<span> ZEND_DECLARE_FUNCTION;
        zend_hash_update(CG(function_table), opline</span>-
><span>op1.u.constant.value.str.val,
            opline</span>->op1.u.constant.value.str.len, &<span>op_array, 
</span><span>sizeof</span><span>(zend_op_array),
             (</span><span>void</span> **) &<span>CG(active_op_array));
    }
 
}
</span><span>/*</span><span> }}} </span><span>*/</span><span><br /></span>
ログイン後にコピー

  生成的代码为ZEND_DECLARE_FUNCTION,根据这个中间的代码及操作数对应的op_type。我们可以找到中间代码的执行函数为ZEND_DECLARE_FUNCTION_SPEC_HANDLER。

    在生成中间代码的时候,可以看到已经统一了函数名全部为小写,表示函数的名称不是区  分大小写的。

  为验证这个实现,我们看一段代码

<span>function T() {
    echo </span><span>1</span><span>;
}
 
function t() {
    echo </span><span>2</span><span>;
}</span>
ログイン後にコピー

  执行代码会报错Fatal error: Cannot redeclare t() (previously declared in ...)

  表示对于PHP来说T和t是同一个函数名,校验函数名是否重复,这个过程是在哪进行的呢?

  4、执行中间代码

  在Zend/zend_vm_execute.h文件中找到ZEND_DECLARE_FUNCTION中间代码对应的执行函数:ZEND_DECLARE_FUNCTION_SPEC_HANDLER。此函数只调用了函数do_bind_function。其调用代码为:

do_bind_function(EX(opline), EG(function_table), <span>0</span>);
ログイン後にコピー

  在这个函数中将EX(opline)所指向的函数添加到EG(function_table)中,并判断是否已经存在相同名字的函数,如果存在则报错,EG(function_table)用来存放执行过程中全部的函数信息,相当于函数的注册表。它的结构是一个HashTable,所以在do_bind_function函数中添加新的函数使用的是HashTable的操作函数zend_hash_add

二、函数的参数

  函数的定义只是一个将函数名注册到函数列表的过程。

  1、用户自定义函数的参数

  我们知道对于函数的参数检查是通过zend_do_receive_arg函数来实现的,在此函数中对于参数的关键代码如下:

CG(active_op_array)->arg_info = erealloc(CG(active_op_array)-><span>arg_info,
        </span><span>sizeof</span>(zend_arg_info)*(CG(active_op_array)-><span>num_args));
cur_arg_info </span>= &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-<span>1</span><span>];
cur_arg_info</span>->name = estrndup(varname-><span>u.constant.value.str.val,
        varname</span>-><span>u.constant.value.str.len);
cur_arg_info</span>->name_len = varname-><span>u.constant.value.str.len;
cur_arg_info</span>->array_type_hint = <span>0</span><span>;
cur_arg_info</span>->allow_null = <span>1</span><span>;
cur_arg_info</span>->pass_by_reference =<span> pass_by_reference;
cur_arg_info</span>->class_name =<span> NULL;
cur_arg_info</span>->class_name_len = <span>0</span>;
ログイン後にコピー

  整个参数的传递是通过给中间代码的arg_info字段执行赋值操作完成。关键点是在arg_info字段,arg_info字段的结构如下:

typedef <span>struct</span><span> _zend_arg_info {
    </span><span>const</span> <span>char</span> *name;   <span>/*</span><span>参数的名称</span><span>*/</span><span>
    zend_uint name_len;     </span><span>/*</span><span>参数名称的长度</span><span>*/</span>
    <span>const</span> <span>char</span> *class_name; <span>/*</span><span> 类名</span><span>*/</span><span>
     zend_uint class_name_len;   </span><span>/*</span><span>类名长度</span><span>*/</span><span>
    zend_bool array_type_hint;  </span><span>/*</span><span>数组类型提示</span><span>*/</span><span>
    zend_bool allow_null;   </span><span>/*</span><span>是否允许为NULLͺ</span><span>*/</span><span>
    zend_bool pass_by_reference;    </span><span>/*</span><span>是否引用传递</span><span>*/</span><span>
    zend_bool return_reference; 
    </span><span>int</span><span> required_num_args;  
} zend_arg_info;</span>
ログイン後にコピー

  参数的值传递和参数传递的区别是通过pass_by_reference参数在生成中间代码时实现的。

  对于参数的个数,中间代码中包含的arg_nums字段在每次执行**zend_do_receive_argxx时都会加1.如下代码:

CG(active_op_array)->num_args++;
ログイン後にコピー

  并且当前参数的索引为ŒCG(active_op_array)->num_args-1.如下代码:

cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-<span>1</span>];
ログイン後にコピー

  以上的分析是针对函数定义时的参数设置,这些参数是固定的。而在实际编写程序时可能我们会用到可变参数。此时我们会用到函数func_num_args和func_get_args。它们是以内部函数存在。于是在Zend\zend_builtin_functions.c文件中找到这两个函数的实现。我们首先来看func_num_args函数的实现,其代码如下:

<span>/*</span><span> {{{ proto int func_num_args(void)
   Get the number of arguments that were passed to the function </span><span>*/</span><span>
ZEND_FUNCTION(func_num_args)
{
    zend_execute_data </span>*ex = EG(current_execute_data)-><span>prev_execute_data;
 
    </span><span>if</span> (ex && ex-><span>function_state.arguments) {
        RETURN_LONG((</span><span>long</span>)(zend_uintptr_t)*(ex-><span>function_state.arguments));
    } </span><span>else</span><span> {
        zend_error(E_WARNING,
</span><span>"</span><span>func_num_args():  Called from the global scope - no function context</span><span>"</span><span>);
        RETURN_LONG(</span>-<span>1</span><span>);
    }
}
</span><span>/*</span><span> }}} </span><span>*/</span>
ログイン後にコピー

  在存在ex->function_state.arguments的情况下,及函数调用时,返回ex->function_state.arguments转化后的值,否则显示错误并返回-1。这里最关键的一点是EG(current_execute_data)。这个变量存放的是当前执行程序或函数的数据,此时我们需要取前一个执行程序的数据,为什么呢?因为这个函数的调用是在进入函数后执行的。函数的相关数据等都在之前执行过程中,于是调用的是:

zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
ログイン後にコピー

  2、内部函数的参数

  以常见的count函数为例,其参数处理部分的代码如下:

<span>/*</span><span> {{{ proto int count(mixed var [, int mode])
   Count the number of elements in a variable (usually an array) </span><span>*/</span><span>
PHP_FUNCTION(count)
{
    zval </span>*<span>array;
    </span><span>long</span> mode =<span> COUNT_NORMAL;
 
    </span><span>if</span> (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, <span>"</span><span>z|l</span><span>"</span><span>,
         </span>&array, &mode) ==<span> FAILURE) {
        </span><span>return</span><span>;
    }
    ... </span><span>//</span><span>省略</span>
}
ログイン後にコピー

  这里包括了两个操作:一个是取参数的个数,一个是解析参数列表。

  (1)取参数的个数

  取参数的个数是通过ZEND_NUM_ARGS()宏来实现的,其定义如下:

<span>#define</span> ZEND_NUM_ARGS()     (ht)
ログイン後にコピー

  ht是在Zend/zend.h文件中定义的宏INTERNAL_FUNCTION_PARAMETERS中的ht,如下

<span>#define</span> INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value,<span>
zval </span>**return_value_ptr, zval *this_ptr, <span>int</span> return_value_used TSRMLS_DC
ログイン後にコピー

  (2)解析参数列表

  PHP内部函数在解析参数时使用的是zend_parse_parameters。它可以大大简化参数的接收处理工作,虽然它在处理可变参数时还有点弱。

  其声明如下:

ZEND_API <span>int</span> zend_parse_parameters(<span>int</span> num_args TSRMLS_DC, <span>char</span> *<span>type_spec, 
...)</span>
ログイン後にコピー
  • 第一个参数num_args表明表示想要接收的参数个数,我们经常使用ZEND_NUM_ARGS()来表示对传入的参数“有多少要多少”
  • 第二个参数应该是宏TSRMLS_CC。
  • 第三个参数type_spec是一个字符串,用来指定我们所期待接收的各个参数的类型,有点类似于printf中指定输出格式的那个格式化字符串。
  • 剩下的参数就是我们用来接收PHP参数值的变量的指针。

  zend_parse_parameters()在解析参数的同时户尽可能的转换参数类型,这样就可以确保我们总是能得到所期望的类型的变量

  3、函数的返回值

  PHP中函数都有返回值,没return返回null

  (1)return语句

  从Zend/zend_language_parser.y文件中可以确认其生成中间代码调用的是zend_do_return函数。

<span>void</span> zend_do_return(znode *expr, <span>int</span> do_end_vparse TSRMLS_DC) <span>/*</span><span> {{{ </span><span>*/</span><span>
{
    zend_op </span>*<span>opline;
    </span><span>int</span><span> start_op_number, end_op_number;
 </span><span>if</span><span> (do_end_vparse) {
        </span><span>if</span> (CG(active_op_array)-><span>return_reference
                </span>&& !<span>zend_is_function_or_method_call(expr)) {
            zend_do_end_variable_parse(expr, BP_VAR_W, </span><span>0</span> TSRMLS_CC);<span>/*</span><span> 处理返回引用 </span><span>*/</span><span>
        } </span><span>else</span><span> {
            zend_do_end_variable_parse(expr, BP_VAR_R, </span><span>0</span> TSRMLS_CC);<span>/*</span><span> 处理常规变量返回 </span><span>*/</span><span>
        }
    }
 
   ...</span><span>//</span><span> 省略,取其他中间代码操作</span>
<span> 
    opline</span>->opcode =<span> ZEND_RETURN;
 
    </span><span>if</span><span> (expr) {
        opline</span>->op1 = *<span>expr;
 
        </span><span>if</span> (do_end_vparse &&<span> zend_is_function_or_method_call(expr)) {
            opline</span>->extended_value =<span> ZEND_RETURNS_FUNCTION;
        }
    } </span><span>else</span><span> {
        opline</span>->op1.op_type =<span> IS_CONST;
        INIT_ZVAL(opline</span>-><span>op1.u.constant);
    }
 
    SET_UNUSED(opline</span>-><span>op2);
}
</span><span>/*</span><span> }}} </span><span>*/</span>
ログイン後にコピー

  生成中间代码为ZEND_RETURN。第一个操作数的类型在返回值为可用的表达式时,其类型为表达式的操作类型,否则类型为IS_CONST。这在后续计算执行中间代码函数时有用到。根据操作数的不同,ZEND_RETURN中间代码会执行ZEND_RETURN_SPEC_CONST_HANDLER,ZEND_RETURN_SPEC_TMP_HANDLER或ZEND_RETURN_SPEC_TMP_HANDLER。这三个函数的执行流程基本类似,包括对一些错误的处理。这里我们以ZEND_RETURN_SPEC_CONST_HANDLER为例说明函数返回值的执行过程:

<span>static</span> <span>int</span><span> ZEND_FASTCALL  
ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    zend_op </span>*opline =<span> EX(opline);
    zval </span>*<span>retval_ptr;
    zval </span>**<span>retval_ptr_ptr;
 
 
    </span><span>if</span> (EG(active_op_array)->return_reference ==<span> ZEND_RETURN_REF) {
 
        </span><span>//</span><span>  Ǔǔŷs&Aacute;\ɁƶMļ@ɗ&Aacute;Ļļ</span>
        <span>if</span> (IS_CONST == IS_CONST || IS_CONST ==<span> IS_TMP_VAR) {   
            </span><span>/*</span><span> Not supposed to happen, but we'll allow it </span><span>*/</span><span>
            zend_error(E_NOTICE, </span><span>"</span><span>Only variable references \</span>
                should be returned by reference<span>"</span><span>);</span>
            <span>goto</span><span> return_by_value;
        }
 
        retval_ptr_ptr </span>= NULL;  <span>//</span><span>  ǓǔŔ</span>
 
        <span>if</span> (IS_CONST == IS_VAR && !<span>retval_ptr_ptr) {
            zend_error_noreturn(E_ERROR, </span><span>"</span><span>Cannot return string offsets by </span>
reference<span>"</span><span>);</span>
<span>        }
 </span><span>if</span> (IS_CONST == IS_VAR && !<span>Z_ISREF_PP(retval_ptr_ptr)) {
            </span><span>if</span> (opline->extended_value == ZEND_RETURNS_FUNCTION &&<span>
                EX_T(opline</span>->op1.u.<span>var</span>).<span>var</span><span>.fcall_returned_reference) {
            } </span><span>else</span> <span>if</span> (EX_T(opline->op1.u.<span>var</span>).<span>var</span>.ptr_ptr ==
                    &EX_T(opline->op1.u.<span>var</span>).<span>var</span><span>.ptr) {
                </span><span>if</span> (IS_CONST == IS_VAR && !<span>0</span><span>) {
                      </span><span>/*</span><span> undo the effect of get_zval_ptr_ptr() </span><span>*/</span><span>
                    PZVAL_LOCK(</span>*<span>retval_ptr_ptr);
                }
                zend_error(E_NOTICE, </span><span>"</span><span>Only variable references \</span>
                 should be returned by reference<span>"</span><span>);</span>
                <span>goto</span><span> return_by_value;
            }
        }
 
        </span><span>if</span> (EG(return_value_ptr_ptr)) { <span>//</span><span>  Ǔǔŷs</span>
            SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);   <span>//</span><span>  is_ref__gcőęŒ</span>
<span>1</span><span>
            Z_ADDREF_PP(retval_ptr_ptr);    </span><span>//</span><span>  refcount__gc&OElig;ď&times;1</span>
<span> 
            (</span>*EG(return_value_ptr_ptr)) = (*<span>retval_ptr_ptr);
        }
    } </span><span>else</span><span> {
return_by_value:
 
        retval_ptr </span>= &opline-><span>op1.u.constant;
 
        </span><span>if</span> (!<span>EG(return_value_ptr_ptr)) {
            </span><span>if</span> (IS_CONST ==<span> IS_TMP_VAR) {
 
            }
        } </span><span>else</span> <span>if</span> (!<span>0</span>) { <span>/*</span><span> Not a temp var </span><span>*/</span>
            <span>if</span> (IS_CONST == IS_CONST ||<span>
                EG(active_op_array)</span>->return_reference == ZEND_RETURN_REF ||<span>
                (PZVAL_IS_REF(retval_ptr) </span>&& Z_REFCOUNT_P(retval_ptr) > <span>0</span><span>)) {
                zval </span>*<span>ret;
 
                ALLOC_ZVAL(ret);
                INIT_PZVAL_COPY(ret, retval_ptr);   </span><span>//</span><span>  Ł™ͿʍǓǔŔ </span>
<span>                zval_copy_ctor(ret);
                </span>*EG(return_value_ptr_ptr) =<span> ret;
            } </span><span>else</span><span> {
                </span>*EG(return_value_ptr_ptr) = retval_ptr; <span>//</span><span>  ħ6ɶŔ</span>
<span>                Z_ADDREF_P(retval_ptr);
            }
        } </span><span>else</span><span> {
            zval </span>*<span>ret;
 
            ALLOC_ZVAL(ret);
            INIT_PZVAL_COPY(ret, retval_ptr);    </span><span>//</span><span>  Ł™ͿʍǓǔŔ </span>
            *EG(return_value_ptr_ptr) =<span> ret;    
        }
    }
 
    </span><span>return</span> zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);   <span>//</span><span>  Ǔ</span>
<span>ǔĉˆșʒ
}</span>
ログイン後にコピー

  函数的返回值在程序执行时存储在*EG(return_value_ptr_ptr)。ZEND内核对值返回和引用返回作了区别,并且在此基础上对常量,临时变量和其他类型的变量在返回时作了不同的处理。在return执行完之后,ZEND内核通过调用zend_leave_helper_SPEC函数,清除函数内部使用的变量等。这也是ZEND内核自动给函数加上NULL返回的原因之一。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1100151.htmlTechArticle深入理解PHP内核(六)函数的定义、传参及返回值,深入理解内核 一、函数的定义 用户函数的定义从function 关键字开始,如下 function foo( $v...
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

確固たる原則と、それらがPHP開発にどのように適用されるかを説明してください。 確固たる原則と、それらがPHP開発にどのように適用されるかを説明してください。 Apr 03, 2025 am 12:04 AM

PHP開発における固体原理の適用には、次のものが含まれます。1。単一責任原則(SRP):各クラスは1つの機能のみを担当します。 2。オープンおよびクローズ原理(OCP):変更は、変更ではなく拡張によって達成されます。 3。Lischの代替原則(LSP):サブクラスは、プログラムの精度に影響を与えることなく、基本クラスを置き換えることができます。 4。インターフェイス分離原理(ISP):依存関係や未使用の方法を避けるために、細粒インターフェイスを使用します。 5。依存関係の反転原理(DIP):高レベルのモジュールと低レベルのモジュールは抽象化に依存し、依存関係噴射を通じて実装されます。

PHPにおける後期静的結合の概念を説明します。 PHPにおける後期静的結合の概念を説明します。 Mar 21, 2025 pm 01:33 PM

記事では、PHP 5.3で導入されたPHPの後期静的結合(LSB)について説明し、より柔軟な継承を求める静的メソッドコールのランタイム解像度を可能にします。 LSBの実用的なアプリケーションと潜在的なパフォーマ

システムの再起動後にUnixSocketの権限を自動的に設定する方法は? システムの再起動後にUnixSocketの権限を自動的に設定する方法は? Mar 31, 2025 pm 11:54 PM

システムが再起動した後、UnixSocketの権限を自動的に設定する方法。システムが再起動するたびに、UnixSocketの許可を変更するために次のコマンドを実行する必要があります:sudo ...

PHPのCurlライブラリを使用してJSONデータを含むPOSTリクエストを送信する方法は? PHPのCurlライブラリを使用してJSONデータを含むPOSTリクエストを送信する方法は? Apr 01, 2025 pm 03:12 PM

PHP開発でPHPのCurlライブラリを使用してJSONデータを送信すると、外部APIと対話する必要があることがよくあります。一般的な方法の1つは、Curlライブラリを使用して投稿を送信することです。

フレームワークセキュリティ機能:脆弱性から保護します。 フレームワークセキュリティ機能:脆弱性から保護します。 Mar 28, 2025 pm 05:11 PM

記事では、入力検証、認証、定期的な更新など、脆弱性から保護するためのフレームワークの重要なセキュリティ機能について説明します。

フレームワークのカスタマイズ/拡張:カスタム機能を追加する方法。 フレームワークのカスタマイズ/拡張:カスタム機能を追加する方法。 Mar 28, 2025 pm 05:12 PM

この記事では、フレームワークにカスタム機能を追加し、アーキテクチャの理解、拡張ポイントの識別、統合とデバッグのベストプラクティスに焦点を当てています。

See all articles