目次
1. INI 設定ファイルを解析します
2,配置作用到模块
2.1,模块的全局空间
2.2,如何确定一个模块需要哪些配置呢?
2.3,将配置作用到模块——REGISTER_INI_ENTRIES
3,总结
ホームページ バックエンド開発 PHPチュートリアル PHP の ini 設定についての深い理解

PHP の ini 設定についての深い理解

Jun 23, 2016 pm 01:16 PM

この記事では、特定の ini 設定項目の目的については詳しく説明しません。これらはマニュアルで詳しく説明されています。私は、特定の観点から PHP の実装メカニズムを検討したいだけです。これには、PHP カーネルの知識が必要になります:-)

PHP を使用する学生は、php.ini 設定が SAPI ライフサイクル全体を通じて有効であることを知っています。 PHP スクリプトの実行中に、ini 設定を手動で変更しても、その変更は有効になりません。現時点で Apache または nginx を再起動できない場合は、php コードで ini_set インターフェイスを明示的に呼び出すことしかできません。 ini_set は、動的に設定を変更するために PHP が提供する関数です。ini_set で設定した設定と、ini ファイルに設定した設定は、有効な時間範囲が異なることに注意してください。 php スクリプトを実行すると、ini_set 設定はすぐに無効になります。

したがって、この記事は 2 つの部分に分かれており、最初の部分では php.ini 設定の原則について説明し、2 番目の部分では php 設定の動的変更について説明します。

php.iniの設定には大きく分けてconfiguration_hash、EG(ini_directives)、PG、BG、PCRE_G、JSON_G、XXX_Gなどの3つのデータが含まれます。これら 3 種類のデータの意味が分からなくても問題ありません。以下で詳しく説明します。

1. INI 設定ファイルを解析します

php.ini は SAPI プロセス中に有効である必要があるため、ini ファイルを解析し、それに応じて php 設定を構築する作業が SAPI の開始部分である必要があります。つまり、PHP の起動プロセス中に発生する必要があります。 PHP では、実際のリクエストが到着する前に、これらの設定を内部で生成する必要があります。

php_module_startup 関数である php のコアに反映されます。

php_module_startup は主に php の起動を担当し、通常は SAPI の起動時に呼び出されます。ところで、もう 1 つの一般的な関数は php_request_startup です。これは、各リクエストが到着したときに初期化する役割を果たします。php_module_startup と php_request_startup は 2 つの象徴的なアクションですが、それらの分析はこの記事の範囲外です。

たとえば、php が Apache のモジュールにフックされている場合、Apache が起動すると、php モジュールを含むすべてのモジュールがアクティブ化されます。 PHPモジュールを有効化する際には、php_module_startupが呼び出されます。 php_module_startup 関数は、php_module_startup 呼び出しが終了すると、多くの作業を完了します。これは、php が開始され、リクエストを受け入れて応答できることを意味します。

php_module_startup 関数では、ini ファイルの解析に関連する実装は次のとおりです:

/* this will read in php.ini, set up the configuration parameters,   load zend extensions and register php function extensions   to be loaded later */if (php_init_config(TSRMLS_C) == FAILURE) {    return FAILURE;}
ログイン後にコピー

ご覧のとおり、ini ファイルの解析を完了するために php_init_config 関数が実際に呼び出されます。解析作業は主に字句と文法の解析を実行し、キーと値のペアを抽出して ini ファイルに保存します。 php.ini の形式は非常に単純で、等号の左側にキー、右側に値があります。 KV のペアが抽出されると、php はそれらをどこに保存しますか?答えは、前述したconfiguration_hashです。

static HashTable configuration_hash;
ログイン後にコピー

Configuration_hash は php_ini.c で宣言されており、HashTable 型のデータ構造です。名前が示すように、実際にはハッシュ テーブルです。余談ですが、configuration_hash は php_ini.c ファイル内の静的変数であるため、php5.3 より前のバージョンでは取得できません。その後、php5.3 では、&configuration_hash を直接返す php_ini_get_configuration_hash インターフェイスが追加されました。これにより、各 PHP 拡張機能で、configuration_hash を簡単に確認できるようになりました... なんとありがたいことでしょう...

