summaryrefslogtreecommitdiff
path: root/documentation/inheritance.html
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-03 14:14:49 +0200
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-03 14:14:49 +0200
commit6e2556ab445169cadb21d9ba16eb77d7350a79f7 (patch)
treecd7360bd946870f204af69b8ed057cb3c59663be /documentation/inheritance.html
parent8ce7055ebfbd28f283e08eb822980a7f4641c0cd (diff)
update documentation about inheritance
Diffstat (limited to 'documentation/inheritance.html')
-rw-r--r--documentation/inheritance.html137
1 files changed, 137 insertions, 0 deletions
diff --git a/documentation/inheritance.html b/documentation/inheritance.html
new file mode 100644
index 0000000..f4f027e
--- /dev/null
+++ b/documentation/inheritance.html
@@ -0,0 +1,137 @@
+<h1>Inheritance</h1>
+<p>
+ Both PHP and C++ are object oriented programming languages that support
+ class inheritance. There are some differences: C++ supports multiple
+ inheritance, while a PHP class can only have a single base class.
+ To make up for not having multiple inheritance, PHP supports interfaces
+ and traits.
+</p>
+<p>
+ The PHP-CPP library also allows you to define PHP interfaces and to create
+ hierarchies of PHP classes and PHP interfaces.
+<p>
+<h2 id="defining-interfaces">Defining interfaces</h2>
+<p>
+ In case you want your extension to <i>define</i> an interface, so that the
+ interface can be implemented from PHP user space scripts, you can do that
+ almost in a similar way to how you would define a class. The only
+ difference is that you do not use Php::Class&lt;YourClass&gt;, but a
+ Php::Interface instance.
+</p>
+<p>
+<pre class="language-c++"><code>
+/**
+ * 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() {
+ // create static instance of the extension object
+ static Php::Extension myExtension("my_extension", "1.0");
+
+ // description of the interface so that PHP knows which methods
+ // are defined by it
+ Php::Interface interface("MyInterface");
+
+ // define an interface method
+ interface.method("myMethod", {
+ Php::ByVal("value", Php::Type::String, true)
+ });
+
+ // register other methods
+ ...
+
+ // add the interface to the extension
+ // (or move it into the extension, which is faster)
+ myExtension.add(std::move(interface));
+
+ // return the extension
+ return myExtension;
+ }
+}
+</code></pre>
+</p>
+<h2 id="deriving-and-implementing">Deriving and implementing</h2>
+<p>
+ The PHP-CPP library tries to make working with PHP and C++ as transparent
+ as possible. C++ functions can be called from PHP userspace scripts,
+ and C++ classes can be made accessible from PHP. However, in the end PHP
+ and C++ are still different languages, and because C++ does not have the
+ same reflection features as PHP, you will have to explicit tell the PHP
+ engine which base classes and interfaces the class implements.
+</p>
+<p>
+ The Php::Class&lt;YourClass&gt; object has a method 'extends()' and a
+ method 'implements()' that can be used for specifying the base classes
+ and implemented interfaces. You need to pass in a class or interface that
+ you configured before. Let's look at an example.
+</p>
+<p>
+<p>
+<pre class="language-c++"><code>
+/**
+ * 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() {
+ // create static instance of the extension object
+ static Php::Extension myExtension("my_extension", "1.0");
+
+ // description of the interface so that PHP knows which methods
+ // are defined by it
+ Php::Interface myInterface("MyInterface");
+
+ // define an interface method
+ myInterface.method("myMethod", {
+ Php::ByVal("value", Php::Type::String, true)
+ });
+
+ // register our own class
+ Php::Class&lt;MyClass&gt; myClass("MyClass");
+
+ // from PHP user space scripts, it must look like the myClass implements
+ // the MyInterface interface
+ myClass.implements(myInterface);
+
+ // the interface requires that the myMethod method is implemented
+ myClass.method("myMethod", &amp;MyClass::myMethod, {
+ Php::ByVal("value", Php::Type::String, true)
+ });
+
+ // create a third class
+ Php::Class&lt;DerivedClass&gt; derivedClass("DerivedClass");
+
+ // in PHP scripts, it should look like DerivedClass has "MyClass"
+ // as its base
+ derivedClass.extends(myClass);
+
+ // add the interface and the classes to the extension
+ myExtension.add(myInterface);
+ myExtension.add(myClass);
+ myExtension.add(derivedClass);
+
+ // return the extension
+ return myExtension;
+ }
+}
+</code></pre>
+</p>
+<p>
+ Be aware that the PHP class hierarchy that you define inside the get_module()
+ function does not have to match the C++ class hierarchy. Your C++ class
+ "DerivedClass" does not at all have to have "MyClass" as its base, even
+ although in PHP scripts it would look like it has. For code maintainability
+ is it of course better to make the PHP signature more or less similar to the
+ C++ implementation.
+<p>