Tài nguyên và đối tượng trong PHP là gì?

PHP bao gồm nhiều kiểu dữ liệu khác nhau như integer, double, string giống như nhiều ngôn ngữ lập trình khác. Trong hướng dẫn này, chúng ta sẽ xem các kiểu dữ liệu tài nguyên PHP

Tuy nhiên, không giống như các loại dữ liệu khác, nó hoạt động như một tham chiếu hoặc một mã định danh để truy cập dữ liệu tài nguyên. Ví dụ: khi chúng tôi cố gắng truy cập cơ sở dữ liệu hoặc tài nguyên tệp, chúng tôi có thể có mã định danh tài nguyên. Số nhận dạng này sẽ được sử dụng để móc tài nguyên để truy cập dữ liệu

Ví dụ về lấy dữ liệu tài nguyên

Đoạn mã sau cho biết cách lấy mã định danh tài nguyên cơ sở dữ liệu bằng cách yêu cầu kết nối MySQL. Trong mã này, thông tin cơ sở dữ liệu được chỉ định cho mysqli_connect() và nó trả về đối tượng kết nối MySQL dưới dạng định danh tài nguyên


Khi làm việc với tệp, chúng ta cần lấy mã định danh tài nguyên tệp. với tham chiếu đến mã định danh này, chúng ta có thể thực hiện các thao tác ghi, nối và nhiều thao tác khác trên tệp. Mã PHP sau đây được sử dụng để tạo tham chiếu đối tượng tài nguyên tệp


Sau khi hoàn thành tất cả các thao tác với dữ liệu tài nguyên, kết nối hoặc hook mà chúng ta đã tạo với các tài nguyên bên ngoài sẽ bị xóa. Các hàm PHP sau đây được sử dụng để xóa tham chiếu đối tượng tài nguyên được tạo cho cơ sở dữ liệu và tài nguyên tệp

Mặc dù PHP thực sự có thể loại bỏ loại "tài nguyên", bởi vì lưu trữ đối tượng tùy chỉnh cho phép xây dựng một biểu diễn PHP của bất kỳ loại dữ liệu trừu tượng nào, loại tài nguyên đó vẫn tồn tại trong phiên bản PHP hiện tại và bạn có thể cần xử lý

Nếu bạn cần tạo tài nguyên, chúng tôi thực sự không muốn thúc đẩy bạn làm điều đó mà thay vào đó hãy sử dụng các đối tượng và quản lý lưu trữ tùy chỉnh của chúng. Đối tượng là loại PHP có thể nhúng bất kỳ thứ gì thuộc bất kỳ loại nào. Tuy nhiên, vì những lý do lịch sử, PHP vẫn biết về loại “Resource” đặc biệt đó và vẫn sử dụng nó trong lòng nó hoặc trong một số tiện ích mở rộng. Cùng xem kiểu đó nhé. Tuy nhiên, hãy cẩn thận, nó thực sự khó hiểu và có lịch sử lâu đời, vì vậy đừng ngạc nhiên về thiết kế của nó, đặc biệt là khi đọc mã nguồn về nó

Loại "Tài nguyên" là gì?

Đủ dễ dàng bạn biết về nó. Chúng ta đang nói về điều này ở đây

$fp = fopen('/proc/cpuinfo', 'r');
var_dump($fp); /* resource(2) of type (stream) */

Bên trong, một tài nguyên được liên kết với loại cấu trúc zend_resource

struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};

Chúng tôi tìm thấy tiêu đề zend_refcounted_h truyền thống, nghĩa là tài nguyên có thể đếm được tham chiếu

handle là một số nguyên được công cụ sử dụng nội bộ để định vị tài nguyên trong bảng tài nguyên nội bộ. Nó được sử dụng làm chìa khóa cho một bảng như vậy

type được sử dụng để tập hợp lại các tài nguyên cùng loại với nhau. Đây là cách tài nguyên bị phá hủy và cách chúng được lấy lại từ tay cầm của chúng