4 つの点に注意してください:

まず、php_init_config は、語彙と構文を除くあらゆる検証を実行します。つまり、ini ファイルに行 hello=world を追加すると、これが正しくフォーマットされた構成項目である限り、最終的なconfiguration_hash にはキー hello と値 world を持つ要素が含まれ、configuration_hash はそれを反映します。 ini ファイルを最大限に拡張します。

2 番目に、ini ファイルを使用すると、配列の形式で構成できます。たとえば、ini ファイルに次の 3 行を書き込みます:

drift.arr[]=1drift.arr[]=2drift.arr[]=3
ログイン後にコピー

次に、最終的に生成されたconfiguration_hashテーブルには、キーdrift.arrを持つ要素があり、その値は3つの数値1、2、および3を含む配列になります。 3.これは非常に珍しい構成方法です。

第三に、php では、デフォルトの php.ini ファイル (正確には php-%s.ini) に加えて、追加の ini ファイルを構築することもできます。これらの ini ファイルは追加のディレクトリに配置されます。このディレクトリは、環境変数 PHP_INI_SCAN_DIR によって指定されます。php_init_config が php.ini を解析した後、このディレクトリを再度スキャンし、分析のためにディレクトリ内のすべての .ini ファイルを検索します。これらの追加の ini ファイルで生成された kv キーと値のペアも、configuration_hash に追加されます。

これは、PHP 拡張機能を自分で開発するが、その設定を php.ini に混ぜたくない場合、別の ini を記述し、PHP_INI_SCAN_DIR を通じてその場所を PHP に指示できます。もちろん、その欠点も明らかであり、それをサポートするには追加の環境変数を設定する必要があります。より良い解決策は、開発者が拡張機能内で php_parse_user_ini_file または zend_parse_ini_file を呼び出して、対応する ini ファイルを解析することです。

第四,在configuration_hash中,key是字符串,那么值的类型是什么?答案也是字符串(除了上述很特殊的数组)。具体来说,比如下面的配置:

display_errors = Onlog_errors = Offlog_errors_max_len = 1024
ログイン後にコピー

那么最后configuration_hash中实际存放的键值对为:

key: "display_errors"val : "1"key: "log_errors"val : ""key: "log_errors_max_len"val : "1024"
ログイン後にコピー

注意log_errors,其存放的值连"0"都不是,就是一个实实在在地空字符串。另外,log_errors_max_len也并非数字,而是字符串1024。

分析至此,基本上解析ini文件相关的内容都说清楚了。简单总结一下:

1,解析ini发生在php_module_startup阶段

2,解析结果存放在configuration_hash里。

2,配置作用到模块

php的大致结构可以看成是最下层有一个zend引擎,它负责与OS进行交互、编译php代码、提供内存托管等等,在zend引擎的上层,排列着很多很多的模块。其中最核心的就一个Core模块,其他还有比如Standard,PCRE,Date,Session等等...这些模块还有另一个名字叫php扩展。我们可以简单理解为,每个模块都会提供一组功能接口给开发者来调用,举例来说,常用的诸如explode,trim,array等内置函数,便是由Standard模块提供的。

为什么需要谈到这些,是因为在php.ini里除了针对php自身,也就是针对Core模块的一些配置(例如safe_mode,display_errors,max_execution_time等),还有相当多的配置是针对其他不同模块的。

例如,date模块,它提供了常见的date, time,strtotime等函数。在php.ini中,它的相关配置形如:

[Date];date.timezone = 'Asia/Shanghai';date.default_latitude = 31.7667;date.default_longitude = 35.2333;date.sunrise_zenith = 90.583333;date.sunset_zenith = 90.583333
ログイン後にコピー

除了这些模块拥有独立的配置,zend引擎也是可配的,只不过zend引擎的可配项非常少,只有error_reporting,zend.enable_gc和detect_unicode三项。

