我们知道定义SAPI之前,首先要定义sapi_module_struct这个结构,相看源码:/soft/php-5.2.9/sapi/apache2handler/sapi_apache2.c,可以看到定义该结构,我直接复制过来:
[cpp]
static sapi_module_struct apache2_sapi_module = {
"apache2handler",
"Apache 2.0 Handler",
php_apache2_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
NULL, /* activate */
NULL, /* deactivate */
php_apache_sapi_ub_write, /* unbuffered write */
php_apache_sapi_flush, /* flush */
php_apache_sapi_get_stat, /* get uid */
php_apache_sapi_getenv, /* getenv */
php_error, /* error handler */
php_apache_sapi_header_handler, /* header handler */
php_apache_sapi_send_headers, /* send headers handler */
NULL, /* send header handler */
php_apache_sapi_read_post, /* read POST data */
php_apache_sapi_read_cookies, /* read Cookies */
php_apache_sapi_register_variables,
php_apache_sapi_log_message, /* Log message */
php_apache_sapi_get_request_time, /* Request Time */
STANDARD_SAPI_MODULE_PROPERTIES
};
1,php_apache2_startup:当通过apache调用PHP时,这个函数会被调用。该函数定义如下,主要是对PHP进行初始化。
[cpp]
static int php_apache2_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(sapi_module, &php_apache_module, 1)==FAILURE) {
return FAILURE;
}
return SUCCESS;
}
2,php_module_shutdown_wrapper :PHP的关闭函数。
3,PHP会在每个request的时候,处理一些初始化,资源分配的事务。这部分就是activate字段要定义的。
4,与activate的函数,就是deactiveate,它会提供一个handler, 用来处理收尾工作。
5,php_apache_sapi_ub_write:提供一个向Response数据写的接口。
[cpp]
static int
php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
{
request_rec *r;
php_struct *ctx;
ctx = SG(server_context);
r = ctx->r;
if (ap_rwrite(str, str_length, r)
php_handle_aborted_connection();
}
return str_length; /* we always consume all the data passed to us. */
}
6,php_apache_sapi_flush:提供给zend刷新缓存的句柄。
[cpp]
static void
php_apache_sapi_flush(void *server_context)
{
php_struct *ctx;
request_rec *r;
TSRMLS_FETCH();
ctx = server_context;
/* If we haven't registered a server_context yet,
* then don't bother flushing. */
if (!server_context) {
return;
}
r = ctx->r;
sapi_send_headers(TSRMLS_C);
r->status = SG(sapi_headers).http_response_code;
SG(headers_sent) = 1;
if (ap_rflush(r) connection->aborted) {
php_handle_aborted_connection();
}
}
7,php_apache_sapi_get_stat:这部分用来让Zend可以验证一个要执行脚本文件的state,从而判断文件是否据有执行权限等等。
[cpp]
static struct stat*
php_apache_sapi_get_stat(TSRMLS_D)
{
php_struct *ctx = SG(server_context);
ctx->finfo.st_uid = ctx->r->finfo.user;
ctx->finfo.st_gid = ctx->r->finfo.group;
ctx->finfo.st_dev = ctx->r->finfo.device;
ctx->finfo.st_ino = ctx->r->finfo.inode;
#if defined(NETWARE) && defined(CLIB_STAT_PATCH)
ctx->finfo.st_atime.tv_sec = apr_time_sec(ctx->r->finfo.atime);
ctx->finfo.st_mtime.tv_sec = apr_time_sec(ctx->r->finfo.mtime);
ctx->finfo.st_ctime.tv_sec = apr_time_sec(ctx->r->finfo.ctime);
#else
ctx->finfo.st_atime = apr_time_sec(ctx->r->finfo.atime);
ctx->finfo.st_mtime = apr_time_sec(ctx->r->finfo.mtime);
ctx->finfo.st_ctime = apr_time_sec(ctx->r->finfo.ctime);
#endif
ctx->finfo.st_size = ctx->r->finfo.size;
ctx->finfo.st_nlink = ctx->r->finfo.nlink;
return &ctx->finfo;
}
8,php_apache_sapi_getenv:为Zend提供了一个根据name来查找环境变量的接口,当我们在脚本中调用getenv的时候,就会间接的调用这个句柄。
[cpp]
static char *
php_apache_sapi_getenv(char *name, size_t name_len TSRMLS_DC)
{
php_struct *ctx = SG(server_context);
const char *env_var;
env_var = apr_table_get(ctx->r->subprocess_env, name);
return (char *) env_var;
}
9,php_error:错误处理函数,直接调用PHP错误处理函数。
10,php_apache_sapi_header_handler:在调用PHP的header()函数时,会调用这个函数。
[cpp]
static int
php_apache_sapi_header_handler(sapi_header_struct *sapi_header,sapi_headers_struct *sapi_headers TSRMLS_DC)
{
php_struct *ctx;
char *val, *ptr;
ctx = SG(server_context);
val = strchr(sapi_header->header, ':');
if (!val) {
sapi_free_header(sapi_header);
return 0;
}
ptr = val;
*val = '\0';
do {
val++;
} while (*val == ' ');
if (!strcasecmp(sapi_header->header, "content-type")) {
if (ctx->content_type) {
efree(ctx->content_type);
}
ctx->content_type = estrdup(val);
} else if (sapi_header->replace) {
apr_table_set(ctx->r->headers_out, sapi_header->header, val);
} else {
apr_table_add(ctx->r->headers_out, sapi_header->header, val);
}
*ptr = ':';
return SAPI_HEADER_ADD;
}
11,php_apache_sapi_send_headers:当要真正发送header的时候,这个函数会被调用。
[cpp]
static int
php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
php_struct *ctx = SG(server_context);
const char *sline = SG(sapi_headers).http_status_line;
ctx->r->status = SG(sapi_headers).http_response_code;
/* httpd requires that r->status_line is set to the first digit of
* the status-code: */
if (sline && strlen(sline) > 12 && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') {
ctx->r->status_line = apr_pstrdup(ctx->r->pool, sline + 9);
ctx->r->proto_num = 1000 + (sline[7]-'0');
if ((sline[7]-'0') == 0) {
apr_table_set(ctx->r->subprocess_env, "force-response-1.0", "true");
}
}
/* call ap_set_content_type only once, else each time we call it,
configured output filters for that content type will be added */
if (!ctx->content_type) {
ctx->content_type = sapi_get_default_content_type(TSRMLS_C);
}
ap_set_content_type(ctx->r, apr_pstrdup(ctx->r->pool, ctx->content_type));
efree(ctx->content_type);
ctx->content_type = NULL;
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
12,在php_apache_sapi_send_headers指针下面有一个域,用来指明发送每一个单独的header时调用。
13,php_apache_sapi_read_post:表示如何读取POST数据。
[cpp]
static int
php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
{
apr_size_t len, tlen=0;
php_struct *ctx = SG(server_context);
request_rec *r;
apr_bucket_brigade *brigade;
r = ctx->r;
brigade = ctx->brigade;
len = count_bytes;
/*
* This loop is needed because ap_get_brigade() can return us partial data
* which would cause premature termination of request read. Therefor we
* need to make sure that if data is available we fill the buffer completely.
*/
while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
apr_brigade_flatten(brigade, buf, &len);
apr_brigade_cleanup(brigade);
tlen += len;
if (tlen == count_bytes || !len) {
break;
}
buf += len;
len = count_bytes - tlen;
}
return tlen;
}
14,php_apache_sapi_read_cookie:如何读取cookie。
[cpp]
static char *
php_apache_sapi_read_cookies(TSRMLS_D)
{
php_struct *ctx = SG(server_context);
const char *http_cookie;
http_cookie = apr_table_get(ctx->r->headers_in, "cookie");
/* The SAPI interface should use 'const char *' */
return (char *) http_cookie;
}
15,php_apache_sapi_register_variables:提供接口,用于给$_SERVER[]数组提供变量。
[cpp]
static void
php_apache_sapi_register_variables(zval *track_vars_array TSRMLS_DC)
{
php_struct *ctx = SG(server_context);
const apr_array_header_t *arr = apr_table_elts(ctx->r->subprocess_env);
char *key, *val;
int new_val_len;
APR_ARRAY_FOREACH_OPEN(arr, key, val)
if (!val) {
val = "";
}
if (sapi_module.input_filter(PARSE_SERVER, key, &val, strlen(val), &new_val_len TSRMLS_CC)) {
php_register_variable_safe(key, val, new_val_len, track_vars_array TSRMLS_CC);
}
APR_ARRAY_FOREACH_CLOSE()
if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &ctx->r->uri, strlen(ctx->r->uri), &new_val_len TSRMLS_CC)) {
php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array TSRMLS_CC);
}
}
16,php_apache_sapi_log_message:输出错误信息。
[cpp]
static void php_apache_sapi_log_message(char *msg)
{
php_struct *ctx;
TSRMLS_FETCH();
ctx = SG(server_context);
if (ctx == NULL) { /* we haven't initialized our ctx yet, oh well */
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "%s", msg);
} else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, "%s", msg);
}
}
17,php_apache_sapi_get_request_time:获取请求时间。
[cpp]
static time_t php_apache_sapi_get_request_time(TSRMLS_D) {
php_struct *ctx = SG(server_context);
return apr_time_sec(ctx->r->request_time);
}
这就完成了apache的SAPI定义。之后,就是当用户用URL请求apache服务,这些函数指针就会在适当的时候,发挥作用了(被调用)。

