ReflectionClass trong PHP là gì?

Bạn đã bao giờ dành thời gian để đọc mã của khung hoặc thư viện PHP yêu thích của mình chưa? . Và, nếu bạn không đọc mã của người khác, bạn nên bắt đầu làm việc đó. (Đó là một công cụ học tập tuyệt vời. )

Bây giờ, hãy quay lại API phản chiếu. Đây là một API được các nhà phát triển framework và thư viện sử dụng khá nhiều. Nhưng điều buồn cười là nó hầu như không bao giờ được nói đến khi bạn đang tìm kiếm các tài nguyên để học PHP. (Hoặc thậm chí là các tài nguyên PHP nâng cao cho vấn đề đó. )

Điều này là không may. Đó là bởi vì API phản chiếu của PHP phục vụ một mục đích duy nhất và quan trọng. Đó là lý do tại sao các nhà phát triển xây dựng các khung và thư viện của chúng tôi sử dụng nó rất nhiều

Phản xạ là gì?

Tại thời điểm này, rất có thể bạn đang tự nhủ: “Tất nhiên, tôi không biết API phản chiếu của PHP. Tôi thậm chí không biết ý của bạn là gì khi phản ánh. ” Đó là một phản ứng hợp lý để có. (Lỗi của tôi. ) Đó là lần đầu tiên tôi gặp mã sử dụng phản xạ

Hãy bắt đầu bằng cách xem xét khái niệm phản ánh. Điều đầu tiên bạn nên biết là khái niệm phản chiếu không dành riêng cho PHP. Đó là một khái niệm xuất phát từ khoa học máy tính

Được rồi, ổn thôi. Nhưng khái niệm phản chiếu bí ẩn này là gì?

Nếu điều đó nghe có vẻ nhanh, đó là bởi vì nó là. Chúng ta thường nghĩ mã của mình là thứ gì đó tĩnh. Sau khi bạn lưu và thực thi nó, không có cách nào để thay đổi nó. Nhưng điều đó không đúng. Và phản xạ là cơ chế mà bạn sử dụng để thực hiện các thay đổi đối với mã của mình khi mã đang chạy

Mặc dù ngày nay nghe có vẻ điên rồ khi bạn muốn chỉnh sửa mã của mình khi nó đang chạy, nhưng không phải lúc nào cũng vậy. Quay lại khi các lập trình viên thường lập trình bằng hợp ngữ, điều này khá phổ biến. Trên thực tế, việc kiểm tra mã của bạn và sửa đổi khi nó chạy là thuộc tính vốn có của hợp ngữ

Tính chất này của hợp ngữ không còn nữa khi các ngôn ngữ biên dịch đầu tiên xuất hiện. Nhưng cuối cùng nó đã xuất hiện trở lại thông qua khái niệm phản ánh. Và bây giờ rất nhiều ngôn ngữ lập trình hỗ trợ nó

Bạn sử dụng chúng để làm gì?

Vì vậy, đó là một số lịch sử đằng sau khái niệm phản ánh. Nhưng điều này không thực sự giúp bạn hiểu bạn sẽ sử dụng nó để làm gì. Hoặc thậm chí tại sao nó thậm chí còn hữu ích. Rốt cuộc, bạn đã không sử dụng nó trong một thời gian rồi

Việc sử dụng phổ biến nhất để phản ánh là để thử nghiệm. Khi bạn đang kiểm tra mã của mình, bạn thường cần kiểm tra và sửa đổi mã khi nó đang chạy. Đó cũng là cách các khung kiểm tra đơn vị có xu hướng tạo ra các bản mô phỏng các lớp và chức năng của bạn

Nó cũng tuyệt vời cho các tình huống mà bạn muốn phân tích mã và tự động hóa một số tác vụ xung quanh nó. Ví dụ: các thư viện tạo tài liệu có thể sử dụng phản xạ để tạo tài liệu cho mã của bạn. Đó cũng là cách rất nhiều bộ chứa tiêm phụ thuộc đưa các phụ thuộc vào các đối tượng mà chúng tạo ra

