Php refleksi membuat metode publik

Apakah Anda pernah meluangkan waktu untuk membaca kode framework atau library PHP favorit Anda? . Dan, jika Anda tidak membaca kode orang lain, Anda harus mulai melakukannya. (Ini adalah alat pembelajaran yang hebat. )

Sekarang, mari kembali ke API refleksi. Ini adalah API yang cukup banyak digunakan oleh pengembang framework dan library. Tapi lucunya hal itu hampir tidak pernah dibicarakan saat Anda melihat sumber daya untuk mempelajari PHP. (Atau bahkan sumber daya PHP tingkat lanjut dalam hal ini. )

Ini sangat disayangkan. Itu karena API refleksi PHP melayani tujuan yang unik dan penting. Itu sebabnya pengembang yang membangun kerangka kerja dan pustaka kami sangat sering menggunakannya

Apa itu refleksi?

Pada titik ini, ada kemungkinan besar Anda mengatakan pada diri sendiri, “Yah, tentu saja, saya tidak tahu API refleksi PHP. Saya bahkan tidak tahu apa yang Anda maksud dengan refleksi. Itu reaksi yang masuk akal. (Salahku. ) Itu yang saya miliki pertama kali saya menemukan kode yang menggunakan refleksi

Mari kita mulai dengan melihat konsep refleksi. Hal pertama yang harus Anda ketahui adalah bahwa konsep refleksi tidak spesifik untuk PHP. Ini adalah konsep yang berasal dari ilmu komputer

Baiklah tidak apa apa. Tapi apakah konsep refleksi yang misterius ini?

Jika kedengarannya trippy, itu karena memang begitu. Kami sering menganggap kode kami sebagai sesuatu yang statis. Setelah Anda menyimpan dan menjalankannya, tidak ada cara untuk mengubahnya. Tapi itu tidak benar. Dan refleksi adalah mekanisme yang Anda gunakan untuk membuat perubahan pada kode Anda saat sedang berjalan

Meskipun mungkin terdengar gila hari ini bahwa Anda ingin mengedit kode Anda saat sedang berjalan, itu tidak selalu terjadi. Kembali ketika pemrogram biasa memprogram menggunakan bahasa rakitan, ini cukup umum. Faktanya, memeriksa kode Anda dan memodifikasinya saat dijalankan adalah properti yang melekat pada bahasa rakitan

Properti bahasa rakitan ini tidak terbawa ketika bahasa kompilasi awal muncul. Tapi itu akhirnya muncul kembali melalui konsep refleksi. Dan sekarang sudah banyak bahasa pemrograman yang mendukungnya

Untuk apa Anda menggunakannya?

Nah itulah beberapa sejarah dibalik konsep refleksi. Tetapi ini tidak benar-benar membantu Anda memahami untuk apa Anda akan menggunakannya. Atau bahkan mengapa itu berguna. Lagi pula, Anda telah lolos dengan tidak menggunakannya untuk sementara waktu sekarang

Penggunaan yang paling umum untuk refleksi adalah untuk pengujian. Saat Anda menguji kode Anda, Anda sering perlu memeriksa dan memodifikasinya saat sedang berjalan. Ini juga bagaimana kerangka pengujian unit cenderung membuat tiruan dari kelas dan fungsi Anda

Ini juga bagus untuk situasi di mana Anda ingin menganalisis kode dan mengotomatiskan beberapa tugas di sekitarnya. Misalnya, pustaka pembuatan dokumentasi dapat menggunakan refleksi untuk membuat dokumentasi untuk kode Anda. Itu juga berapa banyak wadah injeksi ketergantungan menyuntikkan ketergantungan ke objek yang mereka buat

Yang mengatakan, seperti yang akan kita lihat di seluruh artikel, ada banyak kegunaan unik untuk refleksi. Mereka tidak selalu masuk ke dalam kategori rapi seperti yang baru saja kami sebutkan. Tapi kesamaan mereka semua adalah bahwa mereka menggunakan refleksi untuk memeriksa dan memodifikasi kode saat sedang berjalan

Gambaran umum API refleksi PHP