여전히 인기있는 것은 사용 편의성, 유연성 및 강력한 생태계입니다. 1) 사용 편의성과 간단한 구문은 초보자에게 첫 번째 선택입니다. 2) 웹 개발, HTTP 요청 및 데이터베이스와의 우수한 상호 작용과 밀접하게 통합되었습니다. 3) 거대한 생태계는 풍부한 도구와 라이브러리를 제공합니다. 4) 활성 커뮤니티와 오픈 소스 자연은 새로운 요구와 기술 동향에 맞게 조정됩니다.

PHP와 Python은 웹 개발, 데이터 처리 및 자동화 작업에 널리 사용되는 고급 프로그래밍 언어입니다. 1.PHP는 종종 동적 웹 사이트 및 컨텐츠 관리 시스템을 구축하는 데 사용되며 Python은 종종 웹 프레임 워크 및 데이터 과학을 구축하는 데 사용됩니다. 2.PHP는 Echo를 사용하여 콘텐츠를 출력하고 Python은 인쇄를 사용합니다. 3. 객체 지향 프로그래밍을 지원하지만 구문과 키워드는 다릅니다. 4. PHP는 약한 유형 변환을 지원하는 반면, 파이썬은 더 엄격합니다. 5. PHP 성능 최적화에는 Opcache 및 비동기 프로그래밍 사용이 포함되며 Python은 Cprofile 및 비동기 프로그래밍을 사용합니다.