Điều đó nói rằng, như chúng ta sẽ thấy trong suốt bài viết, có rất nhiều cách sử dụng duy nhất cho sự phản chiếu. Chúng không phải lúc nào cũng phù hợp với các danh mục gọn gàng như những danh mục chúng tôi vừa đề cập. Nhưng điểm chung của chúng là chúng sử dụng phản xạ để kiểm tra và sửa đổi mã khi nó đang chạy.

Tổng quan về API phản chiếu PHP

Hãy chuyển sang API phản chiếu. Nếu bạn đã kiểm tra tài liệu PHP trước đó (lại là liên kết này), bạn có thể nhận thấy rằng nó rất lớn. Có hơn chục lớp và một số lớp có hàng tá phương thức

Nó không thực tế (hoặc thậm chí không hữu ích đối với chúng tôi) để xem qua tất cả chúng. Thay vào đó, những gì chúng tôi sẽ làm là xem xét API phản chiếu từ cấp độ cao. Và, từ đó, chúng tôi sẽ xem xét các lớp phản chiếu mà bạn có nhiều khả năng sử dụng nhất

Các lớp phản ánh được cấu trúc như thế nào?

Mặc dù có rất nhiều lớp phản chiếu, nhưng cách chúng liên quan đến nhau khá dễ hiểu. Đó là bởi vì, nói chung, mọi cấu trúc PHP đều có một lớp phản chiếu tương ứng. Chúng ta có nghĩa là gì vậy?

Chà, giả sử bạn có một lớp học mà bạn muốn kiểm tra. Lớp phản ánh mà bạn sử dụng để làm điều đó là lớp

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
0. (Tên lớp khá rõ ràng. ) Nhưng nếu bạn có một đối tượng mà bạn muốn kiểm tra, bạn sẽ sử dụng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 để thay thế. (Chắc hẳn bạn đang có ý tưởng. )

$classReflection = new ReflectionClass('SomeClass');

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

Trên đây là cách bạn tạo phản chiếu của lớp

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2 và phản chiếu của đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Điều đáng chú ý là, trong khi chúng ta sử dụng hai lớp khác nhau để tạo phản xạ, thì cả hai phản xạ đều gần như giống hệt nhau. Trên thực tế, lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 mở rộng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
0

Trong thực tế, không có lý do gì để sử dụng một lớp phản chiếu hơn lớp kia. Bạn chỉ nên sử dụng thông tin phù hợp với thông tin bạn có vào thời điểm đó. Nếu bạn chỉ có tên lớp, hãy sử dụng lớp

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
0. Nếu bạn có một đối tượng, hãy sử dụng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 để thay thế

Hãy quay lại với các đối tượng phản chiếu của chúng ta. Khi chúng tôi đã khởi tạo một trong số chúng, chúng tôi có thể sử dụng các phương thức lớp của nó để kiểm tra lớp

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Điều này cho phép chúng tôi nhận được câu trả lời cho các câu hỏi cụ thể như

  • Là lớp một giao diện? . )
  • Tên của lớp học là gì? . )
    • Lớp này có hằng số, phương thức hoặc thuộc tính này không?

Đi sâu hơn vào những suy tư

Nhưng bạn có thể tìm hiểu sâu hơn nữa và tìm nạp một hằng số, phương thức hoặc thuộc tính cụ thể từ một lớp. Hoặc bạn có thể lấy tất cả. Hãy xem xét một ví dụ nhỏ về điều này trong thực tế

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');

Bây giờ, câu hỏi với ví dụ này là chúng ta đã lưu trữ gì trong biến

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9? . Sự phản ánh này cũng không phải là một trường hợp của
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
0. Đó là một thể hiện của lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);
2

Điều này đưa chúng ta đến một thực tế quan trọng về việc kiểm tra mã bằng phản xạ. Đó là, với các lớp phản xạ, bạn thường chỉ xử lý các lớp phản xạ khác. Nó hơi giống như đi xuống một cái hang thỏ

