summaryrefslogtreecommitdiff
path: root/documentation
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-10 13:37:09 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-10 13:37:09 +0100
commitdd3422f6ed454d06e6091ad5023da7fc294595b8 (patch)
treed37cc9cc541f4e6cc2fb4c1c04c704620b7151c7 /documentation
parent4872cc627642044f46ba8a8726902592a1fae05f (diff)
splitted magic-methods-and-interfaces documentation into two seperate documentation files, added documentation about __set(), __get(), __isset() and __unset()
Diffstat (limited to 'documentation')
-rw-r--r--documentation/magic-interfaces.html (renamed from documentation/magic-methods-and-interfaces.html)40
-rw-r--r--documentation/magic-methods.html186
2 files changed, 203 insertions, 23 deletions
diff --git a/documentation/magic-methods-and-interfaces.html b/documentation/magic-interfaces.html
index f485805..1664e3c 100644
--- a/documentation/magic-methods-and-interfaces.html
+++ b/documentation/magic-interfaces.html
@@ -1,33 +1,28 @@
-<h1>Magic methods and interfaces</h1>
+<h1>Magic interfaces</h1>
<p>
- PHP classes have a number of magic methods that you can implement to
- enable special features. These are methods like __toString(), __get(), __set(),
- __invoke(), etcetera. With the PHP-CPP library you can implement these
- magic methods too.
-</p>
-<p>
- Besides that, a core PHP installation also comes with a number of interfaces
- that you can implement to add even more special features to a class. These
+ A core PHP installation comes with a number of special "magic" PHP interfaces
+ that script writers can implement to add special features to a class. These
are interfaces with names like 'Countable', 'ArrayAccess' and 'Serializable'.
The features that these interfaces bring, can also be implemented using
PHP-CPP.
</p>
<p>
- So there are magic methods and interfaces. Strangely enough,
- there does not seem to be any uniformity in the Zend engine in the choice
- between these magic methods and interfaces. To us it is unclear why some special features
- are implemented with magic methods, while others are activated by implementing
- interfaces. In our eyes the Serializable interface could just as well have
- been implemented with magic __serialize() and __unserialize() methods, or the
- __invoke() method could just as well have been an "Invokable" interface.
- PHP is not a standardized language, and some things just seem to be the way they
- are because someone felt like implementing it this way or another...
+ You may wonder why PHP sometimes uses <a href="magic-methods">magic methods</a>
+ (for example __set and __unset) and sometimes uses interfaces to change the
+ behavior of a class. There does not seem to be any uniformity in the choice
+ between these magic methods and interfaces. To us it is unclear why some
+ special features are implemented with magic methods, while others are activated
+ by implementing interfaces. In our eyes the Serializable interface could just
+ as well have been implemented with magic __serialize() and __unserialize()
+ methods, or the __invoke() method could just as well have been an "Invokable"
+ interface. PHP is not a standardized language, and some things just seem to be
+ the way they are because someone felt like implementing it this way or another...
</p>
<p>
The PHP-CPP library tries to stay as close to PHP as possible. That's why in
- your C++ classes you can also override the magic methods and implement the
- special interfaces - and because C++ does not have interfaces like PHP has,
- we use classes with pure virtual methods instead.
+ your C++ classes you can also use the special interfaces - and because C++
+ does not have interfaces like PHP has, classes with pure virtual methods are
+ used instead.
</p>
<h2>Support for the SPL</h2>
<p>
@@ -51,8 +46,7 @@
<h2>The Countable interface</h2>
<p>
By implementing the Php::Countable interface, you can create objects that
- can be passed to the PHP count() function. You have to implement a count()
- method that returns the value that you want the count() function to return.
+ can be passed to the PHP count() function.
</p>
<p>
<pre class="language-c++"><code>
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 &lt;phpcpp.h&gt;
+
+/**
+ * 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 &amp;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 &amp;name, const Php::Value &amp;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 &amp;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 &amp;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&lt;User&gt; 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>
+&lt;?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);
+?&gt;
+</code></pre>
+</p>