Mari beralih ke API refleksi. Jika Anda memeriksa dokumentasi PHP sebelumnya (ini tautannya lagi), Anda mungkin telah memperhatikan bahwa itu sangat besar. Ada lebih dari selusin kelas, dan beberapa di antaranya memiliki lusinan metode

Tidak realistis (atau bahkan berguna bagi kita) untuk membahas semuanya. Yang akan kami lakukan adalah melihat API refleksi dari level tinggi. Dan, dari sana, kita akan melihat kelas refleksi yang kemungkinan besar akan Anda gunakan

Bagaimana kelas refleksi disusun?

Meskipun ada banyak kelas refleksi, keterkaitannya satu sama lain cukup mudah dipahami. Itu karena, secara umum, setiap konstruk PHP memiliki kelas refleksi yang sesuai. Apa yang kita maksud dengan itu?

Nah, katakanlah Anda memiliki kelas yang ingin Anda periksa. Kelas refleksi yang akan Anda gunakan untuk melakukan itu adalah kelas

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

$someProperty = $objectReflection->getProperty('someProperty');
0. (Nama kelas yang cukup jelas. ) Tetapi jika Anda memiliki objek yang ingin Anda periksa, Anda akan menggunakan kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 sebagai gantinya. (Anda pasti mendapatkan idenya. )

$classReflection = new ReflectionClass('SomeClass');

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

Di atas adalah bagaimana Anda membuat refleksi dari kelas

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

$someProperty = $objectReflection->getProperty('someProperty');
2 dan refleksi dari objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Perlu dicatat bahwa, meskipun kami menggunakan dua kelas berbeda untuk menghasilkan refleksi kami, kedua refleksi tersebut hampir identik. Faktanya, kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_1 memperluas kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Dalam praktiknya, tidak ada alasan untuk menggunakan satu kelas refleksi di atas yang lain. Anda sebaiknya menggunakan yang sesuai dengan informasi yang Anda miliki saat itu. Jika Anda hanya memiliki nama kelas, gunakan kelas

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

$someProperty = $objectReflection->getProperty('someProperty');
0. Jika Anda memiliki objek, gunakan kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Mari kembali ke objek refleksi kita. Setelah kita membuat instance salah satunya, kita kemudian dapat menggunakan metode kelasnya untuk memeriksa kelas

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

$someProperty = $objectReflection->getProperty('someProperty');
2. Hal ini memungkinkan kita untuk mendapatkan jawaban atas pertanyaan spesifik seperti

  • Apakah kelas antarmuka? . )
  • Apa nama kelasnya? . )
    • Apakah kelas ini memiliki konstanta, metode, atau properti ini?

Menyelam lebih jauh ke dalam refleksi

Tapi Anda bisa menggali lebih dalam dan mengambil konstanta, metode, atau properti tertentu dari kelas. Atau Anda bisa mendapatkan semuanya. Mari kita lihat contoh kecil dari tindakan ini

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

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

Sekarang, pertanyaan dengan contoh ini adalah apa yang kita simpan di variabel

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

$someProperty = $objectReflection->getProperty('someProperty');
9? . Refleksi ini juga bukan turunan dari
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
0. Ini adalah turunan dari kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

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

Ini membawa kita pada fakta penting tentang memeriksa kode dengan refleksi. Itu karena, dengan refleksi, Anda sering kali hanya berurusan dengan kelas refleksi lainnya. Ini seperti turun ke lubang kelinci

Yang mengatakan, itu juga merupakan cara yang berguna untuk melihat struktur kelas refleksi ini. Bayangkan Anda membuat refleksi menggunakan

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

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

$someProperty = $objectReflection->getProperty('someProperty');
1. Apa yang akan Anda dapatkan adalah instance dari kelas itu di mana

  • Konstantanya adalah turunan dari kelas
    $object = new SomeClass();
    $objectReflection = new ReflectionObject($object);
    
    $somePropertyReflection = $objectReflection->getProperty('someProperty');
    
    $somePropertyValue = $somePropertyReflection->getValue($object);
    5
  • Metodenya adalah turunan dari kelas
    $object = new SomeClass();
    $objectReflection = new ReflectionObject($object);
    
    $somePropertyReflection = $objectReflection->getProperty('someProperty');
    
    $somePropertyValue = $somePropertyReflection->getValue($object);
    6
  • Propertinya adalah turunan dari kelas
    $object = new SomeClass();
    $objectReflection = new ReflectionObject($object);
    
    $somePropertyReflection = $objectReflection->getProperty('someProperty');
    
    $somePropertyValue = $somePropertyReflection->getValue($object);
    2