Điều đó nói rằng, đó cũng là một cách hữu ích để xem cấu trúc của các lớp phản chiếu này. Hãy tưởng tượng rằng bạn tạo một hình ảnh phản chiếu bằng cách sử dụng

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
0 hoặc
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1. Những gì bạn sẽ nhận được là một thể hiện của lớp đó

  • Hằng số của nó là thể hiện của lớp
    $object = new SomeClass();
    $objectReflection = new ReflectionObject($object);
    
    $somePropertyReflection = $objectReflection->getProperty('someProperty');
    
    $somePropertyValue = $somePropertyReflection->getValue($object);
    5
  • Phương thức của nó là các thể hiện của lớp
    $object = new SomeClass();
    $objectReflection = new ReflectionObject($object);
    
    $somePropertyReflection = $objectReflection->getProperty('someProperty');
    
    $somePropertyValue = $somePropertyReflection->getValue($object);
    6
  • Thuộc tính của nó là thể hiện của lớp
    $object = new SomeClass();
    $objectReflection = new ReflectionObject($object);
    
    $somePropertyReflection = $objectReflection->getProperty('someProperty');
    
    $somePropertyValue = $somePropertyReflection->getValue($object);
    2

Lấy thông tin từ phản xạ

Giả sử bạn đã đi sâu vào đối tượng phản chiếu mà bạn cần. Làm thế nào để bạn có được thông tin cụ thể ra khỏi nó?

Chà, trước tiên, bạn phải nghĩ xem bạn muốn lấy thông tin gì. Trong trường hợp này, chúng tôi muốn lấy giá trị thuộc tính của một đối tượng. Và sau đó bạn phải tự hỏi đâu là phản ánh cụ thể nhất sẽ chứa thông tin này

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);

Đoạn mã trên được xây dựng dựa trên ví dụ trước đây của chúng tôi. Chúng tôi đã khởi tạo một đối tượng

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Sau đó, chúng tôi đã tạo một phản chiếu của nó bằng cách sử dụng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1

Tiếp theo, chúng tôi muốn truy cập thuộc tính

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9 từ đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2 của chúng tôi. Chúng tôi làm điều đó bằng cách lấy hình ảnh phản chiếu của nó từ đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 của chúng tôi. Chúng tôi làm điều đó bằng cách sử dụng phương thức
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);
0 trả về một đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);
2

Chúng tôi cũng đã lưu trữ đối tượng

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);
2 đó trong biến
$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);
6. Sau đó, chúng ta có thể sử dụng nó để lấy giá trị được lưu trữ trong thuộc tính
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9. Chúng tôi làm điều đó bằng cách sử dụng phương pháp
$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);
8. Sau đó, chúng tôi đã lưu trữ giá trị đó trong biến
$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);
9

Phản xạ không bao giờ là phản xạ của một đối tượng cụ thể

Bây giờ, bạn cũng có thể nhận thấy điều kỳ lạ về cuộc gọi của chúng tôi đến phương thức

$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);
8. Đó là chúng tôi đã thông qua nó
class User
{
    /**
     * The user ID.
     *
     * @var int
     */
    private $id;

    /**
     * The user's login.
     *
     * @var string
     */
    private $login;

    /**
     * The user's password.
     *
     * @var string
     */
    private $password;

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $password;
    }
}
1 của chúng tôi như một đối số. Tại sao chúng tôi làm điều đó?

Đúng là chúng ta đã khởi tạo đối tượng

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 bằng đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Nhưng thực tế là chúng tôi đã làm điều đó không quan trọng. Đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 của chúng tôi không chứa bất kỳ thông tin nào về đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2 của chúng tôi

Đây là một trong những phần khó hiểu hơn khi sử dụng phản xạ. Xem xét cách chúng tôi khởi tạo nó, bạn sẽ nghĩ rằng đối tượng

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 của chúng tôi sẽ thông minh hơn. Rằng nó chứa thông tin về đối tượng mà chúng tôi phản ánh

Nhưng đó không phải là trường hợp. Đó là bởi vì, khi bạn tạo một đối tượng

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1, bạn không tạo ra một hình ảnh phản chiếu của đối tượng đó. Thay vào đó, điều đang xảy ra là lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 tạo ra sự phản chiếu của lớp đối tượng mà bạn đã cung cấp cho nó. (Đó cũng là lý do tại sao lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 mở rộng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
0. )

