2009-11-19 47 views
10

Tôi đã lấy một lớp từ Exception, về cơ bản giống như vậy:truy cập vào biến tin từ hàm thành viên trong PHP

class MyException extends Exception { 

    private $_type; 

    public function type() { 
     return $this->_type; //line 74 
    } 

    public function __toString() { 

     include "sometemplate.php"; 
     return ""; 

    } 

} 

Sau đó, tôi bắt nguồn từ MyException như vậy:

class SpecialException extends MyException { 

    private $_type = "superspecial"; 

} 

Nếu tôi throw new SpecialException("bla") từ một hàm, nắm bắt nó và đi echo $e, sau đó chức năng __toString sẽ tải mẫu, hiển thị và sau đó không thực sự trả về bất kỳ điều gì để lặp lại.

này về cơ bản là những gì trong file template

<div class="<?php echo $this->type(); ?>class"> 

    <p> <?php echo $this->message; ?> </p> 

</div> 

trong tâm trí của tôi, điều này chắc chắn sẽ làm việc. Tuy nhiên, tôi nhận được lỗi sau khi một ngoại lệ được ném và tôi cố gắng để hiển thị nó:

Fatal error: Không thể truy cập tài sản cá nhân SpecialException :: $ _ gõ C: \ path \ to \ trường hợp ngoại lệ. php trên dòng

bất cứ ai có thể giải thích lý do tại sao tôi đang phá vỡ các quy tắc ở đây? Tôi đang làm điều gì đó khủng khiếp dí dỏm với mã này? Có cách nào thành ngữ hơn để xử lý tình huống này không? Điểm của biến số $_type là (như được hiển thị) mà tôi muốn một lớp div khác nhau được sử dụng tùy thuộc vào loại ngoại lệ bị bắt.

+0

Như tôi đã viết ở dưới đó: Nó là rất rất rất xấu xí để cho __toString() trả về một chuỗi rỗng. Tôi thực sự không thể nhìn thấy BẤT CỨ hệ thống của chúng tôi cho những thứ như vậy. – tuergeist

+0

Sự trở lại trống của __toString() cho một ngoại lệ thậm chí còn nghi ngờ hơn. – tuergeist

Trả lời

32

Tên biến bảo vệ:

* Public: anyone either inside the class or outside can access them 
* Private: only the specified class can access them. Even subclasses will be denied access. 
* Protected: only the specified class and subclasses can access them 
+1

+1 thẳng đến điểm – Andrew

+1

Lưu ý: Trong PHP 'protected' có nghĩa là cha mẹ của bạn cũng có thể truy cập chúng. – soulmerge

+0

alright, tôi đã làm điều này - nhưng bây giờ tôi không thể sử dụng '$ this-> message' - không có lỗi, nó chỉ hiển thị không có gì ... tại sao? –

0

Bạn cần phải thiết lập các quyền truy cập vào được bảo vệ. Riêng tư có nghĩa là nó chỉ có thể được truy cập từ bên trong lớp riêng của nó và không thể được kế thừa. Được bảo vệ cho phép nó được hít vào nhưng nó vẫn không thể được truy cập trực tiếp từ bên ngoài lớp.

0

Nếu bạn kiểm tra tài liệu visibility, chôn trong một chú thích là:

// Chúng ta có thể redeclare phương pháp công cộng và bảo vệ, nhưng không tin

Bạn nên làm cho nó protected làm những gì bạn đang cố gắng làm.

Ngẫu nhiên, có vẻ như bạn chỉ cần đặt nó là tên lớp - bạn chỉ có thể sử dụng get_class():

<div class="<?php echo get_class($this); ?>class"> 
+0

, nhưng sau đó nếu tôi đổi tên lớp (php), tôi phải thay đổi tên lớp (css), và nếu muốn sử dụng thêm thông tin trong tệp mẫu ngoại lệ, có lẽ tôi sẽ thêm nó giống như cách tôi đã thêm thuộc tính "type". –

0

Bạn thực sự nên thay đổi accessmodifier để protected khi đó bạn đã builing lớp kế thừa.

Một điểm phụ nữa; không sử dụng return ""; nhưng chỉ cần sử dụng return;

+0

điểm phụ của bạn gây ra lỗi nghiêm trọng, tôi đã thử rằng - '__toString()' ** PHẢI ** trả về một chuỗi –

+0

Ah Tôi xin lỗi! Tôi đã xem xét hàm __toString của bạn .. chỉ thấy bạn đã trở về 'không có gì'. Bạn hoàn toàn đúng! – Ben

+0

Rất rất xấu để cho __toString() trả về một chuỗi rỗng. Tôi thực sự không thể nhìn thấy BẤT CỨ hệ thống của chúng tôi cho những thứ như vậy. Nhưng bạn nói đúng, __toString() phải trả về một chuỗi. – tuergeist

32

chỉ là ví dụ làm thế nào để truy cập vào tài sản cá nhân

<?php 
class foo { 
    private $bar = 'secret'; 
} 
$obj = new foo; 


if (version_compare(PHP_VERSION, '5.3.0') >= 0) 
{ 

     $myClassReflection = new ReflectionClass(get_class($obj)); 
     $secret = $myClassReflection->getProperty('bar'); 
     $secret->setAccessible(true); 
     echo $secret->getValue($obj); 
} 
else 
{ 
    $propname="\0foo\0bar"; 
    $a = (array) $obj; 
    echo $a[$propname]; 
} 
+4

Bạn, thưa bạn, thật tuyệt vời. –

5

Xem câu trả lời của tôi ở đây: https://stackoverflow.com/a/40441769/1889685


Tính đến PHP 5.4, bạn có thể sử dụng lớp Closure được xác định trước để liên kết một phương thức/thuộc tính của một lớp với một hàm delta có quyền truy cập ngay cả đối với các thành viên riêng tư.

The Closure class

Ví dụ chúng ta có một lớp với một biến riêng và chúng tôi muốn truy cập nó bên ngoài lớp:

class Foo { 
    private $bar = "Foo::Bar"; 
} 

PHP 5.4+

$foo = new Foo; 
$getFooBarCallback = function() { 
    return $this->bar; 
}; 

$getFooBar = $getFooBarCallback->bindTo($foo, 'Foo'); 
echo $getFooBar(); // Prints Foo::Bar 

Kể từ PHP 7, bạn có thể sử dụng phương thức mới Closure::call meth od, để ràng buộc bất kỳ phương pháp/tài sản của một obect đến một chức năng gọi lại, ngay cả đối với các thành viên private:

PHP 7+

$foo = new Foo; 
$getFooBar = function() { 
    return $this->bar; 
} 

echo $getFooBar->call($foo); // Prints Foo::Bar 
Các vấn đề liên quan