2010-08-25 30 views
53

Hãy cho tôi một số ví dụ thực tế khi bạn phải sử dụng __destruct trong lớp học của bạn.Php Destructors

+23

Tại sao số phiếu gần? Câu hỏi không phải là IMO khủng khiếp: Nó yêu cầu sử dụng trong thế giới thực, trong đó không có * nhiều * trong PHP, vì hầu hết các tài nguyên và kết nối đều tự động đóng lại. –

+2

câu hỏi này nên được đánh dấu là wiki cộng đồng – tamasd

+2

Tôi đã bỏ phiếu cho Pekka, tôi đã bỏ phiếu tán thành daniphp và đánh dấu câu hỏi là yêu thích, chỉ vì tôi nghĩ Yorirou là sai :) – RobertPitt

Trả lời

38

Ok, vì câu trả lời cuối cùng của tôi dường như không đánh dấu, hãy để tôi thử lại lần nữa. Có rất nhiều tài nguyên và ví dụ trên internet cho chủ đề này. Làm một chút tìm kiếm và duyệt mã của khuôn khổ khác và bạn sẽ thấy một số ví dụ khá hay ...

Đừng quên rằng chỉ vì PHP sẽ đóng tài nguyên khi chấm dứt cho bạn không có nghĩa là nó rất tệ để khám phá đóng chúng khi bạn không cần chúng nữa (hoặc tốt để không đóng chúng) ... Nó phụ thuộc vào trường hợp sử dụng (là nó được sử dụng ngay đến cuối, hoặc là có một cuộc gọi sớm và sau đó không cần thiết một lần nữa cho phần còn lại của thực hiện) ...

Bây giờ, chúng ta biết rằng __destruct được gọi khi đối tượng bị hủy. Về mặt logic, điều gì sẽ xảy ra nếu đối tượng bị phá hủy? Vâng, nó có nghĩa là nó không còn nữa. Vì vậy, nếu nó có nguồn lực mở, nó không có ý nghĩa để đóng những nguồn lực như nó đang bị phá hủy? Chắc chắn, trong trang web trung bình, trang sẽ chấm dứt ngay sau đó, vì vậy hãy để PHP đóng chúng thường không phải là khủng khiếp. Tuy nhiên, điều gì sẽ xảy ra nếu vì một lý do nào đó tập lệnh dài hạn? Sau đó, bạn có một rò rỉ tài nguyên. Vì vậy, tại sao không chỉ đóng tất cả mọi thứ khi bạn không còn cần nó (hoặc xem xét phạm vi của destructor, khi nó không còn có sẵn)?

Dưới đây là một số ví dụ trong khuôn khổ thế giới thực:

  1. Lithium's lithium\net\Socket class
  2. Kohana's Memcached Driver
  3. Joomla's FTP Implementation
  4. CodeIgniter's TTemplate Class
  5. A Tidy Filter Helper for Cake
  6. A Google-Groups Thread about using Destructors For the Symfony Session Class

Điều thú vị là Kohana theo dõi các thẻ, để nó có thể xóa bằng cách "namespace" sau (thay vì chỉ xóa bộ nhớ cache). Vì vậy, nó sử dụng destructor để tuôn ra những thay đổi để lưu trữ cứng.

Lớp CodeIgniter cũng làm điều gì đó thú vị ở chỗ nó thêm đầu ra gỡ lỗi vào luồng đầu ra trong trình phá hủy. Tôi không nói điều này là tốt, nhưng đó là một ví dụ về việc sử dụng khác ...

Cá nhân tôi sử dụng các trình phá hủy bất cứ khi nào tôi có các quy trình chạy dài trên bộ điều khiển chính của mình. Trong hàm tạo, tôi kiểm tra tệp pid. Nếu tệp đó tồn tại (Và quá trình của nó vẫn đang chạy), tôi ném một ngoại lệ. Nếu không, tôi tạo một tệp với id quy trình hiện tại. Sau đó, trong destructor tôi loại bỏ tập tin đó. Vì vậy, nó thêm về dọn dẹp sau khi bản thân hơn các nguồn lực chỉ giải phóng ...

+2

Công việc rất hay. +1 –

+0

Yêu thích danh sách liên kết bao gồm một mảng các phần mềm PHP đã biết. – markus

+0

Danh sách đầy đủ các ca sử dụng +1 cho rằng –

4

Tôi tạo trang php sẽ tạo tệp jpg thông tin phim. Trang này sẽ phải thu thập một vài thông tin và chạy inkscape để chuyển đổi mẫu (tệp svg) thành png trước khi chuyển sang jpg. Svg chứa liên kết tương đối với hình ảnh khác phải là tệp. Vì vậy, trang của tôi tải xuống các tệp cần thiết vào một thư mục tạm thời, chuyển đổi tệp svg. Cuối cùng, thư mục tạm thời phải được xóa.