Vì vậy, nếu chúng ta quay lại ví dụ của mình, thì

class User
{
    // ...

    /**
     * Set the ID of a user.
     *
     * @param int $id
     */
    public function setId($id)
    {
        if (!empty($this->id)) {
            return;
        }

        $this->id = $id;
    }
}
3 không phải là sự phản ánh của
class User
{
    /**
     * The user ID.
     *
     * @var int
     */
    private $id;

    /**
     * The user's login.
     *
     * @var string
     */
    private $login;

    /**
     * The user's password.
     *
     * @var string
     */
    private $password;

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $password;
    }
}
1. Đó là sự phản ánh của lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Lúc đầu, nó không trực quan, nhưng cuối cùng bạn sẽ hiểu rõ về nó

Điều tương tự cũng xảy ra với tất cả các loại phản xạ khác.

Điều gì sẽ xảy ra sau đó khi chúng ta gọi phương thức

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);
0 của đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1? . Bạn đang nhận được sự phản ánh của một thuộc tính của một lớp

Điều này có nghĩa là, trong ví dụ của chúng ta,

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9 không phải là phản ánh của thuộc tính
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9 của
class User
{
    /**
     * The user ID.
     *
     * @var int
     */
    private $id;

    /**
     * The user's login.
     *
     * @var string
     */
    private $login;

    /**
     * The user's password.
     *
     * @var string
     */
    private $password;

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $password;
    }
}
1. Nó phản ánh thuộc tính
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9 của lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Và đó là lý do tại sao chúng ta phải chuyển
class User
{
    /**
     * The user ID.
     *
     * @var int
     */
    private $id;

    /**
     * The user's login.
     *
     * @var string
     */
    private $login;

    /**
     * The user's password.
     *
     * @var string
     */
    private $password;

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $password;
    }
}
1 cho phương thức
$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);
8

Một lần nữa, điều này không trực quan lắm khi bạn bắt đầu sử dụng phản xạ. Điều đó nói rằng, có những lợi ích cho những thứ làm việc theo cách họ làm. Ví dụ, điều đó có nghĩa là chúng ta không cần tạo nhiều phản chiếu của thuộc tính

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9. Nếu chúng ta phải kiểm tra hai đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2, chúng ta có thể làm điều này thay thế

$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);

Trong ví dụ trên, chúng tôi đã quản lý để trích xuất hai giá trị

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9 bằng cách sử dụng cùng một đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);
2. Đầu tiên, chúng tôi bắt đầu bằng cách tạo một phản ánh của lớp
class UserRepository
{
    /**
     * The user's login.
     *
     * @var mysqli
     */
    private $mysql;

    // ...

    public function persist(User $user) 
    {
        $result = $this->mysql->query('INSERT INTO ...');

        if (!$result) {
            throw new \Exception($this->mysql->error);
        }

        $userReflection = new ReflectionObject($user);
        $idPropertyReflection = $userReflection->getProperty('id');

        $idPropertyReflection->setAccessible(true);
        $idPropertyReflection->setValue($user, $this->mysql->insert_id);
        $idPropertyReflection->setAccessible(false);

        return $user;
    }
}
9. Chúng tôi đã tạo ra nó bằng cách sử dụng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 và truyền nó vào lớp
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
1. (Chúng ta cũng có thể sử dụng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
2. )

Sử dụng

class User
{
    // ...

    /**
     * Set the ID of a user.
     *
     * @param int $id
     */
    public function setId($id)
    {
        if (!empty($this->id)) {
            return;
        }

        $this->id = $id;
    }
}
3 của chúng tôi, chúng tôi nhận được phản ánh của thuộc tính
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9. Sau đó, chúng tôi sử dụng nó để trích xuất giá trị của thuộc tính
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9 từ cả hai đối tượng của chúng tôi. Sau đó, chúng tôi lưu trữ các giá trị đó trong các biến
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
6 và
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
7

Phản ánh trong thực tế

