summaryrefslogtreecommitdiff
path: root/documentation/properties.html
blob: 288a7e6d4b00dd3de24dba9635279a5a5462acc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
<h1>Class properties</h1>
<p>
    When you define a class completely in PHP, you can add properties (member 
    variables) to it. When you add member variables to a native C++ class however, 
    you better use regular native member variables for that, instead of PHP variables.
    Native variables have an immensely better performance than PHP variables,
    and it would be insane to store integers or strings in Php::Value objects
    if you can store them in int's and std::string objects as well.
</p>
<h2 id="normal-members">Normal member variables</h2>
<p>
    It is difficult to imagine that someone in the world would like to create
    a native class, with regular non-typed public PHP properties on it. However,
    if you insist, you can use the PHP-CPP library for this. Let's take an example
    class in PHP, and see what it would look like in C++.
</p>
<p>
<pre class="language-php"><code>
&lt;?php
/**
 *  PHP example class
 */
class Example
{
    /**
     *  Define a public property
     */
    public $property1;

    /**
     *  Constructor
     */
    public function __construct()
    {
        // initialize the property
        $this->property1 = "xyz";
    }
    
    /**
     *  Example method
     */
    public function method()
    {
        // do something with the public property (like changing it)
        $this->property = "abc";
    }
}

// create an instance
$example = new Example();

// overwrite the public property
$example->property1 = "new value";

?&gt;
</code></pre>
</p>
<p>
    The above example creates a class with one public property. This property
    can be accessed by the Example class, and because it is public also by
    everyone else, as is shown in the example. If you like such classes, you can 
    write something similar with PHP-CPP.
</p>
<p>
<pre class="language-cpp"><code>
#include &lt;phpcpp.h&gt;

/**
 *  C++ Example class
 */
class Example : public Php::Base
{
public:
    /**
     *  c++ constructor
     */
    Example() {}
    
    /**
     *  c++ destructor
     */
    virtual ~Example() {}
    
    /**
     *  php "constructor"
     *  @param  params
     */
    void __construct()
    {
        // get self reference as Php::Value object
        Php::Value self(this);
        
        // initialize a public property
        self["property1"] = "xyz";
    }
    
    /**
     *  Example method
     */
    void method()
    {
        // get self reference as Php::Value object
        Php::Value self(this);

        // overwrite the property
        self["property1"] = "abc";
    }
};

/**
 *  Switch to C context so that the get_module() function can be
 *  called by C programs (which the Zend engine is)
 */
extern "C" {
    /**
     *  Startup function for the extension
     *  @return void*
     */
    PHPCPP_EXPORT void *get_module() {
        // create static 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;Example&gt; example("Example");
        
        // register the methods
        example.method("__construct", &amp;Example::__construct);
        example.method("method", &amp;Example::method);
        
        // the Example class has one public property
        example.property("property1", "xyz", Php::Public);
        
        // add the class to the extension
        myExtension.add(std::move(example));
        
        // return the extension
        return myExtension;
    }
}
</code></pre>
</p>
<p>
    The example code shows how you initialize the properties inside
    the get_module() function.
</p>
<p>
    Instead of public properties, you can also define private or protected
    properties, but even that is probably not what you want, as storing 
    data in native C++ variables is much faster.
</p>
<h2 id="constants">Class constants</h2>
<p>
    Class constants can be defined in a similar way as properties. The only
    difference is that you have to pass in the flag 'Php::Const' instead of 
    one of the public, private or protected access modifiers.
</p>
<p>
<pre class="language-cpp"><code>
#include &lt;phpcpp.h&gt;

// @todo you class definition

/**
 *  Switch to C context so that the get_module() function can be
 *  called by C programs (which the Zend engine is)
 */
extern "C" {
    /**
     *  Startup function for the extension
     *  @return void*
     */
    PHPCPP_EXPORT void *get_module() {
        // create static 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;Example&gt; example("Example");
        
        // the Example class has a class constant
        example.property("MY_CONSTANT", "some value", Php::Const);
        
        // add the class to the extension
        myExtension.add(std::move(example));
        
        // return the extension
        return myExtension;
    }
}
</code></pre>
</p>
<p>
    The class constant can be accessed from PHP scripts using Example::MY_CONSTANT.
</p>
<h2>Smart properties</h2>
<p>
    With the <a href="magic-methods">magic methods __get() and __set()</a> you
    can make more advanced properties that are directly mapped to C++
    variables, and that allow you to perform additional checks when a property
    is overwritten, so that an object always remains in a valid state.
</p>
<p>
    On top of that, with the PHP-CPP library you can also assign getter and
    setter methods to properties. Every time a property is accessed, your getter
    or setter method is automatically called.
</p>
<p>
<pre class="language-cpp"><code>
#include &lt;phpcpp.h&gt;

/**
 *  C++ Example class
 */
class Example : public Php::Base
{
private:
    /**
     *  Example property
     *  @var    int
     */
    int _value = 0;
    
    
public:
    /**
     *  c++ constructor
     */
    Example() {}
    
    /**
     *  c++ destructor
     */
    virtual ~Example() {}
    
    /**
     *  Method to get access to the property
     *  @return Php::Value
     */
    Php::Value getValue() const
    {
        return _value;
    }
    
    /**
     *  Method to overwrite the property
     *  @param  value
     */
    void setValue(const Php::Value &amp;value)
    {
        // overwrite property
        _value = value;
        
        // sanity check: the value should never exceed 100
        if (_value > 100) _value = 100;
    }
        
    /**
     *  Method to retrieve the double property value
     *  @return Php::Value
     */
    Php::Value getDouble() const
    {
        return _value * 2;
    }
};

/**
 *  Switch to C context so that the get_module() function can be
 *  called by C programs (which the Zend engine is)
 */
extern "C" {
    /**
     *  Startup function for the extension
     *  @return void*
     */
    PHPCPP_EXPORT void *get_module() {
        // create static 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;Example&gt; example("Example");
        
        // register the "value" property, with the methods to get and set it
        example.property("value", &amp;Example::getValue, &amp;Example::setValue);
        
        // register a read-only "double" property, with a method to get it
        example.property("double", &amp;Example::getDouble);
        
        // add the class to the extension
        myExtension.add(std::move(example));
        
        // return the extension
        return myExtension;
    }
}
</code></pre>
</p>
<p>
    The following PHP script uses this. It created an example object, sets the
    value property to 500 (which is not allowed, values higher than 100 are 
    rounded to 100), and then it reads out the double value.
</p>
<p>
<pre class="language-php"><code>
&lt;?php
// create object
$object = new Example();

// set the value
$object->value = 500;

// show the double value
echo($object->double."\n");

// update the double value
// (this will trigger an error, this is a read-only property)
$object->double = 300;
?&gt;
</code></pre>