-
Notifications
You must be signed in to change notification settings - Fork 7
/
README.md~
245 lines (155 loc) · 6.6 KB
/
README.md~
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
REACT-PHP-CPP
=============
Event loop library for PHP implemented in C++. Support for asynchronous non-blocking sockets, DNS lookups and database connections.
REACT-PHP-CPP utilizes the features of the PHP-CPP library and is a wrapper around the REACT-CPP and REACT-CPP-MYSQL libraries. Thus, it depends on the aforementioned libraries.
Event Loop
==========
The ReactPhp::Loop class is wrapped around the React::Loop class of the REACT-CPP library and runs the main PHP event loop. It contains methods to set timers, while it also utilizes callback functions which will be called whenever a filedescriptor becomes readable or writable.
Below is a typical application, where an instance of the event loop is created, which can then be used to register timers and filedescriptors that will be checked for readability:
```php
<?php
// create the event loop
$loop = new Async\Loop();
// set a timeout
$timer1 = $loop->onTimeout(1, function() {
echo("timeout 1 expires\n");
return false;
});
// set a timeout -- alternative way
$timer2 = new Async\TimeoutWatcher($loop, 2, function() {
echo("timeout 2 expires\n");
return false;
});
// notify us when input is available
$reader1 = $loop->onReadable('STDIN_FILENO', function() {
echo("Input is available at first reader\n");
return false;
});
// notify us when input is available -- alternative way
$reader2 = new Async\ReadWatcher($loop, 'STDIN_FILENO', function() {
echo("Input is available at second reader\n");
return false;
});
// the current time
echo($loop->now()."\n");
// run the event loop
$loop->run();
?>
```
After the instance of the event loop is created, it should be run in order to register the timers and filedescriptors.
Connection class
================
The ReactPhp::Connection class is wrapped around the React::MySQL::Connection class of the REACT-CPP-MYSQL library and it can be used to establish a connection to a MySQL daemon, as the following script illustrates:
```php
<?php
// create the event loop
$loop = new Async\Loop();
// establish a connection to MySQL
$connection = new Async\Connection($loop, "mysql.example.org", "example user", "example password", "example database", function() {
echo("Connection established\n");
return false;
});
// run the event loop
$loop->run();
?>
```
Again, an instance of the event loop needs to be created, so that the connection class can be used, whilst the callback function notifies us when the connection is established.
Statements
==========
Naturally, the next step after establishing a connection to a MySQL daemon is to use statements in order to define or manipulate a certain table in a database.
To achieve this we can use the ReactPhp::Statement class, which is also wrapped around the React::MySQL::Statement class of the REACT-CPP-MYSQL library. First, a ReactPhp::Statement object needs to be created in the following fashion:
```php
// initialize a statement
$statement = new Async\Statement($connection, "INSERT INTO Persons (FirstName, LastName, Age) VALUES ('A', 'B', 10), ('C', 'D', 20), ('E', 'F', 30)", function() {
echo("Statement initialized\n");
return false;
});
```
From the above script it is obvious that the connection object is essential in order to create the statement object, since it constitutes the first parameter of the constructor. The second parameter is the actual MySQL statement and the third is the callback function, which notifies us that the statement can be executed.
For the execution to take place, we need to call the ReactPhp::Statement::execute() function. However, when the statement is a SELECT statement, the ReactPhp::Statement::executeQuery() function needs to be called. This happens, because in the case of a query a result object needs to be passed as a parameter in the callback function, so that the result set can be dumped to the screen:
```php
<?php
// create the event loop
$loop = new Async\Loop();
// establish a connection to MySQL
$connection = new Async\Connection($loop, "mysql.example.org", "example user", "example password", "example database", function() {
echo("Connection established\n");
return false;
});
// initialize a statement
$statement = new Async\Statement($connection, "INSERT INTO Persons (FirstName, LastName, Age) VALUES ('A', 'B', 10), ('C', 'D', 20), ('E', 'F', 30)", function() {
echo("Statement initialized\n");
return false;
});
// execute the statement
$statement->execute(function() {
echo("Executing statement\n");
return false;
});
// execute a query statement -- should only be used when we have a SELECT statement
$statement->executeQuery(function($result) {
echo("Executing a SELECT statement\n");
// iterate over the result set
foreach ($result as $row)
{
// wrap the row in curly braces
echo("{ ");
// iterate over each individual row of the result set
foreach ($row as $field)
{
// and dump all the result fields to the screen
echo("$field ");
}
// close the row
echo("}\n");
}
return false;
});
// run the event loop
$loop->run();
?>
```
That, practically, means that all MySQL statements are executed using the ReactPhp::Statement::execute() function, except the SELECT statement, which demands the ReactPhp::Statement::executeQuery() function to execute.
This is the reason why there is a separate function, which can be used for executing queries only, namely the ReactPhp::Connection::query() function. As a result, whenever a query has to be executed, the best approach is to use the aforementioned function and not the ReactPhp::Statement::executeQuery() function, since the former is more straightforward:
```php
<?php
// create the event loop
$loop = new Async\Loop();
// establish a connection to MySQL
$connection = new Async\Connection($loop, "mysql.example.org", "example user", "example password", "example database", function() {
echo("Connection established\n");
return false;
});
// query the database
$connection->query("SELECT * FROM Persons", function($result) {
// iterate over the result set
foreach ($result as $row)
{
// wrap each row in curly braces
echo("{ ");
// iterate over each individual row of the result set
foreach ($row as $field)
{
// and dump all the result fields to the screen
echo("$field ");
}
// close the row
echo("}\n");
}
// alternative way -> iterate over the result set and dump each individual row to the screen
/* for ($i = 0; $i < $result->size(); $i++)
{
// wrap each row in curly braces
echo("{\n");
// fetch the row and dump it to screen
$result->fetchRow($i);
// close the row
echo("\n}\n");
}
*/
return false;
});
// run the event loop
$loop->run();
?>
```