Mặc dù chúng tôi chưa thấy mọi thứ mà sự phản xạ có thể làm, nhưng đó là một điểm khởi đầu tốt. Những gì chúng ta sẽ làm tiếp theo là xem xét cách sử dụng phản xạ trong ngữ cảnh thực tế hơn. Điều này sẽ cho phép chúng ta xem xét các khía cạnh khác của suy tư mà chúng ta chưa đề cập đến cho đến nay

Một lớp học để phản ánh

Nhưng trước tiên, chúng ta cần một lớp mà chúng ta có thể phản ánh. Chúng ta không cần phải làm cho lớp này quá phức tạp. Nó chỉ cần các phương thức và thuộc tính không công khai. (Bạn không cần phản ánh để kiểm tra các phương thức hoặc thuộc tính công khai. )

class User
{
    /**
     * The user ID.
     *
     * @var int
     */
    private $id;

    /**
     * The user's login.
     *
     * @var string
     */
    private $login;

    /**
     * The user's password.
     *
     * @var string
     */
    private $password;

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $password;
    }
}

Vì vậy, trên đây là một lớp nhỏ có tên là

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 mà chúng ta sẽ sử dụng cho các ví dụ thực tế hơn. Nó có ba thuộc tính riêng bên trong.
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9,
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
0 và
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1. Hiện tại, nó không có bất kỳ phương thức nào khác ngoài hàm tạo

Bản thân hàm tạo có hai tham số.

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
0 và
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1. Đó là hai trong số ba thuộc tính bên trong mà lớp
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 của chúng ta có. Tất cả những gì hàm tạo thực hiện là gán các đối số
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
0 và
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1 được truyền cho nó cho các biến nội bộ
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
0 và
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1

Bây giờ, bạn có thể thắc mắc tại sao chúng tôi không đặt

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9 làm tham số cho hàm tạo của chúng tôi. Đó là bởi vì bạn không phải lúc nào cũng có hoặc cần
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9 của người dùng khi bạn đang tạo một đối tượng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8. Ví dụ: một người dùng mới có thể chưa được gán ID ngay lập tức

Gán một giá trị cho một thuộc tính riêng tư hoặc được bảo vệ

Nhưng điều gì sẽ xảy ra nếu bạn muốn gán giá trị cho

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9 của người dùng? . Nhưng điều này có nghĩa là bất kỳ ai cũng có thể đặt ID mới cho người dùng bất kỳ lúc nào

Đây không phải là một giải pháp lý tưởng vì ID của người dùng sẽ không thay đổi nếu có. Điều đó nói rằng, đây cũng có thể là một phần logic của phương thức setter. Nếu người dùng đã có ID, đừng gán cho họ một ID mới như thế này

class User
{
    // ...

    /**
     * Set the ID of a user.
     *
     * @param int $id
     */
    public function setId($id)
    {
        if (!empty($this->id)) {
            return;
        }

        $this->id = $id;
    }
}

Sử dụng một sự phản ánh thay vì một phương pháp

Tuy nhiên, ngay cả khi phương thức

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);
3 ngăn ai đó ghi đè lên thuộc tính
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9, điều đó không có nghĩa là phương thức đó nên tồn tại. Thay vì tạo phương thức
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);
3, bạn có thể sử dụng phản xạ để thêm
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9 vào đối tượng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 bất cứ khi nào bạn cần. Hãy xem làm thế nào chúng ta có thể làm điều đó

class UserRepository
{
    /**
     * The user's login.
     *
     * @var mysqli
     */
    private $mysql;

    // ...

    public function persist(User $user) 
    {
        $result = $this->mysql->query('INSERT INTO ...');

        if (!$result) {
            throw new \Exception($this->mysql->error);
        }

        $userReflection = new ReflectionObject($user);
        $idPropertyReflection = $userReflection->getProperty('id');

        $idPropertyReflection->setAccessible(true);
        $idPropertyReflection->setValue($user, $this->mysql->insert_id);
        $idPropertyReflection->setAccessible(false);

        return $user;
    }
}

Ở trên chúng ta có một phần của lớp

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);
8. Nếu bạn chưa quen với khái niệm kho lưu trữ, thì đó là lớp hoạt động như một tập hợp các đối tượng. Nếu bạn cần một lớp kiên trì, nó cũng có thể xử lý các đối tượng kiên trì bên trong cơ sở dữ liệu. (Nếu đó là những gì bạn sử dụng để kiên trì. )