Mendapatkan informasi dari refleksi

Katakanlah Anda telah menelusuri objek refleksi yang Anda butuhkan. Bagaimana Anda mendapatkan informasi konkret darinya?

Nah, pertama-tama, Anda harus memikirkan informasi apa yang ingin Anda dapatkan. Dalam hal ini, kami ingin mendapatkan nilai properti dari suatu objek. Dan kemudian Anda harus bertanya pada diri sendiri refleksi apa yang paling spesifik yang berisi informasi ini

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

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

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

Kode di atas dibuat berdasarkan contoh kita sebelumnya. Kami menginisialisasi objek

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

$someProperty = $objectReflection->getProperty('someProperty');
_2. Kami kemudian membuat refleksinya menggunakan kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Selanjutnya, kami ingin mengakses properti

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

$someProperty = $objectReflection->getProperty('someProperty');
_9 dari objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2 kami. Kami melakukannya dengan mengambil pantulannya dari objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 kami. Kami melakukannya dengan menggunakan metode
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

$somePropertyValue = $somePropertyReflection->getValue($object);
_0 yang mengembalikan objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

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

Kami juga menyimpan objek

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

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

$somePropertyValue = $somePropertyReflection->getValue($object);
_2 itu di variabel
$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

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

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);
6. Kami kemudian dapat menggunakannya untuk mendapatkan nilai yang disimpan di properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9. Kami melakukannya dengan menggunakan metode
$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

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

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);
_8. Kami kemudian menyimpan nilai itu dalam variabel ________29______9

Refleksi tidak pernah merupakan refleksi dari objek tertentu

Sekarang, Anda mungkin juga memperhatikan keanehan tentang panggilan kami ke metode

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

$objectReflection = new ReflectionObject($object1);

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

$somePropertyValue1 = $somePropertyReflection->getValue($object1);
$somePropertyValue2 = $somePropertyReflection->getValue($object2);
8. Itu karena kami memberikan
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 kami sebagai argumen. mengapa kita melakukan itu?

Memang benar bahwa kami membuat instance objek

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

$someProperty = $objectReflection->getProperty('someProperty');
1 kami menggunakan objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2 kami. Tetapi kenyataannya adalah tidak masalah bahwa kami melakukan itu. Objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 kami tidak berisi informasi apa pun tentang objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Ini adalah salah satu bagian yang lebih membingungkan dalam menggunakan refleksi. Mempertimbangkan bagaimana kami membuat instance, Anda akan berpikir bahwa objek

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

$someProperty = $objectReflection->getProperty('someProperty');
1 kami akan lebih pintar. Itu akan berisi informasi tentang objek yang kami refleksikan

Tapi bukan itu masalahnya. Itu karena, saat Anda membuat objek

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

$someProperty = $objectReflection->getProperty('someProperty');
1, Anda tidak membuat refleksi dari objek tersebut. Alih-alih, yang terjadi adalah kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 membuat refleksi dari kelas objek yang Anda berikan. (Itu juga mengapa kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_1 memperluas kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Jadi, jika kita kembali ke contoh kita,

class User
{
    // ...

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

        $this->id = $id;
    }
}
3 bukanlah cerminan dari
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. Ini adalah cerminan dari kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Ini tidak intuitif pada awalnya, tetapi pada akhirnya Anda akan menguasainya

Hal yang sama berlaku untuk semua jenis refleksi lainnya

Apa yang terjadi kemudian ketika kita melakukan panggilan ke metode

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

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

$somePropertyValue = $somePropertyReflection->getValue($object);
0 dari objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1 kita? . Anda mendapatkan refleksi dari properti kelas

Artinya, dalam contoh kita,

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

