advanced.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. Advanced
  2. ========
  3. - `PhantomJS command line options <#phantomjs-command-line-options>`__
  4. - `Custom PhantomJS scripts <#custom-phantom-js-scripts>`__
  5. - `Writing a custom script <#writing-a-custom-script>`__
  6. - `Using custom request parameters in your
  7. script <#using-custom-request-parameters-in-your-script>`__
  8. - `Loading your script <#loading-your-script>`__
  9. PhantomJS command line options
  10. ------------------------------
  11. The PhantomJS API contains a range of command line options that can be
  12. passed when executing the PhantomJS executable. These can also be passed
  13. in via the client before a request:
  14. .. code:: php
  15. <?php
  16. use JonnyW\PhantomJs\Client;
  17. $client = Client::getInstance();
  18. $client->addOption('--load-images=true');
  19. $client->addOption('--ignore-ssl-errors=true');
  20. $request = $client->getMessageFactory()->createRequest('http://google.com');
  21. $response = $client->getMessageFactory()->createResponse();
  22. $client->send($request, $response);
  23. You can also set a path to a JSON configuration file that contains
  24. multiple PhantomJS options:
  25. .. code:: php
  26. <?php
  27. use JonnyW\PhantomJs\Client;
  28. $client = Client::getInstance();
  29. $client->addOption('--config=/path/to/config.json');
  30. $request = $client->getMessageFactory()->createRequest('http://google.com');
  31. $response = $client->getMessageFactory()->createResponse();
  32. $client->send($request, $response);
  33. See the `PhantomJS
  34. Documentation <http://phantomjs.org/api/command-line.html>`__ for a full
  35. list of command line options.
  36. Custom PhantomJS scripts
  37. ------------------------
  38. In most instances you shouldn't need to worry about the javascript files
  39. that run the PHP PhantomJS library but there may be times when you want
  40. to execute your own custom PhantomJS scripts through the client. This
  41. can be easily achieved by using the built in script loader.
  42. Script files or 'procedures' as they are referred to in the application
  43. are closely mapped to requests. When you create a default request
  44. instance, you are essentially running the default javascript procedure
  45. that comes bundled with the application. When you create a capture
  46. request you are running the capture procedure.
  47. .. code:: php
  48. <?php
  49. use JonnyW\PhantomJs\Client;
  50. $client->getMessageFactory()->createRequest(); // ~/Resources/procedures/default.proc
  51. $client->getMessageFactory()->createCaptureRequest(); // ~/Resources/procedures/capture.proc
  52. Writing a custom script
  53. ~~~~~~~~~~~~~~~~~~~~~~~
  54. The first step in creating your script is to create a procedure file
  55. somewhere. For the purpose of this guide we will refer to it as
  56. ``my_procedure.proc`` but in reality it can be called anything you like.
  57. The only requirement is that the file extension must be ``.proc``.
  58. Create the file somewhere and make sure it can be read by your
  59. application. Make a note of the path to the directory where your file is
  60. created as you will need this when loading your script which is
  61. explained later in this guide.
  62. .. code:: shell
  63. $ touch my_procedure.proc
  64. $ chmod 755 my_procedure.proc
  65. Next open your procedure file in your text editor and write your
  66. PhantomJS script. The `PhantomJS
  67. documentation <http://phantomjs.org/quick-start.html>`__ has more
  68. detailed information on writing custom scripts.
  69. .. code:: javascript
  70. // my_procedure.proc
  71. var page = require('webpage').create();
  72. page.open ('{{ request.getUrl() }}', '{{ request.getMethod() }}', '{{ request.getBody() }}', function (status) {
  73. // It is important that you exit PhantomJS
  74. // when your script has run or when you
  75. // encounter an error
  76. phantom.exit(1);
  77. });
  78. ...
  79. .. important::
  80. Make sure that ``phantom.exit(1);`` is always called after your script has run or if you encounter an error. This requires you to take care when handling PhantomJS errors to ensure that you exit the PhantomJS script, whether the script was successfully executed or not. If you do not call ``phantom.exit(1);`` then PhantomJS will continue to run until your PHP script times out. If you find that your custom script is hanging then this is most likely the cause.
  81. It is a good practice to create a global error handler in your script
  82. that exits PhantomJS:
  83. .. code:: javascript
  84. // my_procedure.proc
  85. phantom.onError = function(msg, trace) {
  86. phantom.exit(1);
  87. };
  88. ...
  89. Using custom request parameters in your script
  90. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  91. Before a procedure is executed by the application it is parsed through a
  92. template parser. The PHP PhantomJS library uses the popular `Twig
  93. templating engine <https://github.com/fabpot/Twig>`__. This gives you
  94. access to all the `Twig
  95. niceness <http://twig.sensiolabs.org/doc/templates.html>`__ which you
  96. can use in your custom scripts.
  97. You may have noticed in the example above that we have used some Twig
  98. template tags referencing a request object e.g.
  99. ``{{ request.getUrl() }}``. This is in fact the PHP request instance
  100. that you created and passed to the client when sending your request,
  101. which is injected into the Twig template parser. As a result you gain
  102. full access to all the data contained within the request instance, via
  103. the data accessor methods.
  104. A default request instance contains the following accessors:
  105. +--------------------------+-----------------------------------------------+------------------------------------+
  106. | Accessor | Description | Twig example |
  107. +==========================+===============================================+====================================+
  108. | getMethod() | The request method e.g. GET. | {{ request.getMethod() }} |
  109. +--------------------------+-----------------------------------------------+------------------------------------+
  110. | getTimeout() | The request timeout period in milliseconds. | {{ request.getTimeout() }} |
  111. +--------------------------+-----------------------------------------------+------------------------------------+
  112. | getDelay() | The page render delay in seconds. | {{ request.getDelay() }} |
  113. +--------------------------+-----------------------------------------------+------------------------------------+
  114. | getViewportWidth() | The viewport width. | {{ request.getViewportWidth() }} |
  115. +--------------------------+-----------------------------------------------+------------------------------------+
  116. | getViewportHeight() | The viewport height. | {{ request.getViewportHeight() }} |
  117. +--------------------------+-----------------------------------------------+------------------------------------+
  118. | getUrl() | The request URL. | {{ request.getUrl() }} |
  119. +--------------------------+-----------------------------------------------+------------------------------------+
  120. | getBody() | The request body (POST, PUT). | {{ request.getBody() }} |
  121. +--------------------------+-----------------------------------------------+------------------------------------+
  122. | getHeaders(\ *format*) | The request headers. | {{ request.getHeaders('json') }} |
  123. +--------------------------+-----------------------------------------------+------------------------------------+
  124. A capture request contains a few additional ones:
  125. +--------------------+-------------------------------------------+----------------------------------+
  126. | Accessor | Description | Twig example |
  127. +====================+===========================================+==================================+
  128. | getRectTop() | The x coordinate of the capture region. | {{ request.getRectTop() }} |
  129. +--------------------+-------------------------------------------+----------------------------------+
  130. | getRectLeft() | The y coordinate of the capture region. | {{ request.getRectLeft() }} |
  131. +--------------------+-------------------------------------------+----------------------------------+
  132. | getRectWidth() | The width of the capture region. | {{ request.getRectWidth() }} |
  133. +--------------------+-------------------------------------------+----------------------------------+
  134. | getRectHeight() | The height of the capture region. | {{ request.getRectHeight() }} |
  135. +--------------------+-------------------------------------------+----------------------------------+
  136. | getCaptureFile() | The file to save the capture to. | {{ request.getCaptureFile() }} |
  137. +--------------------+-------------------------------------------+----------------------------------+
  138. If you would like to inject additional data into your script through
  139. custom accessors, simply extend the request class with your own:
  140. .. code:: php
  141. <?php
  142. use JonnyW\PhantomJs\Message\Request;
  143. class CustomRequest extends Request
  144. {
  145. public function getSomething()
  146. {
  147. return 'Something!';
  148. }
  149. }
  150. Now you will be able to access the data in your custom script when using
  151. your custom request:
  152. .. code:: javascript
  153. // my_procedure.proc
  154. var something = '{{ request.getSomething() }}'; // Get something
  155. ...
  156. And to use your custom request simply create a new instance of it and
  157. pass it to the client:
  158. .. code:: php
  159. <?php
  160. use JonnyW\PhantomJs\Client;
  161. $client = Client::getInstance();
  162. $response = $client->getMessageFactory()->createResponse();
  163. $request = new CustomRequest();
  164. $request->setMethod('GET');
  165. $request->setUrl('http://www.google.com');
  166. $client->send($request, $response);
  167. Loading your script
  168. ~~~~~~~~~~~~~~~~~~~
  169. Now that you have your custom script and you've added your custom
  170. request parameters, you may be wondering how to tell the client to
  171. actually load your script. This is done by creating a procedure loader
  172. and telling it where to find your script files.
  173. The service container has a factory that makes creating a new procedure
  174. loader easy:
  175. .. code:: php
  176. <?php
  177. use JonnyW\PhantomJs\Client;
  178. use JonnyW\PhantomJs\DependencyInjection\ServiceContainer;
  179. $location = '/path/to/your/procedure/directory';
  180. $serviceContainer = ServiceContainer::getInstance();
  181. $procedureLoader = $serviceContainer->get('procedure_loader_factory')
  182. ->createProcedureLoader($location);
  183. ...
  184. The client contains a chain procedure loader which lets you set multiple
  185. loaders at the same time. Ultimately this means that you can load your
  186. custom scripts while still maintaining the ability to load the default
  187. scripts if you choose.
  188. Now add your procedure loader to the chain loader:
  189. .. code:: php
  190. <?php
  191. ...
  192. $client = Client::getInstance();
  193. $client->getProcedureLoader()->addLoader($procedureLoader);
  194. ...
  195. The last thing you need to do is to tell the request which script you
  196. want to load for that request. This is done by setting the request type
  197. to the name of your procedure file, minus the extension:
  198. .. code:: php
  199. <?php
  200. ...
  201. $request = $client->getMessageFactory()->createRequest();
  202. $request->setType('my_procedure');
  203. ...
  204. Or if you are using a custom request as outlined in the `custom request
  205. parameters <#using-custom-request-parameters-in-your-script>`__ section,
  206. you can implement a ``getType()`` method which returns the name of your
  207. procedure, eliminating the need to set the request type for each
  208. request:
  209. .. code:: php
  210. <?php
  211. use JonnyW\PhantomJs\Message\Request;
  212. class CustomRequest extends Request
  213. {
  214. public function getType()
  215. {
  216. return 'my_procedure';
  217. }
  218. }
  219. Below is a full example for clarity:
  220. .. code:: php
  221. <?php
  222. use JonnyW\PhantomJs\Client;
  223. use JonnyW\PhantomJs\DependencyInjection\ServiceContainer;
  224. $location = '/path/to/your/procedure/directory';
  225. $serviceContainer = ServiceContainer::getInstance();
  226. $procedureLoader = $serviceContainer->get('procedure_loader_factory')
  227. ->createProcedureLoader($location);
  228. $client = Client::getInstance();
  229. $client->getProcedureLoader()->addLoader($procedureLoader);
  230. $request = $client->getMessageFactory()->createRequest();
  231. $request->setType('my_procedure');
  232. $response = $client->getMessageFactory()->createResponse();
  233. $client->send($request, $response);
  234. .. important::
  235. If you find that your script isn't running or that you are receiving a status of '0' back in the response, chances are you have a syntax error in you script. It pays to turn debugging on in the client ``$client->debug(true)`` which will then give you access to some log information through ``$client->getLog()``.
  236. See more detailed information about
  237. `troubleshooting https://github.com/jonnnnyw/php-phantomjs/blob/master/doc/troubleshooting.rst>`__.