Đây là những gì phương pháp

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);
9 làm. Nó lấy một đối tượng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 làm đối số và duy trì nó trong cơ sở dữ liệu MySQL. Chỉ khi chúng tôi đã duy trì đối tượng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 của mình, chúng tôi mới gán cho nó một
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9

Vì vậy, thay vì sử dụng phương pháp

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);
3 để gán cho
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9, chúng tôi đang sử dụng phản xạ. Nhưng trước tiên, chúng ta cần lưu đối tượng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 bên trong cơ sở dữ liệu. Để làm điều đó, lớp
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);
8 của chúng tôi sử dụng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
07. Đây là một lớp PHP được sử dụng để thể hiện kết nối với cơ sở dữ liệu MySQL

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);
8 của chúng ta đã có một đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
07 được khởi tạo được lưu trữ trong thuộc tính
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
10. Vì vậy, chúng tôi có thể cho rằng kết nối của chúng tôi với cơ sở dữ liệu MySQL đã hoạt động. Tất cả những gì chúng ta phải làm sau đó là tạo một truy vấn để chèn người dùng mới vào cơ sở dữ liệu

Chúng tôi làm điều đó bằng cách sử dụng phương thức

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
11 để chạy truy vấn
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
12. Chúng tôi không hiển thị truy vấn vì nó không liên quan ở đây. Điều đó nói rằng, đừng bao giờ quên vệ sinh đầu vào cơ sở dữ liệu của bạn nếu bạn chạy các truy vấn như thế này

Chúng tôi lưu trữ kết quả của truy vấn trong biến

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
13. Sau đó, chúng tôi kiểm tra xem đó có phải là
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
14. Nếu đúng như vậy, chúng tôi sẽ đưa ra một ngoại lệ với thông báo lỗi được lưu trữ trong thuộc tính
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
15 của đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
07

Khi chúng tôi đã thông qua điều khoản bảo vệ này, chúng tôi có thể bắt đầu sử dụng phản xạ của mình. Đầu tiên, chúng ta tạo một phản chiếu của đối tượng

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 bằng cách sử dụng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1. Sau đó, chúng tôi tạo phản ánh của thuộc tính
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9 bằng cách sử dụng phương pháp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);
0 của phản ánh
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 của chúng tôi

Thay đổi khả năng truy cập của một thuộc tính

Bạn không nên cảm thấy điều này quá mới mẻ vì đó là những gì chúng ta đã thấy trước đó về việc đi sâu vào những suy tư. Có gì mới là nửa cuối của phần này. Đó là nơi chúng ta thay đổi giá trị của một biến nội bộ của một đối tượng

Theo mặc định, phản ánh không ghi đè lên phạm vi của một biến. Điều này có nghĩa là, trong khi chúng tôi phản ánh tài sản

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9, chúng tôi không thể làm gì nhiều với nó. Nó vẫn là tài sản của
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
23

Để thay đổi điều đó, chúng ta cần sử dụng phương thức

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
24. Điều này thay đổi phạm vi của thuộc tính thành
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
25. Khi chúng tôi đã hoàn thành việc đó, đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$somePropertyReflection = $objectReflection->getProperty('someProperty');

$somePropertyValue = $somePropertyReflection->getValue($object);
2 sẽ cho phép chúng tôi sửa đổi giá trị của thuộc tính
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9

Tại thời điểm đó, tất cả những gì chúng ta phải làm là gọi phương thức

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
28. Chúng tôi chuyển đối tượng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 của chúng tôi và ID của người dùng mà chúng tôi đã chèn vào cơ sở dữ liệu. Đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
07 luôn lưu trữ ID đó trong thuộc tính
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
31

Khi chúng tôi đã đặt giá trị của thuộc tính

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9, chúng tôi cần hoàn nguyên thay đổi khả năng truy cập mà chúng tôi đã thực hiện lúc đầu. Mặt khác, thuộc tính
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
9 sẽ vẫn có thể truy cập được chừng nào đối tượng còn tồn tại. (Và chúng tôi không muốn điều đó. ) Đó là lý do tại sao chúng ta gọi phương thức
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
24 một lần nữa sau khi gọi phương thức
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
28