$someProperty = $objectReflection->getProperty('someProperty');
_9 bukanlah cerminan dari properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9 dari
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. Ini adalah refleksi dari properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_9 dari kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
2. Dan itulah mengapa kita harus meneruskan
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 ke metode
$object1 = new SomeClass();
$object2 = new SomeClass();

$objectReflection = new ReflectionObject($object1);

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

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

Sekali lagi, ini tidak terlalu intuitif saat Anda mulai menggunakan pantulan. Yang mengatakan, ada manfaat untuk hal-hal yang bekerja seperti yang mereka lakukan. Misalnya, ini berarti kita tidak perlu membuat banyak refleksi dari properti

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

$someProperty = $objectReflection->getProperty('someProperty');
9. Jika kita harus memeriksa dua objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_2, kita bisa melakukannya

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

$objectReflection = new ReflectionObject($object1);

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

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

Dalam contoh di atas, kami berhasil mengekstrak dua nilai

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

$someProperty = $objectReflection->getProperty('someProperty');
9 menggunakan objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

$somePropertyValue = $somePropertyReflection->getValue($object);
2 yang sama. Pertama, kita mulai dengan membuat refleksi dari kelas
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. Kami membuatnya dengan menggunakan kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_1 dan meneruskannya
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. (Kita juga bisa menggunakan
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. )

Menggunakan

class User
{
    // ...

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

        $this->id = $id;
    }
}
_3 kami, kami mendapatkan refleksi dari properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
9. Kami kemudian menggunakannya untuk mengekstrak nilai properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_9 dari kedua objek kami. Kami kemudian menyimpan nilai-nilai tersebut dalam variabel
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 dan
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

Refleksi dalam praktek

Meskipun kami belum melihat semua yang dapat dilakukan refleksi, ini adalah titik awal yang baik. Apa yang akan kita lakukan selanjutnya adalah melihat bagaimana menggunakan refleksi dalam konteks yang lebih praktis. Ini akan memungkinkan kita untuk membahas aspek refleksi lain yang belum kita bahas sejauh ini

Sebuah kelas untuk direfleksikan

Tapi pertama-tama, kita membutuhkan kelas yang bisa kita refleksikan. Kita tidak perlu membuat kelas ini terlalu rumit. Itu hanya membutuhkan metode dan properti yang tidak bersifat publik. (Anda tidak perlu refleksi untuk memeriksa metode atau properti publik. )

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;
    }
}

Jadi di atas adalah kelas kecil bernama

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 yang akan kita gunakan untuk contoh yang lebih praktis. Ini memiliki tiga properti pribadi internal.
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 dan
$userReflection = new ReflectionObject($user);

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

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1. Untuk saat ini, tidak ada metode lain selain konstruktor

Konstruktor itu sendiri memiliki dua parameter.

$userReflection = new ReflectionObject($user);

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

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

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

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1. Itu adalah dua dari tiga properti internal yang dimiliki kelas
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 kita. Semua yang konstruktor lakukan adalah memberikan
$userReflection = new ReflectionObject($user);

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

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

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

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1 argumen yang diteruskan ke
$userReflection = new ReflectionObject($user);

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

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

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

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

Sekarang, Anda mungkin bertanya-tanya mengapa kami tidak menempatkan

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 sebagai parameter konstruktor kami. Itu karena Anda tidak selalu memiliki atau membutuhkan
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 pengguna saat Anda membuat objek
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. Misalnya, pengguna baru mungkin tidak langsung menetapkan ID-nya

Menetapkan nilai ke properti pribadi atau dilindungi

Namun apa yang terjadi jika Anda ingin menetapkan nilai ke

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 pengguna? . Tapi ini berarti siapa pun dapat menetapkan ID baru untuk pengguna kapan saja

Ini bukan solusi yang ideal karena ID pengguna tidak boleh berubah jika ada. Yang mengatakan, ini juga bisa menjadi bagian dari logika metode setter. Jika pengguna sudah memiliki ID, jangan berikan yang baru seperti ini

class User
{
    // ...

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

        $this->id = $id;
    }
}

Menggunakan refleksi alih-alih metode

Namun, meskipun metode

$userReflection = new ReflectionObject($user);

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

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

