scratch – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
115 | office | 1 | # Binary Driver |
2 | |||
3 | Binary-Driver is a set of PHP tools to build binary drivers. |
||
4 | |||
5 | [![Build Status](https://travis-ci.org/alchemy-fr/BinaryDriver.png?branch=master)](https://travis-ci.org/alchemy-fr/BinaryDriver) |
||
6 | |||
7 | ## Why ? |
||
8 | |||
9 | You may wonder *Why building a library while I can use `exec` or |
||
10 | [symfony/process](https://github.com/symfony/Process) ?*. |
||
11 | |||
12 | Here is a simple answer : |
||
13 | |||
14 | - If you use `exec`, `passthru`, `system`, `proc_open` or any low level process |
||
15 | handling in PHP, you should have a look to [symfony/process](https://github.com/symfony/Process) |
||
16 | component that will provide an OO portable, testable and secure interface to |
||
17 | deal with this. It seems easy at first approach, but if you look at this |
||
18 | component [unit tests](https://github.com/symfony/Process/tree/master/Tests), |
||
19 | you will see that handling process in a simple interface can easily become a |
||
20 | nightmare. |
||
21 | |||
22 | - If you already use symfony/process, and want to build binary drivers, you |
||
23 | will always have the same common set of methods and objects to configure, log, |
||
24 | debug, and generate processes. |
||
25 | This library is a base to implement any binary driver with this common set of |
||
26 | needs. |
||
27 | |||
28 | ## AbstractBinary |
||
29 | |||
30 | `AbstractBinary` provides an abstract class to build a binary driver. It implements |
||
31 | `BinaryInterface`. |
||
32 | |||
33 | Implementation example : |
||
34 | |||
35 | ```php |
||
36 | use Alchemy\BinaryDriver\AbstractBinary; |
||
37 | |||
38 | class LsDriver extends AbstractBinary |
||
39 | { |
||
40 | public function getName() |
||
41 | { |
||
42 | return 'ls driver'; |
||
43 | } |
||
44 | } |
||
45 | |||
46 | $parser = new LsParser(); |
||
47 | |||
48 | $driver = Driver::load('ls'); |
||
49 | // will return the output of `ls -a -l` |
||
50 | $parser->parse($driver->command(array('-a', '-l'))); |
||
51 | ``` |
||
52 | |||
53 | ### Binary detection troubleshooting |
||
54 | |||
55 | If you are using Nginx with PHP-fpm, executable detection may not work because of an empty `$_ENV['path']`. |
||
56 | To avoid having an empty `PATH` environment variable, add the following line to your `fastcgi_params` |
||
57 | config file (replace `/your/current/path/` with the output of `printenv PATH`) : |
||
58 | |||
59 | ``` |
||
60 | fastcgi_param PATH /your/current/path |
||
61 | ``` |
||
62 | |||
63 | ## Logging |
||
64 | |||
65 | You can log events with a `Psr\Log\LoggerInterface` by passing it in the load |
||
66 | method as second argument : |
||
67 | |||
68 | ```php |
||
69 | $logger = new Monolog\Logger('driver'); |
||
70 | $driver = Driver::load('ls', $logger); |
||
71 | ``` |
||
72 | |||
73 | ## Listeners |
||
74 | |||
75 | You can add custom listeners on processes. |
||
76 | Listeners are built on top of [Evenement](https://github.com/igorw/evenement) |
||
77 | and must implement `Alchemy\BinaryDriver\ListenerInterface`. |
||
78 | |||
79 | ```php |
||
80 | use Symfony\Component\Process\Process; |
||
81 | |||
82 | class DebugListener extends EventEmitter implements ListenerInterface |
||
83 | { |
||
84 | public function handle($type, $data) |
||
85 | { |
||
86 | foreach (explode(PHP_EOL, $data) as $line) { |
||
87 | $this->emit($type === Process::ERR ? 'error' : 'out', array($line)); |
||
88 | } |
||
89 | } |
||
90 | |||
91 | public function forwardedEvents() |
||
92 | { |
||
93 | // forward 'error' events to the BinaryInterface |
||
94 | return array('error'); |
||
95 | } |
||
96 | } |
||
97 | |||
98 | $listener = new DebugListener(); |
||
99 | |||
100 | $driver = CustomImplementation::load('php'); |
||
101 | |||
102 | // adds listener |
||
103 | $driver->listen($listener); |
||
104 | |||
105 | $driver->on('error', function ($line) { |
||
106 | echo '[ERROR] ' . $line . PHP_EOL; |
||
107 | }); |
||
108 | |||
109 | // removes listener |
||
110 | $driver->unlisten($listener); |
||
111 | ``` |
||
112 | |||
113 | ### Bundled listeners |
||
114 | |||
115 | The debug listener is a simple listener to catch `stderr` and `stdout` outputs ; |
||
116 | read the implementation for customization. |
||
117 | |||
118 | ```php |
||
119 | use Alchemy\BinaryDriver\Listeners\DebugListener; |
||
120 | |||
121 | $driver = CustomImplementation::load('php'); |
||
122 | $driver->listen(new DebugListener()); |
||
123 | |||
124 | $driver->on('debug', function ($line) { |
||
125 | echo $line; |
||
126 | }); |
||
127 | ``` |
||
128 | |||
129 | ## ProcessBuilderFactory |
||
130 | |||
131 | ProcessBuilderFactory ease spawning processes by generating Symfony [Process] |
||
132 | (http://symfony.com/doc/master/components/process.html) objects. |
||
133 | |||
134 | ```php |
||
135 | use Alchemy\BinaryDriver\ProcessBuilderFactory; |
||
136 | |||
137 | $factory = new ProcessBuilderFactory('/usr/bin/php'); |
||
138 | |||
139 | // return a Symfony\Component\Process\Process |
||
140 | $process = $factory->create('-v'); |
||
141 | |||
142 | // echoes '/usr/bin/php' '-v' |
||
143 | echo $process->getCommandLine(); |
||
144 | |||
145 | $process = $factory->create(array('-r', 'echo "Hello !";')); |
||
146 | |||
147 | // echoes '/usr/bin/php' '-r' 'echo "Hello !";' |
||
148 | echo $process->getCommandLine(); |
||
149 | ``` |
||
150 | |||
151 | ## Configuration |
||
152 | |||
153 | A simple configuration object, providing an `ArrayAccess` and `IteratorAggregate` |
||
154 | interface. |
||
155 | |||
156 | ```php |
||
157 | use Alchemy\BinaryDriver\Configuration; |
||
158 | |||
159 | $conf = new Configuration(array('timeout' => 0)); |
||
160 | |||
161 | echo $conf->get('timeout'); |
||
162 | |||
163 | if ($conf->has('param')) { |
||
164 | $conf->remove('param'); |
||
165 | } |
||
166 | |||
167 | $conf->set('timeout', 20); |
||
168 | |||
169 | $conf->all(); |
||
170 | ``` |
||
171 | |||
172 | Same example using the `ArrayAccess` interface : |
||
173 | |||
174 | ```php |
||
175 | use Alchemy\BinaryDriver\Configuration; |
||
176 | |||
177 | $conf = new Configuration(array('timeout' => 0)); |
||
178 | |||
179 | echo $conf['timeout']; |
||
180 | |||
181 | if (isset($conf['param'])) { |
||
182 | unset($conf['param']); |
||
183 | } |
||
184 | |||
185 | $conf['timeout'] = 20; |
||
186 | ``` |
||
187 | |||
188 | ## License |
||
189 | |||
190 | This project is released under the MIT license. |