Cuối cùng, trường ptr trong zend_resource là dữ liệu trừu tượng của bạn. Hãy nhớ rằng các tài nguyên là về việc lưu trữ một dữ liệu trừu tượng không thể phù hợp với bất kỳ loại dữ liệu nào mà PHP có thể biểu diễn nguyên bản (nhưng các đối tượng thì có thể, như chúng tôi đã nói trước đó)

Các loại tài nguyên và phá hủy tài nguyên

Tài nguyên phải đăng ký một hàm hủy. Khi người dùng sử dụng tài nguyên trong vùng người dùng PHP, họ thường không bận tâm đến việc dọn dẹp những tài nguyên đó khi họ không sử dụng chúng nữa. Ví dụ: không có gì lạ khi thấy cuộc gọi

struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
1 và không thấy cuộc gọi
struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
2 phù hợp. Sử dụng ngôn ngữ C, đây tốt nhất là một ý tưởng tồi, nhiều nhất là một thảm họa. Nhưng sử dụng một ngôn ngữ cấp cao như PHP, bạn sẽ dễ dàng hơn

Bạn, với tư cách là nhà phát triển nội bộ, phải chuẩn bị cho thực tế là người dùng sẽ tạo ra nhiều tài nguyên mà bạn sẽ cho phép anh ta sử dụng mà không làm sạch chúng đúng cách và giải phóng tài nguyên bộ nhớ/hệ điều hành. Do đó, bạn phải đăng ký một hàm hủy sẽ được gọi bất cứ lúc nào công cụ chuẩn bị hủy tài nguyên thuộc loại đó

Các hàm hủy được nhóm theo loại, bản thân các tài nguyên cũng vậy. Bạn sẽ không áp dụng hàm hủy cho tài nguyên thuộc loại 'cơ sở dữ liệu' so với tài nguyên thuộc loại 'tệp'

Cũng tồn tại hai loại tài nguyên, ở đây lại phân biệt về tuổi thọ của chúng

  • Tài nguyên cổ điển, những tài nguyên được sử dụng nhiều nhất, không tồn tại trong một số yêu cầu, hàm hủy của chúng được gọi khi tắt yêu cầu

  • Tài nguyên liên tục sẽ tồn tại trong một số yêu cầu và sẽ chỉ bị hủy khi quá trình PHP chết

Ghi chú

Bạn có thể quan tâm đến chương vòng đời PHP cho bạn thấy các bước khác nhau xảy ra trong vòng đời quy trình của PHP. Ngoài ra, chương Trình quản lý bộ nhớ Zend có thể giúp hiểu các khái niệm về cấp phát bộ nhớ liên tục và theo yêu cầu

Chơi với tài nguyên

API liên quan đến tài nguyên có thể được tìm thấy trong zend/zend_list. c. Bạn có thể tìm thấy một số mâu thuẫn trong đó, chẳng hạn như nói về “danh sách” cho “tài nguyên”

Tạo tài nguyên

Để tạo một tài nguyên, trước tiên người ta phải đăng ký một hàm hủy cho nó và liên kết nó với tên loại tài nguyên bằng cách sử dụng

struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
3. Cuộc gọi đó sẽ trả về một số nguyên đại diện cho loại tài nguyên bạn đăng ký. Bạn phải nhớ số nguyên đó vì sau này bạn sẽ cần nó để lấy lại tài nguyên của mình từ người dùng

Sau đó, bạn có thể đăng ký tài nguyên mới bằng cách sử dụng

struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
4. Cái đó sẽ trả lại cho bạn một zend_resource. Hãy cùng nhau xem một ví dụ về trường hợp sử dụng đơn giản

________số 8_______

Những gì chúng ta làm trong đoạn mã trên là chúng ta mở một tệp bằng cách sử dụng

struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
1 của libc và lưu trữ con trỏ được trả về vào một tài nguyên. Trước đó, chúng tôi đã đăng ký một hàm hủy mà khi được gọi sẽ sử dụng libc's
struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
2 trên con trỏ. Sau đó, chúng tôi đăng ký tài nguyên đối với công cụ và chúng tôi chuyển tài nguyên vào một vùng chứa
struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
8 có thể được trả lại cho vùng người dùng