$maybeEncodeClosure($password);
3 mencegah seseorang menimpa properti
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, itu tidak berarti bahwa metode tersebut harus ada. Alih-alih membuat metode
$userReflection = new ReflectionObject($user);

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

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

$maybeEncodeClosure($password);
_3, Anda bisa menggunakan refleksi untuk menambahkan
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 ke objek
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 kapan pun Anda membutuhkannya. Mari kita lihat bagaimana kita bisa melakukannya

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;
    }
}

Di atas kita memiliki bagian dari kelas ________89______8. Jika Anda tidak terbiasa dengan konsep repositori, kelaslah yang bertindak sebagai kumpulan objek. Jika Anda memerlukan lapisan kegigihan, lapisan ini juga dapat menangani objek yang bertahan di dalam database. (Jika itu yang Anda gunakan untuk kegigihan. )

Inilah yang dilakukan metode

$userReflection = new ReflectionObject($user);

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

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

$maybeEncodeClosure($password);
_9. Dibutuhkan objek
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 sebagai argumen dan menyimpannya di database MySQL. Hanya setelah kami mempertahankan objek
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 kami, kami menetapkannya sebagai
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

Jadi, alih-alih menggunakan metode

$userReflection = new ReflectionObject($user);

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

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

$maybeEncodeClosure($password);
_3 untuk menetapkan
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, kami menggunakan refleksi. Tapi pertama-tama, kita perlu menyimpan objek ________65______8 kita di dalam database. Untuk melakukan itu, kelas
$userReflection = new ReflectionObject($user);

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

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

$maybeEncodeClosure($password);
_8 kami menggunakan kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
07. Ini adalah kelas PHP yang digunakan untuk mewakili koneksi dengan database MySQL

$userReflection = new ReflectionObject($user);

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

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

$maybeEncodeClosure($password);
_8 kami sudah memiliki objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
07 yang dibuat dalam bentuk
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
10 yang disimpan di properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
10. Jadi kita dapat berasumsi bahwa koneksi kita ke database MySQL sudah berfungsi. Yang harus kita lakukan adalah membuat kueri untuk memasukkan pengguna baru kita ke dalam database

Kami melakukannya menggunakan metode

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

$someProperty = $objectReflection->getProperty('someProperty');
_11 untuk menjalankan kueri
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
12. Kami tidak menampilkan kueri karena tidak relevan di sini. Yang mengatakan, jangan pernah lupa untuk membersihkan input database Anda jika Anda menjalankan kueri seperti ini

Kami menyimpan hasil kueri dalam variabel

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

$someProperty = $objectReflection->getProperty('someProperty');
13. Kami kemudian memeriksa untuk melihat apakah itu
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
14. Jika ya, kami membuang pengecualian dengan pesan kesalahan yang disimpan di properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
15 dari objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Setelah kita melewati klausa penjaga ini, kita bisa mulai menggunakan refleksi kita. Pertama, kita membuat refleksi dari objek

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 menggunakan kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1. Kemudian kami membuat refleksi dari properti
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 menggunakan metode
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

$somePropertyValue = $somePropertyReflection->getValue($object);
0 dari refleksi
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 kami

Mengubah aksesibilitas properti

Ini seharusnya tidak terasa terlalu baru bagi Anda karena itulah yang kita lihat sebelumnya tentang menyelam ke dalam refleksi. Apa yang baru adalah paruh terakhir dari bagian ini. Di situlah kita mengubah nilai variabel internal suatu objek

Secara default, refleksi tidak mengesampingkan cakupan variabel. Artinya, meskipun kami memiliki refleksi dari properti

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, kami tidak dapat berbuat banyak dengannya. Itu masih properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Untuk mengubahnya, kita perlu menggunakan metode ________0______24. Ini mengubah cakupan properti menjadi

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

$someProperty = $objectReflection->getProperty('someProperty');
25. Setelah kami selesai melakukannya, objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

$somePropertyValue = $somePropertyReflection->getValue($object);
_2 akan memungkinkan kami mengubah nilai properti
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

Pada saat itu, yang harus kita lakukan hanyalah memanggil metode

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