PHP는 주로 절차 적 프로그래밍이지만 객체 지향 프로그래밍 (OOP)도 지원합니다. Python은 OOP, 기능 및 절차 프로그래밍을 포함한 다양한 패러다임을 지원합니다. PHP는 웹 개발에 적합하며 Python은 데이터 분석 및 기계 학습과 같은 다양한 응용 프로그램에 적합합니다.

PHP는 1994 년에 시작되었으며 Rasmuslerdorf에 의해 개발되었습니다. 원래 웹 사이트 방문자를 추적하는 데 사용되었으며 점차 서버 측 스크립팅 언어로 진화했으며 웹 개발에 널리 사용되었습니다. Python은 1980 년대 후반 Guidovan Rossum에 의해 개발되었으며 1991 년에 처음 출시되었습니다. 코드 가독성과 단순성을 강조하며 과학 컴퓨팅, 데이터 분석 및 기타 분야에 적합합니다.

PHP는 웹 개발 및 빠른 프로토 타이핑에 적합하며 Python은 데이터 과학 및 기계 학습에 적합합니다. 1.PHP는 간단한 구문과 함께 동적 웹 개발에 사용되며 빠른 개발에 적합합니다. 2. Python은 간결한 구문을 가지고 있으며 여러 분야에 적합하며 강력한 라이브러리 생태계가 있습니다.

PHP는 현대화 프로세스에서 많은 웹 사이트 및 응용 프로그램을 지원하고 프레임 워크를 통해 개발 요구에 적응하기 때문에 여전히 중요합니다. 1.PHP7은 성능을 향상시키고 새로운 기능을 소개합니다. 2. Laravel, Symfony 및 Codeigniter와 같은 현대 프레임 워크는 개발을 단순화하고 코드 품질을 향상시킵니다. 3. 성능 최적화 및 모범 사례는 응용 프로그램 효율성을 더욱 향상시킵니다.

phphassignificallyimpactedwebdevelopmentandextendsbeyondit

PHP 유형은 코드 품질과 가독성을 향상시키기위한 프롬프트입니다. 1) 스칼라 유형 팁 : PHP7.0이므로 int, float 등과 같은 기능 매개 변수에 기본 데이터 유형을 지정할 수 있습니다. 2) 반환 유형 프롬프트 : 기능 반환 값 유형의 일관성을 확인하십시오. 3) Union 유형 프롬프트 : PHP8.0이므로 기능 매개 변수 또는 반환 값에 여러 유형을 지정할 수 있습니다. 4) Nullable 유형 프롬프트 : NULL 값을 포함하고 널 값을 반환 할 수있는 기능을 포함 할 수 있습니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SecList
SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경