Gọi một phương pháp riêng tư hoặc được bảo vệ

Chúng tôi cũng có thể làm những gì chúng tôi vừa làm cho các thuộc tính riêng tư hoặc được bảo vệ bằng các phương thức đối tượng. Chúng tôi có thể sử dụng một phương pháp riêng tư hoặc được bảo vệ và đặt nó ở chế độ công khai để chúng tôi có thể sử dụng nó. Đây cũng là một cái gì đó có thể hữu ích trong một số tình huống nhất định

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}

Trên đây là phiên bản cập nhật của lớp

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 của chúng tôi. Chúng tôi đã thêm một phương thức riêng tư mới có tên là
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
37. Mục đích của phương pháp này là mã hóa mật khẩu của chúng tôi nếu nó chưa được mã hóa. Chúng tôi làm điều đó bằng cách sử dụng hai hàm PHP tích hợp.
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
38 và
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
39

Phương thức

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
37 bắt đầu bằng mệnh đề bảo vệ. Chúng tôi sử dụng hàm
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
38 để kiểm tra xem chúng tôi có cần mã hóa
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1 đã cho hay không. Nếu chúng tôi không cần, chúng tôi trả lại. Mặt khác, chúng tôi hàm
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
39 để mã hóa
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1 đã cho

Cũng cần lưu ý rằng cả hai hàm đều có đối số thứ hai nơi chúng ta truyền hằng số

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
45. Đây là hằng số thuật toán mật khẩu mà chúng tôi sẽ sử dụng để mã hóa
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1 đã cho. Bạn cũng có thể sử dụng hằng số
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
47 nếu không muốn chỉ định thuật toán. Điều đó nói rằng,
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
45 là giá trị
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
47 hiện tại

Sử dụng một phương pháp phản ánh

Bây giờ chúng ta có một phương thức private trong lớp

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 của mình, chúng ta có thể xem cách tạo phản chiếu cho nó. Điều này khá đơn giản và tuân theo mô hình tương tự mà chúng ta đã thấy cho đến nay. Bạn có thể xem mã dưới đây

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);

Không giống như ví dụ trước của chúng ta với lớp

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);
8, đây chỉ là một mẫu mã. Điều đó nói rằng, bạn sẽ nhận thấy rằng một lần nữa chúng ta bắt đầu bằng cách phản ánh đối tượng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 của chúng ta bằng cách sử dụng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1. Thay vào đó, bạn có thể đã sử dụng lớp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
0 nếu bạn muốn

Sau đó là nơi mọi thứ chuyển hướng một chút. Đầu tiên, chúng ta gọi phương thức

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
55. Chúng tôi sử dụng nó để yêu cầu phản ánh phương pháp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
37

Tiếp theo, chúng tôi muốn làm cho phương thức có thể truy cập được. Chúng tôi sử dụng phương pháp

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
24 giống như chúng tôi đã làm với tài sản riêng của mình. Điều này sẽ cho phép chúng tôi sử dụng phương pháp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
37 của chúng tôi

Để gọi một phương thức phản ánh, bạn phải sử dụng phương thức

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
59.
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
59 hoạt động giống như các phương pháp phản ánh khác mà chúng tôi đã thấy cho đến nay. Trước tiên, bạn phải chuyển đối tượng mà bạn muốn phản chiếu tương tác với nó

Tạo đóng cửa

Ngoài ra còn có một cách khác để truy cập một phương thức riêng tư bằng phản xạ. Đó là bằng cách tạo một bao đóng cho phương thức mà chúng ta muốn phản ánh. Đây là một ví dụ để cho bạn thấy làm thế nào để làm điều đó

$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeClosure = $maybeEncodeReflection->getClosure($user);

$maybeEncodeClosure($password);

Như bạn có thể nhận thấy, đây là phiên bản sửa đổi của ví dụ trước của chúng tôi. Phần đầu tiên của ví dụ là như nhau. Chúng tôi đã tạo một hình ảnh phản chiếu của đối tượng