$someProperty = $objectReflection->getProperty('someProperty');
28. Kami menyebarkan objek
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 kami dan ID pengguna yang kami masukkan ke dalam database. Objek
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
07 selalu menyimpan ID tersebut di properti
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Setelah kami menetapkan nilai properti

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, kami perlu mengembalikan perubahan aksesibilitas yang kami lakukan pada awalnya. Jika tidak, properti
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 akan tetap dapat diakses selama objek tersebut ada. (Dan kami tidak menginginkan itu. ) Itu sebabnya kami melakukan panggilan ke metode
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
24 sekali lagi setelah panggilan ke metode
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Memanggil metode pribadi atau dilindungi

Kita juga dapat melakukan apa yang baru saja kita lakukan untuk properti pribadi atau yang dilindungi dengan metode objek. Kita dapat menggunakan metode private atau protected dan membuatnya menjadi publik sehingga kita dapat menggunakannya. Ini juga sesuatu yang dapat berguna dalam skenario tertentu

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);
    }
}

Di atas adalah versi terbaru dari kelas ________65______8 kami. Kami menambahkan metode pribadi baru yang disebut

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

$someProperty = $objectReflection->getProperty('someProperty');
37. Tujuan dari metode ini adalah untuk menyandikan kata sandi kami jika belum dikodekan. Kami melakukannya dengan menggunakan dua fungsi PHP bawaan.
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

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

Metode

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

$someProperty = $objectReflection->getProperty('someProperty');
37 dimulai dengan klausa penjaga. Kami menggunakan fungsi
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_38 untuk memeriksa apakah kami perlu menyandikan
$userReflection = new ReflectionObject($user);

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

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1 yang diberikan. Kalau tidak perlu, kami kembalikan. Jika tidak, kami
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_39 berfungsi untuk menyandikan
$userReflection = new ReflectionObject($user);

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

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

Perlu juga dicatat bahwa kedua fungsi memiliki argumen kedua di mana kami meneruskan konstanta

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

$someProperty = $objectReflection->getProperty('someProperty');
45. Ini adalah konstanta algoritme sandi yang akan kami gunakan untuk menyandikan
$userReflection = new ReflectionObject($user);

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

$maybeEncodeReflection->setAccessible(true);
$maybeEncodeReflection->invoke($user, $password);
$maybeEncodeReflection->setAccessible(false);
1 yang diberikan. Anda juga dapat menggunakan konstanta
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_47 jika Anda memilih untuk tidak menentukan algoritme. Yang mengatakan,
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_45 adalah nilai
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
47 saat ini

Menggunakan metode refleksi

Sekarang kita memiliki metode pribadi di kelas

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 kita, kita dapat melihat cara membuat refleksi untuk itu. Ini cukup mudah dan mengikuti pola serupa yang telah kita lihat sejauh ini. Anda dapat melihat kode di bawah ini

$userReflection = new ReflectionObject($user);

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

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

Tidak seperti contoh kita sebelumnya dengan kelas

$userReflection = new ReflectionObject($user);

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

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

$maybeEncodeClosure($password);
8, ini hanyalah contoh kode. Yang mengatakan, Anda akan melihat bahwa kita sekali lagi mulai dengan merefleksikan objek
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 kita menggunakan kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
1. Anda bisa menggunakan kelas
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_0 sebagai gantinya jika Anda menginginkannya juga

Setelah itu hal-hal sedikit menyimpang. Pertama, kami memanggil metode

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

$someProperty = $objectReflection->getProperty('someProperty');
55. Kami menggunakannya untuk meminta refleksi dari metode ________0______37

Selanjutnya, kami ingin membuat metode ini dapat diakses. Kami menggunakan metode

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

$someProperty = $objectReflection->getProperty('someProperty');
_24 seperti yang kami lakukan dengan properti pribadi kami. Ini akan memungkinkan kami untuk menggunakan metode ________0______37 kami

Untuk memanggil refleksi metode, Anda harus menggunakan metode

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

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

$someProperty = $objectReflection->getProperty('someProperty');
59 bekerja dengan cara yang sama seperti metode refleksi lain yang telah kita lihat sejauh ini. Anda harus terlebih dahulu memberikannya objek yang Anda inginkan untuk berinteraksi dengan refleksi

Menghasilkan penutupan