在上一小节中我们已经谈到,php_module_startup会调用php_init_config,其目的是解析ini文件并生成configuration_hash。那么接下来在php_module_startup中还会做什么事情呢?很显然,就是会将configuration_hash中的配置作用于Zend,Core,Standard,SPL等不同模块。当然这并非一个一蹴而就的过程,因为php通常会包含有很多模块,php启动的过程中这些模块也会依次进行启动。那么,对模块A进行配置的过程,便是发生在模块A的启动过程中。

有扩展开发经验的同学会直接指出,模块A的启动不就是在PHP_MINIT_FUNCTION(A)中么?

是的,如果模块A需要配置,那么在PHP_MINIT_FUNCTION中,可以调用REGISTER_INI_ENTRIES()来完成。REGISTER_INI_ENTRIES会根据当前模块所需要的配置项名称,去configuration_hash查找用户设置的配置值,并更新到模块自己的全局空间中。

2.1,模块的全局空间

要理解如何将ini配置从configuration_hash作用到各个模块之前,有必要先了解一下php模块的全局空间。对于不同的php模块,均可以开辟一块属于自己的存储空间,并且这块空间对于该模块来说,是全局可见的。一般而言,它会被用来存放该模块所需的ini配置。也就是说,configuration_hash中的配置项,最终会被存放到该全局空间中。在模块的执行过程中,只需要直接访问这块全局空间,就可以拿到用户针对该模块进行的设置。当然,它也经常被用来记录模块在执行过程中的中间数据。

我们以bcmath模块来举例说明,bcmath是一个提供数学计算方面接口的php模块,首先我们来看看它有哪些ini配置:

PHP_INI_BEGIN()    STD_PHP_INI_ENTRY("bcmath.scale", "0", PHP_INI_ALL, OnUpdateLongGEZero, bc_precision, zend_bcmath_globals, bcmath_globals)PHP_INI_END()
ログイン後にコピー

bcmath只有一个配置项,我们可以在php.ini中用bcmath.scale来配置 bcmath模块。

接下来继续看看bcmatch模块的全局空间定义。在php_bcmath.h中有如下声明:

ZEND_BEGIN_MODULE_GLOBALS(bcmath)    bc_num _zero_;    bc_num _one_;    bc_num _two_;    long bc_precision;ZEND_END_MODULE_GLOBALS(bcmath)
ログイン後にコピー

宏展开之后,即为:

typedef struct _zend_bcmath_globals {

bc_num _zero_;

bc_num _one_;

bc_num _two_;

long bc_precision;

} zend_bcmath_globals;

其实,zend_bcmath_globals类型就是bcmath模块中的全局空间类型。这里仅仅声明了zend_bcmath_globals结构体,在 bcmath.c中还有具体的实例化定义:

// 展开后即为zend_bcmath_globals bcmath_globals;ZEND_DECLARE_MODULE_GLOBALS(bcmath)
ログイン後にコピー

可以看出,用ZEND_DECLARE_MODULE_GLOBALS完成了对变量bcmath_globals的定义。

bcmath_globals是一块真正的全局空间,它包含有四个字段。其最后一个字段bc_precision,对应于ini配置中的 bcmath.scale。我们在php.ini中设置了bcmath.scale的值,随后在启动bcmath模块的时候, bcmath.scale的值被更新到bcmath_globals.bc_precision中去。

把configuration_hash中的值,更新到各个模块自己定义的xxx_globals变量中,就是所谓的将ini配置作用到模块。一旦模块启动完成,那么这些配置也都作用到位。所以 在随后的执行阶段,php模块无需再次访问configuration_hash,模块仅需要访问自己的XXX_globals,就可以拿到用户设定的配置。

bcmath_globals,除了有一个字段为ini配置项,其他还有三个字段为何意?这就是模块全局空间的第二个作用,它除了用于ini配置,还可以存储模块执行过程中的一些数据。