class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 của chúng tôi. Sau đó, chúng tôi đã sử dụng sự phản chiếu đó để tạo ra sự phản chiếu của phương thức
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
37

Phần cuối cùng của ví dụ là nơi mọi thứ thay đổi. Đầu tiên, chúng tôi không sử dụng phương pháp

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
24. Chúng ta không cần thay đổi khả năng truy cập của phương pháp
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
37 để sử dụng nó trong trường hợp này

Thay vào đó, chúng ta chỉ cần gọi phương thức

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
65. Điều này tạo ra một đối tượng
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
66. Đối tượng này gọi phương thức
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
37 trong đối tượng
class User
{
    // ...

    /**
     * Constructor.
     *
     * @param string $login
     * @param string $password
     */
    public function __construct($login, $password)
    {
        $this->login = $login;
        $this->password = $this->maybeEncode($password);
    }

    /**
     * Encodes the password using the BCRYPT algorithm if it's not already
     * encoded.
     *
     * @param string $password
     *
     * @return string
     */
    private function maybeEncode($password)
    {
        if (!password_needs_rehash($password, PASSWORD_BCRYPT)) {
            return $password;
        }

        return password_hash($password, PASSWORD_BCRYPT);
    }
}
8 mà chúng ta đã truyền vào nó

Chúng tôi làm điều đó trên dòng cuối cùng. Chúng tôi sử dụng biến

$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
69 làm hàm. Chúng tôi vượt qua nó
$userReflection = new ReflectionObject($user);

$maybeEncodeReflection = $userReflection->getMethod('maybeEncode');

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1 của chúng tôi như một đối số

Một nền tảng tốt

Đây chỉ là một phần của tất cả những gì bạn có thể làm bằng phản xạ. Như chúng tôi đã nói lúc đầu, điều này bao gồm các cách sử dụng phản xạ phổ biến nhất. Có rất nhiều lớp và phương thức, nhưng việc sử dụng chúng mang tính tình huống hơn rất nhiều

Với những gì bạn đã thấy ở đây, bạn đang ở trạng thái tốt để sử dụng phản xạ để giải các bài toán thú vị. Điều đó nói rằng, hầu hết việc sử dụng nó sẽ xoay quanh thử nghiệm. Phản ánh và thử nghiệm thường đi đôi với nhau

Vì vậy, nếu bạn quan tâm đến việc thử nghiệm, thì đây là kiến ​​thức tốt cần có. Nhưng bất kể bạn có thử nghiệm hay không (mặc dù bạn nên. ), phản xạ là khái niệm khoa học máy tính quan trọng. Bạn có thể gặp chúng trong một ngôn ngữ lập trình khác sau này trong sự nghiệp của bạn

Lớp phản chiếu trong PHP là gì?

Thuật ngữ “phản ánh” trong phát triển phần mềm có nghĩa là một chương trình biết cấu trúc của chính nó trong thời gian chạy và cũng có thể sửa đổi cấu trúc đó. Khả năng này còn được gọi là “hướng nội”. Trong khu vực PHP, sự phản chiếu được dùng để đảm bảo an toàn kiểu trong mã chương trình .

Khi nào sử dụng lớp phản chiếu PHP?

Lớp phản chiếu được sử dụng để lấy thông tin về trạng thái hiện tại của ứng dụng . Nó được gọi là sự phản chiếu, bởi vì nó nhìn vào chính nó, và có thể cho bạn biết thông tin về chương trình bạn đang chạy, trong thời gian chạy.

Việc sử dụng ReflectionClass là gì?

Lớp ReflectionClass trong PHP là một cách để kiểm tra một lớp và lấy tất cả thông tin của lớp như tên của nó là gì, thuộc tính của nó là gì, phương thức, thuộc tính, hằng số, thậm chí cả nhận xét tài liệu, giao diện, công cụ sửa đổi, không gian tên, lớp cha là gì

ReflectionClass trong laravel là gì?

Lớp phản chiếu. báo cáo thông tin về một lớp học . Phản ánhChức năng. báo cáo thông tin về một chức năng. Thông số phản ánh. lấy thông tin về các tham số của hàm hoặc phương thức.