Ada juga cara lain untuk mengakses metode privat menggunakan refleksi. Itu dengan menghasilkan penutupan untuk metode yang ingin kita refleksikan. Berikut adalah contoh untuk menunjukkan cara melakukannya

$userReflection = new ReflectionObject($user);

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

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

$maybeEncodeClosure($password);

Seperti yang mungkin Anda perhatikan, ini adalah versi modifikasi dari contoh kami sebelumnya. Bagian pertama dari contoh adalah sama. Kami membuat refleksi dari objek

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 kami. Kami kemudian menggunakan refleksi itu untuk membuat refleksi dari metode
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

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

Bagian terakhir dari contoh adalah di mana hal-hal berubah. Pertama, kami tidak menggunakan metode

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

$someProperty = $objectReflection->getProperty('someProperty');
24. Kami tidak perlu mengubah aksesibilitas metode
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
37 untuk menggunakannya dalam skenario ini

Sebaliknya, kita hanya perlu memanggil metode ________0______65. Ini menghasilkan objek

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

$someProperty = $objectReflection->getProperty('someProperty');
_66. Objek ini memanggil metode
$object = new SomeClass();
$objectReflection = new ReflectionObject($object);

$someProperty = $objectReflection->getProperty('someProperty');
_37 di objek
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 yang kita lewati

Kami melakukannya di baris terakhir. Kami menggunakan variabel

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

$someProperty = $objectReflection->getProperty('someProperty');
_69 sebagai fungsi. Kami memberikan
$userReflection = new ReflectionObject($user);

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

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

Fondasi yang bagus

Ini hanya sebagian kecil dari semua yang dapat Anda lakukan dengan menggunakan pantulan. Seperti yang kami katakan di awal, ini mencakup penggunaan refleksi yang paling umum. Ada lebih banyak kelas dan metode, tetapi penggunaannya jauh lebih situasional

Dengan apa yang Anda lihat di sini, Anda berada dalam kondisi yang baik untuk menggunakan refleksi untuk memecahkan masalah yang menarik. Yang mengatakan, sebagian besar penggunaannya akan berada di sekitar pengujian. Refleksi dan pengujian sering berjalan seiring

Jadi, jika Anda tertarik untuk menguji, ini semua pengetahuan yang bagus untuk dimiliki. Tetapi terlepas dari apakah Anda melakukan pengujian atau tidak (Anda harus melakukannya. ), refleksi adalah konsep ilmu komputer yang penting. Anda mungkin menemukannya dalam bahasa pemrograman lain di kemudian hari dalam karier Anda

Bagaimana cara memanggil metode pribadi di luar kelas di PHP?

Jika dua objek bertipe sama maka satu objek dapat memanggil metode privat objek lainnya. Sintaksis. Variabel, properti, atau metode apa pun dapat dideklarasikan sebagai pribadi dengan mengawalinya dengan kata kunci “pribadi” .

Bagaimana cara mengakses metode pribadi di PHP?

Kata kunci pribadi adalah pengubah akses. Itu menandai properti atau metode sebagai pribadi. Properti dan metode pribadi hanya dapat digunakan oleh kelas di mana properti atau metode didefinisikan. Kelas turunan dan kode luar tidak dapat menggunakannya.

Apa itu metode refleksi dalam PHP?

Istilah "refleksi" dalam pengembangan perangkat lunak berarti bahwa suatu program mengetahui strukturnya sendiri pada waktu proses dan juga dapat memodifikasinya. Kemampuan ini juga disebut sebagai "introspeksi". Di area PHP, refleksi digunakan untuk memastikan keamanan jenis dalam kode program .

Bagaimana cara menggunakan ReflectionClass di PHP?

Contoh untuk Mengimplementasikan Refleksi PHP . Kemudian variabel baru yang disebut "Z1" dibuat dengan konsep ReflectionClass baru. Kemudian objek/metodenya dipanggil dengan bantuan pernyataan gema dan dengan bantuan fungsi getName(). class_alias() function is used with “X1”, “Y1” and “Y1“, “Z1”. Then a new variable called “Z1” is created with the new ReflectionClass concept. Then it's object/method is called with the help of the echo statement and with the help of the getName() function.