Tôi đặt xóa thư mục tạm thời vào trình phá hủy. Trước khi có thể có nhiều lý do trang kết thúc bất ngờ và chỉ nghĩ rằng tôi có thể chắc chắn là destructor sẽ được gọi khi thoát trang.

Hy vọng điều này sẽ hữu ích.

3

Tôi sử dụng bộ nhớ đệm APC cho số lượng lớn các đối tượng "cấp thấp", nếu không sẽ sử dụng bộ nhớ quá mức; và tôi có một đối tượng cacheCollection xử lý việc đọc và ghi các đối tượng "mức thấp" đó đến và từ APC trong khi thực thi kịch bản lệnh. Khi kịch bản kết thúc, các đối tượng phải được xóa khỏi APC, vì vậy tôi sử dụng phương thức cacheCollection __destruct để thực hiện chức năng đó.

+0

Bạn đang đùa tôi - downvote để cung cấp một ví dụ thực tế cuộc sống của việc sử dụng của riêng tôi, khi đó là những gì các câu hỏi yêu cầu? Bạn có thể tranh luận rằng đó là một cách sử dụng không phù hợp, nhưng nó chắc chắn là một cách sử dụng thực tế trong cuộc sống "trong tự nhiên", đó chính xác là những gì OP yêu cầu. –

4

Trình phá hủy cực kỳ hữu ích nếu bạn sử dụng trình kết nối/trình bao bọc cơ sở dữ liệu tùy chỉnh.

Trong hàm tạo, bạn có thể chuyển thông tin kết nối. Bởi vì bạn có thể sử dụng một destructor (thay vì một finalizer, vv,), bạn có thể dựa vào đó để đóng kết nối cho bạn. Đó là một sự tiện lợi, nhưng nó chắc chắn là hữu ích.

Ví dụ: khi PHP quyết định rõ ràng "miễn phí" đối tượng (tức là, nó không còn được sử dụng nữa), nó sẽ gọi hàm hủy tại thời điểm đó. Điều này hữu ích hơn trong kịch bản mà tôi mô tả khi bạn không đợi bộ thu gom rác chạy và gọi trình hoàn tất.

$ 0,02

Ian

4
<?php 
class Database 
{ 
    private $connection; 
    private $cache = array(); 

    function __construct([$params]) 
    { 
     //Connection here 
    } 

    //Query 
    public function query(Query $Query) 
    { 
     if($this->is_cached($Query->checksum)) 
     { 
      return $this->get_cache($Query->checksum); 
     } 
     //... 
    } 
    public function __destruct() 
    { 
     unset($this->connection); 
     $this->WriteCache(); 
     unset($this->cache); 
     shutdown_log($this,'Destruction Completed'); 
    } 
} 
?> 

theres một ví dụ rằng nên làm cho bạn hiểu.

4

Nếu bạn sử dụng xử lý được trả về bởi fopen() cho biết, khai thác gỗ, bạn có thể sử dụng __destruct() để đảm bảo fclose() đang kêu gọi các nguồn lực của chúng tôi khi lớp học của bạn bị phá hủy.

4

Bạn nói đúng, __destruct hầu như không cần thiết cho các tập lệnh php chạy ngắn. Kết nối cơ sở dữ liệu, xử lý tệp, v.v. đóng trên lối ra tập lệnh hoặc đôi khi thậm chí sớm hơn nếu các biến hết phạm vi.

Một ví dụ tôi có thể nghĩ là ghi nhật ký vào cơ sở dữ liệu. Vì chúng tôi không muốn kích hoạt một truy vấn cho mỗi mục nhật ký được tạo ở đâu đó trong kịch bản, chúng tôi đã viết phần "write to db" trong __destruct của lớp logging vì vậy khi kịch bản kết thúc mọi thứ được chèn vào cơ sở dữ liệu tại một.

Một ví dụ khác: Nếu bạn cho phép người dùng upload file destructor là đôi khi một nơi tốt đẹp để xóa các tập tin tạm thời (trong trường hợp họ gặp khó khăn trong kịch bản nó ít nhất được dọn dẹp)

Nhưng ngay cả đối với filehandles nó có thể hữu ích. Tôi đã làm việc trên một ứng dụng đã sử dụng các cuộc gọi fopen cũ vv được bao bọc trong các đối tượng và khi sử dụng những tập tin lớn trên filetrees php sẽ sớm hết tập tin, vì vậy hãy dọn dẹp trong khi kịch bản đang chạy không chỉ đẹp mà còn cần thiết .

2

Tôi đã sử dụng __destruct() trong một lớp học khai thác gỗ mà quấn một kết nối cơ sở dữ liệu:

<?php 

class anyWrap 
{ 
    private $obj,$calls,$log,$hooks; 
    function anyWrap($obj, $logfile = NULL) 
    { 
     if(is_null($logfile)) 
     { 
     $this->log = dirname(__FILE__) . "/../logs/wrapLog.txt"; 
     } 
     $this->hooks = array(); 
     $this->dbCalls = 0; 
     $this->obj = $obj; 
    } 

    public function __set($attri, $val) { 
     $this->obj->$attri = $val; 
    } 

    public function __get($attri) {  
     return $this->obj->$attri; 
    } 
    public function __hook($method) 
    { 
    $this->hooks[] = $method; 
    } 


    public function __call($name,$args) 
    { 
     $this->calls++; 
     if(in_array($name,$this->hooks)) 
     { 
      file_put_contents($this->log,var_export($args,TRUE)."\r\n",FILE_APPEND); 
     } 
     return call_user_func_array(array($this->obj,$name),$args); 
    } 
    //On destruction log diagnostics 
    public function __destruct() 
    { 
     unset($this->dbReal); 
     file_put_contents($this->log,$this->calls."\r\n",FILE_APPEND); 
    } 
} 

Các móc script vào các cuộc gọi cơ sở dữ liệu và ghi lại những báo cáo chuẩn bị, sau đó khi kịch bản đã chạy đến một kết thúc (I don 't luôn luôn biết khi nào) nó cuối cùng sẽ đăng nhập số lượng các cuộc gọi đến cơ sở dữ liệu vào tập tin. Bằng cách này tôi có thể thấy bao nhiêu lần một số chức năng đã được gọi trên cơ sở dữ liệu và lập kế hoạch tối ưu hóa của tôi cho phù hợp.

1

Nếu bạn đang tạo một xem sử dụng một kịch bản PHP trong một cơ sở dữ liệu MySQL , bạn phải thả rằng xem ở phần cuối của kịch bản. Bởi vì nếu không, lần tiếp theo kịch bản lệnh được thực thi sẽ không được tạo, vì đã có một khung nhìn có tên tương tự trong cơ sở dữ liệu. Với mục đích này, bạn có thể sử dụng destructor.

+1

Giả sử bạn đang đề cập đến một khung nhìn cơ sở dữ liệu, tại sao bạn sẽ tạo nó mỗi chu kỳ thực thi (và thả nó sau mỗi lần chạy)? Tại sao không chỉ tạo ra nó một lần và để nó ở đó? Như một quy tắc của họ mã sản xuất không nên chạy với một đặc quyền 'CREATE' hoặc' DROP', nhưng một mình được làm điều đó trên mỗi yêu cầu ... Hoặc tôi đã hiểu lầm những gì bạn có nghĩa là? (Nếu không, nó là một ví dụ hợp lệ về việc sử dụng cho một destructor, vì vậy không có -1) ... – ircmaxell

5

Ví dụ:

<?php 
class Session 
{ 
    protected $data = array(); 

    public function __construct() 
    { 
     // load session data from database or file 
    } 

    // get and set functions 

    public function __destruct() 
    { 
     // store session data in database or file 
    } 
}; 

Đây là một lý do tại sao tốt để sử dụng hủy. Bạn luôn ngăn việc đọc và ghi vào nguồn phiên và chỉ thực hiện điều này ngay từ đầu và cuối.

17

Có một ứng dụng tiện lợi để tạo ra mã HTML của trang

class HTMLgenerator { 
    function __construct() { 
    echo "<html><body>"; 
    } 
    function __destruct() { 
    echo "</body></html>"; 
    } 
} 

Với lớp này, bạn có thể viết

$html = new HTMLgenerator(); 
echo "Hello, world!"; 

Và kết quả là

<html><body>Hello, world!</body></html> 
+8

Tôi không nghĩ rằng điều này nên được sử dụng trong thế giới thực, trông giống như một hack. Phụ thuộc vào cách sử dụng rất cụ thể. Tôi sẽ chỉ triển khai HTMLgenerator khi lấy một số HTML trong hàm tạo của nó và ghi đè lên phương thức toString. Người gọi có thể chỉ đơn giản nói "echo new HTMLGenerator()'. Nếu bạn sử dụng mẫu âm thanh _destructor này, bạn nên sử dụng nó ở một nơi duy nhất, hoặc bạn sẽ ở địa ngục cố gắng tìm ra khi nào mọi thứ sẽ được xuất ra. Nói tóm lại, đó là lạm dụng tính năng. –

+0

Tôi đồng ý. Nó chỉ là một ý tưởng, nó có thể gọi một số suy nghĩ tuyệt vời trong một số tâm trí rực rỡ, vì vậy hãy để exot này sống :-) –

Các vấn đề liên quan