Ghi chú

Chương Zvals có thể được tìm thấy

Điều phải nhớ là loại tài nguyên. Ở đây, chúng tôi đăng ký một tài nguyên loại “my_res”. Đây là tên loại. Công cụ không thực sự quan tâm đến tên loại, nhưng mã định danh loại, số nguyên được trả về bởi

struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
3. Bạn nên nhớ nó ở đâu đó, giống như chúng ta làm trong biến
#include 

int res_num;
FILE *fp;
zend_resource *my_res;
zval my_val;

static void my_res_dtor(zend_resource *rsrc)
{
    fclose((FILE *)rsrc->ptr);
}

/* module_number should be your PHP extension number here */
res_num = zend_register_list_destructors_ex(my_res_dtor, NULL, "my_res", module_number);
fp      = fopen("/proc/cpuinfo", "r");
my_res  = zend_register_resource((void *)fp, res_num);

ZVAL_RES(&my_val, my_res);
0

Lấy lại tài nguyên

Bây giờ chúng ta đã đăng ký một tài nguyên và đặt nó vào một

struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
8 làm ví dụ, chúng ta nên tìm hiểu cách lấy lại tài nguyên đó từ vùng người dùng. Hãy nhớ rằng, tài nguyên được lưu trữ vào
struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
8. Vào tài nguyên được lưu trữ số loại tài nguyên (trên trường type). Vì vậy, để được trả lại tài nguyên của chúng tôi từ người dùng, chúng tôi phải trích xuất zend_resource từ
struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
8 và gọi
#include 

int res_num;
FILE *fp;
zend_resource *my_res;
zval my_val;

static void my_res_dtor(zend_resource *rsrc)
{
    fclose((FILE *)rsrc->ptr);
}

/* module_number should be your PHP extension number here */
res_num = zend_register_list_destructors_ex(my_res_dtor, NULL, "my_res", module_number);
fp      = fopen("/proc/cpuinfo", "r");
my_res  = zend_register_resource((void *)fp, res_num);

ZVAL_RES(&my_val, my_res);
6 để lấy lại con trỏ
#include 

int res_num;
FILE *fp;
zend_resource *my_res;
zval my_val;

static void my_res_dtor(zend_resource *rsrc)
{
    fclose((FILE *)rsrc->ptr);
}

/* module_number should be your PHP extension number here */
res_num = zend_register_list_destructors_ex(my_res_dtor, NULL, "my_res", module_number);
fp      = fopen("/proc/cpuinfo", "r");
my_res  = zend_register_resource((void *)fp, res_num);

ZVAL_RES(&my_val, my_res);
7 của chúng tôi

/* .. later on .. */

zval *user_zval = /* fetch zval from userland, assume type IS_RESOURCE */

ZEND_ASSERT(Z_TYPE_P(user_zval) == IS_RESOURCE); /* just a check to be sure */

fp = (FILE *)zend_fetch_resource(Z_RESVAL_P(user_zval), "my_res", res_num);

như chúng tôi đã nói. lấy lại một zval từ người dùng (thuộc loại

#include 

int res_num;
FILE *fp;
zend_resource *my_res;
zval my_val;

static void my_res_dtor(zend_resource *rsrc)
{
    fclose((FILE *)rsrc->ptr);
}

/* module_number should be your PHP extension number here */
res_num = zend_register_list_destructors_ex(my_res_dtor, NULL, "my_res", module_number);
fp      = fopen("/proc/cpuinfo", "r");
my_res  = zend_register_resource((void *)fp, res_num);

ZVAL_RES(&my_val, my_res);
8) và lấy lại con trỏ tài nguyên từ nó bằng cách gọi
#include 

int res_num;
FILE *fp;
zend_resource *my_res;
zval my_val;

