diff options
Diffstat (limited to 'documentation/magic-methods.html')
-rw-r--r-- | documentation/magic-methods.html | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/documentation/magic-methods.html b/documentation/magic-methods.html new file mode 100644 index 0000000..87c6cc2 --- /dev/null +++ b/documentation/magic-methods.html @@ -0,0 +1,186 @@ +<h1>Magic methods</h1> +<p> + Every PHP class has "magic methods". You may already know these methods + from writing PHP code: the methods start with two underscores and have + names like __set(), __isset(), __call(), etcetera. +</p> +<p> + The PHP-CPP library also has support for these magic methods. The methods + are already defined in the Php::Base class (which is the base class for + all classes that are written using the PHP-CPP library), and can be + overridden in your derived class. +</p> +<p> + The nice thing about magic methods implemented with PHP-CPP is that they + do not become visible from PHP user space. In other words, when you define + a function like __set() or __unset() in your C++ class, these functions + can not be called explicitly from PHP scripts - but they do get called + when a property is accessed. +</p> +<h2>Pseudo properties</h2> +<p> + With the methods __get(), __set(), __unset() and __isset() you can define + pseudo properties. It allows you to, for example, create read-only properties, + or properties that are checked for validity when they are set. +<p> +<p> + The magic methods work exactly the same as their counterparts in PHP scripts + do, so you can easily port PHP code that uses these properties to C++. +</p> +<p> +<pre class="language-c++"><code> +#include <phpcpp.h> + +/** + * A sample class, that has some pseudo properties that map to native types + */ +class User : public Php::Base +{ +private: + /** + * Name of the user + * @var std::string + */ + std::string _name; + + /** + * Email address of the user + * @var std::string + */ + std::string _email; + +public: + /** + * C++ constructor and C++ destructpr + */ + User() {} + virtual ~User() {} + + /** + * Get access to a property + * @param name Name of the property + * @return Value Property value + */ + virtual Php::Value __get(const Php::Value &name) override + { + // check if the property name is supported + if (name == "name") return _name; + if (name == "email") return _email; + + // property not supported, fall back on default + Php::Base::__get(name); + } + + /** + * Overwrite a property + * @param name Name of the property + * @param value New property value + */ + virtual void __set(const Php::Value &name, const Php::Value &value) override + { + // check the property name + if (name == "name") + { + // store member + _name = value; + } + + // we check emails for validity + else if (name == "email") + { + // store the email in a string + std::string email = value; + + // must have a '@' character in it + if (email.find('@') == std::string::npos) throw Php::Exception("Invalid email address"); + + // store the member + _email = email; + } + + // other properties fall back to default + else + { + // call default + Php::Base::__set(name, value); + } + } + + /** + * Check if a property is set + * @param name Name of the property + * @return bool + */ + virtual bool __isset(const Php::Value &name) override + { + // true for name and email address + if (name == "name" || name == "email") return true; + + // fallback to default + return Php::Base::__isset(name); + } + + /** + * Remove a property + * @param name Name of the property to remove + */ + virtual void __unset(const Php::Value &name) override + { + // name and email can not be unset + if (name == "name" || name == "email") throw Php::Exception("Name and email address can not be removed"); + + // fallback to default + Php::Base::__unset(name); + } +}; + +/** + * Switch to C context to ensure that the get_module() function + * is callable by C programs (which the Zend engine is) + */ +extern "C" { + /** + * Startup function that is called by the Zend engine + * to retrieve all information about the extension + * @return void* + */ + PHPCPP_EXPORT void *get_module() { + + // extension object + static Php::Extension myExtension("my_extension", "1.0"); + + // description of the class so that PHP knows + // which methods are accessible + Php::Class<User> user("User"); + + // add the class to the extension + myExtension.add(std::move(user)); + + // return the extension + return myExtension; + } +} +</code></pre> +</p> +<p> + The above example shows how you can create a User class that seems to have a + name and email property, but that does not allow you to assign an email + address without a '@' character in it, and that does not allow you to + remove the properties. +</p> +<p> +<pre code="language-php"><code> +<?php +// initialize user and set its name and email address +$user = new User(); +$user->name = "John Doe"; +$user->email = "john.doe@example.com"; + +// show the email address +echo($user->email."\n"); + +// remove the email address (this will cause an exception) +unset($user->email); +?> +</code></pre> +</p> |