2010-05-06 9 views
6

Tôi đang cố gắng hiểu về hàm tạo php và hành vi hủy. Mọi thứ diễn ra như mong đợi với các nhà xây dựng nhưng tôi đang gặp rắc rối khi nhận được destructor để cháy ngầm. Ive thực hiện tất cả các đọc trên php.net và các trang web liên quan, nhưng tôi không thể tìm thấy một câu trả lời cho câu hỏi này.hành vi phá hoại php

Nếu tôi có một lớp đơn giản, một cái gì đó như:

class test{ 

    public function __construct(){ 
      print "contructing<br>"; 
    } 

    public function __destruct(){ 
      print "destroying<br>"; 
    } 
} 

và tôi gọi nó với cái gì đó như:

$t = new test; 

nó in thông điệp constructor. Tuy nhiên, tôi hy vọng rằng khi các kịch bản kết thúc và trang được hiển thị mà destructor sẽ cháy. Tất nhiên nó không.

Nếu tôi gọi không được đặt ($ t); khi các kịch bản kết thúc, tất nhiên các destructor cháy, nhưng có cách nào để làm cho nó cháy ngầm?

nhờ cho bất cứ lời khuyên

+3

Chào mừng bạn đến ngăn xếp tràn :) –

Trả lời

4

Các __destruct() chức năng kỳ diệu được thực hiện khi đối tượng này sẽ bị xóa/bị phá hủy (sử dụng unset). Nó không được gọi trong khi tắt kịch bản. Khi một kịch bản PHP kết thúc thực thi, nó dọn sạch bộ nhớ, nhưng nó không xóa các đối tượng như vậy, do đó các phương thức __destruct() không được gọi.

Bạn có thể nghĩ đến số register_shutdown_function(), được kích hoạt khi tập lệnh PHP của bạn kết thúc thực thi.

function shutdown() 
{ 
    // code here 
    echo 'this will be called last'; 
} 

register_shutdown_function('shutdown'); 
+0

alright, cảm ơn cho lời giải thích – kris

+10

Trên thực tế, theo hướng dẫn này không đúng. Xem http://php.net/manual/en/language.oop5.decon.php. "Phương thức destructor sẽ được gọi ngay sau khi tất cả các tham chiếu đến một đối tượng cụ thể được loại bỏ hoặc khi đối tượng bị phá hủy một cách rõ ràng hoặc theo thứ tự bất kỳ trong chuỗi tắt máy." –

+2

Bạn cần phải rất cẩn thận khi cố gắng ghi vào trình duyệt bằng chức năng tắt máy -" Chức năng tắt máy được gọi sau khi đóng tất cả các bộ đệm đầu ra đã mở "- stthuogh stdout vẫn được kết nối, đây có thể không phải là luồng đầu ra bạn đã sử dụng trước đó – symcbean

3

Hiểu biết của tôi là trình tự hủy được tự động gọi cho mọi đối tượng còn lại khi tập lệnh kết thúc.

Nhìn mặc dù manual page on constructors and destructors, có vẻ như cách duy nhất để bỏ qua triệt tiêu hoàn toàn là nếu bạn gọi exit() từ trình phá hủy của đối tượng bị hủy trước đối tượng được đề cập.

Bạn đang sử dụng exit() trong bất kỳ trình hủy nào của mình? Thậm chí có nhiều đối tượng trong tập lệnh của bạn không?

Nếu không quá nhiều sự cố, có thể bạn có thể đăng mã thực tế đang được đề cập chứ không phải mã mẫu bạn có trong câu hỏi của mình ngay bây giờ. Bên cạnh lỗi đánh máy trong trình tạo mẫu của bạn, mã đó phải gọi cả hàm tạo và destructor cho đối tượng test của bạn.

+2

Tôi nghĩ rằng nó phức tạp hơn điều đó.Nếu bạn đặt một 'thoát' trong một destructor thì lần đầu tiên đối tượng được destructed nó sẽ gọi bất kỳ hàm nào được đăng ký với 'register_shutdown_function' và sau đó gọi bất kỳ destructors nào khác.Nếu những destructor đó cũng chứa một' exit' thì script sẽ dừng lại ở đó, tức là, lệnh gọi đầu tiên để thoát ra đặt kịch bản vào chế độ tắt máy, trừ khi lối ra thứ 2 nằm bên trong chức năng tắt máy - đó là một hoạt động nhiều hơn hoặc ít hơn giống như 'trả lại'. – mpen

9

Điều này khá dễ dàng để kiểm tra.

<?php 

class DestructTestDummy { 
    protected $name; 

    function __construct($name) { 
     echo "Constructing $name\n"; 
     $this->name = $name; 
    } 

    function __destruct() { 
     echo "Destructing $this->name\n"; 
     //exit; 
    } 
} 

echo "Start script\n"; 

register_shutdown_function(function() { 
    echo "Shutdown function\n"; 
    //exit 
}); 

$a = new DestructTestDummy("Mr. Unset"); 
$b = new DestructTestDummy("Terminator 1"); 
$c = new DestructTestDummy("Terminator 2"); 

echo "Before unset\n"; 
unset($a); 
echo "After unset\n"; 


echo "Before func\n"; 
call_user_func(function() { 
    $c = new DestructTestDummy("Mrs. Scopee"); 
}); 
echo "After func\n"; 

$b->__destruct(); 

exit("Exiting\n"); 

Trong PHP 5.5.12 in này:

Start script 
Constructing Mr. Unset 
Constructing Terminator 1 
Constructing Terminator 2 
Before unset 
Destructing Mr. Unset 
After unset 
Before func 
Constructing Mrs. Scopee 
Destructing Mrs. Scopee 
After func 
Destructing Terminator 1 
Exiting 
Shutdown function 
Destructing Terminator 2 
Destructing Terminator 1 

Vì vậy, chúng ta có thể thấy rằng các destructor được gọi khi chúng tôi một cách rõ ràng unset đối tượng, khi nó đi ra khỏi phạm vi, khi tập lệnh kết thúc.