static void my_res_dtor(zend_resource *rsrc)
{
    fclose((FILE *)rsrc->ptr);
}

/* module_number should be your PHP extension number here */
res_num = zend_register_list_destructors_ex(my_res_dtor, NULL, "my_res", module_number);
fp      = fopen("/proc/cpuinfo", "r");
my_res  = zend_register_resource((void *)fp, res_num);

ZVAL_RES(&my_val, my_res);
6

Hàm đó sẽ kiểm tra xem loại tài nguyên có thuộc loại bạn chuyển làm tham số thứ ba hay không (

#include 

int res_num;
FILE *fp;
zend_resource *my_res;
zval my_val;

static void my_res_dtor(zend_resource *rsrc)
{
    fclose((FILE *)rsrc->ptr);
}

/* module_number should be your PHP extension number here */
res_num = zend_register_list_destructors_ex(my_res_dtor, NULL, "my_res", module_number);
fp      = fopen("/proc/cpuinfo", "r");
my_res  = zend_register_resource((void *)fp, res_num);

ZVAL_RES(&my_val, my_res);
0 tại đây). Nếu có, nó sẽ trích xuất lại con trỏ tài nguyên
/* .. later on .. */

zval *user_zval = /* fetch zval from userland, assume type IS_RESOURCE */

ZEND_ASSERT(Z_TYPE_P(user_zval) == IS_RESOURCE); /* just a check to be sure */

fp = (FILE *)zend_fetch_resource(Z_RESVAL_P(user_zval), "my_res", res_num);
1 mà bạn cần và chúng ta đã hoàn tất. Nếu không, nó sẽ đưa ra một cảnh báo như “tài nguyên được cung cấp không phải là tài nguyên {type name} hợp lệ”. Điều này có thể xảy ra nếu chẳng hạn như bạn mong đợi một tài nguyên thuộc loại “my_res”, và bạn được cung cấp một zval với một tài nguyên thuộc loại “gzip”, giống như tài nguyên được trả về bởi hàm
/* .. later on .. */

zval *user_zval = /* fetch zval from userland, assume type IS_RESOURCE */

ZEND_ASSERT(Z_TYPE_P(user_zval) == IS_RESOURCE); /* just a check to be sure */

fp = (FILE *)zend_fetch_resource(Z_RESVAL_P(user_zval), "my_res", res_num);
2 PHP

Các loại tài nguyên chỉ là một cách để công cụ kết hợp các loại tài nguyên khác nhau (thuộc loại “tệp”, “gzip” hoặc thậm chí “kết nối mysql”) vào cùng một bảng tài nguyên. Các loại tài nguyên có tên, để chúng có thể được sử dụng trong các thông báo lỗi hoặc trong câu lệnh gỡ lỗi (như

/* .. later on .. */

zval *user_zval = /* fetch zval from userland, assume type IS_RESOURCE */

ZEND_ASSERT(Z_TYPE_P(user_zval) == IS_RESOURCE); /* just a check to be sure */

fp = (FILE *)zend_fetch_resource(Z_RESVAL_P(user_zval), "my_res", res_num);
3) và chúng cũng được biểu diễn dưới dạng một số nguyên được sử dụng nội bộ để tìm nạp lại con trỏ tài nguyên từ nó và để đăng ký một hàm hủy với

Ghi chú

Giống như bạn có thể thấy, nếu chúng ta đã sử dụng các đối tượng, thì các đối tượng đó tự đại diện cho các loại và sẽ không phải xảy ra bước tìm nạp lại tài nguyên từ mã định danh xác minh loại của nó. Các đối tượng là các loại tự mô tả. Nhưng tài nguyên vẫn là kiểu dữ liệu hợp lệ cho phiên bản PHP hiện tại

Tài nguyên đếm tham chiếu