再例如json模块,也是php中一个很常用的模块:

ZEND_BEGIN_MODULE_GLOBALS(json)    int error_code;ZEND_END_MODULE_GLOBALS(json)
ログイン後にコピー

可以看到json模块并不需要ini配置,它的全局空间只有一个字段error_code。error_code记录了上一次执行json_decode或者json_encode中发生的错误。json_last_error函数便是返回这个error_code,来帮助用户定位错误原因。

为了能够很便捷的访问模块全局空间变量,php约定俗成的提出了一些宏。比如我们想访问json_globals中的error_code,当然可以直接写做json_globals.error_code(多线程环境下不行),不过更通用的写法是定义JSON_G宏:

#define JSON_G(v) (json_globals.v)
ログイン後にコピー

我们使用JSON_G(error_code)来访问json_globals.error_code。本文刚开始的时候,曾提到PG、BG、JSON_G、PCRE_G,XXX_G等等,这些宏在php源代码中也是很常见的。现在我们可以很轻松的理解它们,PG宏可以访问Core模块的全局变量,BG访问Standard模块的全局变量,PCRE_G则访问PCRE模块的全局变量。

#define PG(v) (core_globals.v)#define BG(v) (basic_globals.v)
ログイン後にコピー

2.2,如何确定一个模块需要哪些配置呢?

模块需要什么样的INI配置,都是在各个模块中自己定义的。举例来说,对于Core模块,有如下的配置项定义:

PHP_INI_BEGIN()    ......    STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL,    OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode)    STD_PHP_INI_BOOLEAN("enable_dl",       "1", PHP_INI_SYSTEM, OnUpdateBool,          enable_dl,      php_core_globals, core_globals)    STD_PHP_INI_BOOLEAN("expose_php",      "1", PHP_INI_SYSTEM, OnUpdateBool,          expose_php,     php_core_globals, core_globals)    STD_PHP_INI_BOOLEAN("safe_mode",       "0", PHP_INI_SYSTEM, OnUpdateBool,          safe_mode,      php_core_globals, core_globals)    ......PHP_INI_END()
ログイン後にコピー

可以在php-src\main\main.c文件大概450+行找到上述代码。其中涉及的宏比较多,有ZEND_INI_BEGIN 、ZEND_INI_END、PHP_INI_ENTRY_EX、 STD_PHP_INI_BOOLEAN等等,本文不一一赘述,感兴趣的读者可自行分析。

上述代码进行宏展开后得到:

static const zend_ini_entry ini_entries[] = {    ..    { 0, PHP_INI_ALL,    "display_errors",sizeof("display_errors"),OnUpdateDisplayErrors,(void *)XtOffsetOf(php_core_globals, display_errors), (void *)&core_globals, NULL, "1", sizeof("1")-1, NULL, 0, 0, 0, display_errors_mode },    { 0, PHP_INI_SYSTEM, "enable_dl",     sizeof("enable_dl"),     OnUpdateBool,         (void *)XtOffsetOf(php_core_globals, enable_dl),      (void *)&core_globals, NULL, "1", sizeof("1")-1, NULL, 0, 0, 0, zend_ini_boolean_displayer_cb },    { 0, PHP_INI_SYSTEM, "expose_php",    sizeof("expose_php"),    OnUpdateBool,         (void *)XtOffsetOf(php_core_globals, expose_php),     (void *)&core_globals, NULL, "1", sizeof("1")-1, NULL, 0, 0, 0, zend_ini_boolean_displayer_cb },    { 0, PHP_INI_SYSTEM, "safe_mode",     sizeof("safe_mode"),     OnUpdateBool,         (void *)XtOffsetOf(php_core_globals, safe_mode),      (void *)&core_globals, NULL, "0", sizeof("0")-1, NULL, 0, 0, 0, zend_ini_boolean_displayer_cb },    ...    { 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL }};
ログイン後にコピー

我们看到,配置项的定义,其本质上就是定义了一个zend_ini_entry类型的数组。zend_ini_entry结构体的字段具体含义为:

struct _zend_ini_entry {    int module_number;                // 模块的id    int modifiable;                   // 可被修改的范围,例如php.ini,ini_set    char *name;                       // 配置项的名称    uint name_length;    ZEND_INI_MH((*on_modify));        // 回调函数,配置项注册或修改的时候会调用    void *mh_arg1;                    // 通常为配置项字段在XXX_G中的偏移量    void *mh_arg2;                    // 通常为XXX_G    void *mh_arg3;                    // 通常为保留字段,极少用到    char *value;                      // 配置项的值    uint value_length;    char *orig_value;                 // 配置项的原始值    uint orig_value_length;    int orig_modifiable;              // 配置项的原始modifiable    int modified;                     // 是否发生过修改,如果有修改,则orig_value会保存修改前的值    void (*displayer)(zend_ini_entry *ini_entry, int type);};
ログイン後にコピー

2.3,将配置作用到模块——REGISTER_INI_ENTRIES

经常能够在不同扩展的PHP_MINIT_FUNCTION里看到REGISTER_INI_ENTRIES。REGISTER_INI_ENTRIES主要负责完成两件事情,第一,对模块的全局空间XXX_G进行填充,同步 configuration_hash中的值到XXX_G中去。其次,它还生成了EG(ini_directives)。

REGISTER_INI_ENTRIES也是一个宏,展开之后实则为zend_register_ini_entries方法。具体来看下zend_register_ini_entries的实现:

ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int module_number TSRMLS_DC) /* {{{ */{    // ini_entry为zend_ini_entry类型数组,p为数组中每一项的指针    const zend_ini_entry *p = ini_entry;    zend_ini_entry *hashed_ini_entry;    zval default_value;        // EG(ini_directives)就是registered_zend_ini_directives    HashTable *directives = registered_zend_ini_directives;    zend_bool config_directive_success = 0;        // 还记得ini_entry最后一项固定为{ 0, 0, NULL, ... }么    while (p->name) {        config_directive_success = 0;                // 将p指向的zend_ini_entry加入EG(ini_directives)        if (zend_hash_add(directives, p->name, p->name_length, (void*)p, sizeof(zend_ini_entry), (void **) &hashed_ini_entry) == FAILURE) {            zend_unregister_ini_entries(module_number TSRMLS_CC);            return FAILURE;        }        hashed_ini_entry->module_number = module_number;                // 根据name去configuration_hash中查询,取出来的结果放在default_value中        // 注意default_value的值比较原始,一般是数字、字符串、数组等,具体取决于php.ini中的写法        if ((zend_get_configuration_directive(p->name, p->name_length, &default_value)) == SUCCESS) {            // 调用on_modify更新到模块的全局空间XXX_G中            if (!hashed_ini_entry->on_modify || hashed_ini_entry->on_modify(hashed_ini_entry, Z_STRVAL(default_value), Z_STRLEN(default_value), hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC) == SUCCESS) {                hashed_ini_entry->value = Z_STRVAL(default_value);                hashed_ini_entry->value_length = Z_STRLEN(default_value);                config_directive_success = 1;            }        }        // 如果configuration_hash中没有找到,则采用默认值        if (!config_directive_success && hashed_ini_entry->on_modify) {            hashed_ini_entry->on_modify(hashed_ini_entry, hashed_ini_entry->value, hashed_ini_entry->value_length, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, hashed_ini_entry->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC);        }        p++;    }    return SUCCESS;}
ログイン後にコピー

简单来说,可以把上述代码的逻辑表述为:

1,将模块声明的ini配置项添加到EG(ini_directives)中。注意,ini配置项的值可能在随后被修改。

2,尝试去configuration_hash中寻找各个模块需要的ini。

  • 如果能够找到,说明用户叜ini文件中配置了该值,那么采用用户的配置。
  • 如果没有找到,OK,没有关系,因为模块在声明ini的时候,会带上默认值。

3,将ini的值同步到XX_G里面。毕竟在php的执行过程中,起作用的还是这些XXX_globals。具体的过程是调用每条ini配置对应的on_modify方法完成,on_modify由模块在声明ini的时候进行指定。

我们来具体看下on_modify,它其实是一个函数指针,来看两个具体的Core模块的配置声明:

STD_PHP_INI_BOOLEAN("log_errors",      "0",    PHP_INI_ALL, OnUpdateBool, log_errors,         php_core_globals, core_globals)STD_PHP_INI_ENTRY("log_errors_max_len","1024", PHP_INI_ALL, OnUpdateLong, log_errors_max_len, php_core_globals, core_globals)
ログイン後にコピー

对于log_errors,它的on_modify被设置为OnUpdateBool,对于log_errors_max_len,则on_modify被设置为OnUpdateLong。

进一步假设我们在php.ini中的配置为:

log_errors = Onlog_errors_max_len = 1024
ログイン後にコピー

具体来看下OnUpdateBool函数:

ZEND_API ZEND_INI_MH(OnUpdateBool) {    zend_bool *p;        // base表示core_globals的地址    char *base = (char *) mh_arg2;    // p表示core_globals的地址加上log_errors字段的偏移量    // 得到的即为log_errors字段的地址    p = (zend_bool *) (base+(size_t) mh_arg1);      if (new_value_length == 2 && strcasecmp("on", new_value) == 0) {        *p = (zend_bool) 1;    }    else if (new_value_length == 3 && strcasecmp("yes", new_value) == 0) {        *p = (zend_bool) 1;    }    else if (new_value_length == 4 && strcasecmp("true", new_value) == 0) {        *p = (zend_bool) 1;    }    else {        // configuration_hash中存放的value是字符串"1",而非"On"        // 因此这里用atoi转化成数字1        *p = (zend_bool) atoi(new_value);    }    return SUCCESS;}
ログイン後にコピー

最令人费解的估计就是mh_arg1和mh_arg2了,其实对照前面所述的 zend_ini_entry定义,mh_arg1,mh_arg2还是很容易参透的。 mh_arg1表示字节偏移量, mh_arg2表示XXX_globals的地址。因此,(char *) mh_arg2+mh_arg1的结果即为 XXX_globals中某个字段的地址。具体到本case中,就是计算core _globals中log_errors的地址。因此,当OnUpdateBool最后执行到

*p = (zend_bool) atoi(new_value);

其作用就相当于

core _globals. log_errors= (zend_bool) atoi("1");

分析完了 OnUpdateBool,我们再来看 OnUpdateLong便觉得一目了然:

ZEND_API ZEND_INI_MH(OnUpdateLong){    long *p;    char *base = (char *) mh_arg2;    // 获得log_errors_max_len的地址    p = (long *) (base+(size_t) mh_arg1);    // 将"1024"转化成long型,并赋值给core_globals.log_errors_max_len    *p = zend_atol(new_value, new_value_length);    return SUCCESS;}
ログイン後にコピー

最后需要注意的是,zend_register_ini_entries函数中,如果configuration_hash中存在配置,则当调用on_modify结束后,hashed_ini_entry中的value和value_length会被更新。也就是说,如果用户在php.ini中配置过,则EG(ini_directives)存放的就是实际配置的值。如果用户没配, EG(ini_directives)中存放的是声明zend_ini_entry时给出的默认值。

zend_register_ini_entries中的default_value变量命名比较糟糕,相当容易造成误解。其实default_value并非表示默认值,而是表示用户实际配置的值。

3,总结

至此,三块数据configuration_hash,EG(ini_directives)以及PG、BG、PCRE_G、JSON_G、XXX_G...已经都交代清楚了。

总结一下:

1,configuration_hash,存放php.ini文件里的配置,不做校验,其值为字符串。

2,EG(ini_directives),存放的是各个模块中定义的zend_ini_entry,如果用户在php.ini配置过(configuration_hash中存在),则值被替换为configuration_hash中的值,类型依然是字符串。

3,XXX_G,该宏用于访问模块的全局空间,这块内存空间可用来存放ini配置,并通过on_modify指定的函数进行更新,其数据类型由XXX_G中的字段声明来决定。

更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2016-02/128442p2.htm

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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)

11ベストPHP URLショートナースクリプト(無料およびプレミアム) 11ベストPHP URLショートナースクリプト(無料およびプレミアム) Mar 03, 2025 am 10:49 AM

多くの場合、キーワードと追跡パラメーターで散らかった長いURLは、訪問者を阻止できます。 URL短縮スクリプトはソリューションを提供し、ソーシャルメディアやその他のプラットフォームに最適な簡潔なリンクを作成します。 これらのスクリプトは、個々のWebサイトにとって価値があります

Laravelでフラッシュセッションデータを使用します Laravelでフラッシュセッションデータを使用します Mar 12, 2025 pm 05:08 PM

Laravelは、直感的なフラッシュメソッドを使用して、一時的なセッションデータの処理を簡素化します。これは、アプリケーション内に簡単なメッセージ、アラート、または通知を表示するのに最適です。 データは、デフォルトで次の要求のためにのみ持続します。 $リクエスト -

LaravelのバックエンドでReactアプリを構築する:パート2、React LaravelのバックエンドでReactアプリを構築する:パート2、React Mar 04, 2025 am 09:33 AM

これは、LaravelバックエンドとのReactアプリケーションの構築に関するシリーズの2番目と最終部分です。シリーズの最初の部分では、基本的な製品上場アプリケーションのためにLaravelを使用してRESTFUL APIを作成しました。このチュートリアルでは、開発者になります

Laravelテストでの簡略化されたHTTP応答のモッキング Laravelテストでの簡略化されたHTTP応答のモッキング Mar 12, 2025 pm 05:09 PM

Laravelは簡潔なHTTP応答シミュレーション構文を提供し、HTTP相互作用テストを簡素化します。このアプローチは、テストシミュレーションをより直感的にしながら、コード冗長性を大幅に削減します。 基本的な実装は、さまざまな応答タイプのショートカットを提供します。 Illuminate \ support \ facades \ httpを使用します。 http :: fake([[ 'google.com' => 'hello world'、 'github.com' => ['foo' => 'bar']、 'forge.laravel.com' =>

PHPのカール:REST APIでPHPカール拡張機能を使用する方法 PHPのカール:REST APIでPHPカール拡張機能を使用する方法 Mar 14, 2025 am 11:42 AM

PHPクライアントURL(CURL)拡張機能は、開発者にとって強力なツールであり、リモートサーバーやREST APIとのシームレスな対話を可能にします。尊敬されるマルチプロトコルファイル転送ライブラリであるLibcurlを活用することにより、PHP Curlは効率的なexecuを促進します

Codecanyonで12の最高のPHPチャットスクリプト Codecanyonで12の最高のPHPチャットスクリプト Mar 13, 2025 pm 12:08 PM

顧客の最も差し迫った問題にリアルタイムでインスタントソリューションを提供したいですか? ライブチャットを使用すると、顧客とのリアルタイムな会話を行い、すぐに問題を解決できます。それはあなたがあなたのカスタムにより速いサービスを提供することを可能にします

2025 PHP状況調査の発表 2025 PHP状況調査の発表 Mar 03, 2025 pm 04:20 PM

2025 PHP Landscape Surveyは、現在のPHP開発動向を調査しています。 開発者や企業に洞察を提供することを目的とした、フレームワークの使用、展開方法、および課題を調査します。 この調査では、現代のPHP Versioの成長が予想されています

Laravelの通知 Laravelの通知 Mar 04, 2025 am 09:22 AM

この記事では、Laravel Webフレームワークの通知システムを検討します。 Laravelの通知システムを使用すると、さまざまなチャネルでユーザーに通知を送信できます。今日は、通知ovを送信する方法について説明します

See all articles