Giống như nhiều loại khác, zend_resource được tính tham chiếu. Chúng ta có thể thấy tiêu đề zend_refcounted_h của nó. Đây là API để chơi với tính toán tham chiếu, nếu bạn cần (trung bình bạn không thực sự cần nó)

  • /* .. later on .. */
    
    zval *user_zval = /* fetch zval from userland, assume type IS_RESOURCE */
    
    ZEND_ASSERT(Z_TYPE_P(user_zval) == IS_RESOURCE); /* just a check to be sure */
    
    fp = (FILE *)zend_fetch_resource(Z_RESVAL_P(user_zval), "my_res", res_num);
    
    6 giảm số lượng truy cập lại và phá hủy tài nguyên nếu giảm xuống 0

  • /* .. later on .. */
    
    zval *user_zval = /* fetch zval from userland, assume type IS_RESOURCE */
    
    ZEND_ASSERT(Z_TYPE_P(user_zval) == IS_RESOURCE); /* just a check to be sure */
    
    fp = (FILE *)zend_fetch_resource(Z_RESVAL_P(user_zval), "my_res", res_num);
    
    7 kiểm tra xem số lần đếm ngược có bằng 0 không và hủy tài nguyên nếu đúng

  • /* .. later on .. */
    
    zval *user_zval = /* fetch zval from userland, assume type IS_RESOURCE */
    
    ZEND_ASSERT(Z_TYPE_P(user_zval) == IS_RESOURCE); /* just a check to be sure */
    
    fp = (FILE *)zend_fetch_resource(Z_RESVAL_P(user_zval), "my_res", res_num);
    
    8 gọi hàm hủy tài nguyên bất kể điều kiện là gì

tài nguyên liên tục

Tài nguyên liên tục không bị phá hủy khi kết thúc yêu cầu. Trường hợp sử dụng cổ điển cho các kết nối cơ sở dữ liệu liên tục. Đó là những kết nối được tái chế từ yêu cầu này sang yêu cầu khác (với tất cả những thứ nhảm nhí sẽ mang lại)

Theo truyền thống, bạn không nên sử dụng các tài nguyên liên tục, vì một yêu cầu sẽ khác với yêu cầu kia. Sử dụng lại cùng một tài nguyên nên thực sự được suy nghĩ trước khi đi theo cách này

Để đăng ký tài nguyên liên tục, hãy sử dụng hàm hủy liên tục thay vì tài nguyên cổ điển. Điều này được thực hiện trong lệnh gọi tới

struct _zend_resource {
        zend_refcounted_h gc;
        int               handle;
        int               type;
        void             *ptr;
};
3, API giống như

Tài nguyên trong PHP là gì?

Trong PHP, Tài nguyên là một loại dữ liệu đặc biệt đề cập đến bất kỳ tài nguyên bên ngoài nào . Một biến tài nguyên hoạt động như một tham chiếu đến nguồn dữ liệu bên ngoài như luồng, tệp, cơ sở dữ liệu, v.v. PHP sử dụng các hàm liên quan để tạo các tài nguyên này.

Đối tượng trong PHP là gì?

Đối tượng là một thể hiện riêng lẻ của cấu trúc dữ liệu được định nghĩa bởi một lớp . Chúng tôi định nghĩa một lớp một lần và sau đó tạo nhiều đối tượng thuộc về nó. Các đối tượng còn được gọi là thể hiện.

Đối tượng tài nguyên là gì?

Đối tượng Tài nguyên là một thành viên của bộ sưu tập Tài nguyên . Sử dụng đối tượng tài nguyên Sử dụng tài nguyên (chỉ mục), trong đó chỉ mục là số chỉ mục tài nguyên hoặc tên tài nguyên, để trả về một đối tượng tài nguyên duy nhất. Ví dụ sau liệt kê tên của tất cả các tài nguyên trong dự án đang hoạt động.

Ví dụ về kiểu dữ liệu tài nguyên trong PHP là gì?

Loại tài nguyên đặc biệt không phải là loại dữ liệu thực tế. Nó là nơi lưu trữ tham chiếu đến các hàm và tài nguyên bên ngoài PHP. Một ví dụ phổ biến về việc sử dụng loại dữ liệu tài nguyên là lệnh gọi cơ sở dữ liệu .