Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Zephir - A Wind of Change for writing PHP extensions

1.462 Aufrufe

Veröffentlicht am

Slides from the tutorial given at the PHPNW2015 conference

Veröffentlicht in: Software
  • Als Erste(r) kommentieren

Zephir - A Wind of Change for writing PHP extensions

  1. 1. Zephir A WIND OF CHANGE FOR WRITING PHP EXTENSIONS
  2. 2. What is Zephir? Zephir – Zend Engine PHP Intermediate. A high-level domain-specific language (DSL) that simplifies the creation and maintain-ability of native C extensions for PHP. Developed by the team behind Phalcon, the PHP CMS written in C.
  3. 3. What is Zephir? The creators of Zephir actually pronounce it “zaefire”. (/ˈzäfī(-ə)r/) But I still pronounce it “Zephir” (/ˈzef.ər/) The Zephir Language is an open source project licensed under an MIT license. Zephir is written in PHP.
  4. 4. What is Zephir? In a nutshell Zephir makes it easy for high-level developers write low-level PHP Extensions.
  5. 5. Writing a PHP Extension https://wiki.php.net/internals/references http://www.phpinternalsbook.com/ http://www.amazon.com/Extending-Embedding-PHP-Sara-Golemon/dp/067232704X
  6. 6. Why might I write an Extension? Native C Extensions to PHP can typically execute faster than raw PHP code. The ability to use native C datatypes in an Extension may help save memory usage. Deploying an Extension allows you to keep the source of your code closed.
  7. 7. Why might I write an Extension? If a class is heavily IO bound, or requires the allocation/ deallocation of large amounts of memory, then you will probably not gain any performance benefits. Unless you can take advantage of the native C datatypes internally in the code, then you will probably not gain any memory benefits.
  8. 8. Why might I write an Extension? Performance comparison HHVM vs Zephir vs PHP https://www.simonholywell.com/post/2014/02/hhvm-vs-zephir-vs-php-the- showdown/ https://www.simonholywell.com/static/files/2014-02-28/index.html Simon Holywell Australian Zend certified Development Director at Mosaic in Brighton, UK
  9. 9. What is Zephir? http://zephir-lang.com/ https://github.com/phalcon/zephir
  10. 10. Zephir – Installation (Ubuntu) Requirements ◦gcc >= 4.x/clang >= 3.x ◦re2c 0.13 or later ◦gnu make 3.81 or later ◦autoconf 2.31 or later ◦automake 1.14 or later ◦libpcre3 ◦php development headers and tools
  11. 11. Zephir – Installation (Ubuntu) $ sudo apt-get update $ sudo apt-get install -y python-software-properties $ sudo apt-get install -y curl $ sudo apt-get install -y git gcc make re2c libpcre3-dev $ sudo add-apt-repository ppa:ondrej/php5-5.6 $ sudo apt-get update $ sudo apt-get install -y php5 dh-make-php php5-dev $ sudo apt-get install -y php5-curl php5-gd php5-gmp php5-mcrypt php5-intl php5-cli
  12. 12. Zephir – Installation (Ubuntu) $ php –v PHP 5.6.13-1+deb.sury.org~precise+3 (cli) Copyright (c) 1997-2015 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies $ phpize –v Configuring for: PHP Api Version: 20131106 Zend Module Api No: 20131226 Zend Extension Api No: 220131226
  13. 13. Zephir – Installation (Ubuntu) $ git clone https://github.com/phalcon/zephir $ cd zephir $ ./install-json $ ./install -c $ cd .. $ zephir version 0.8.0a
  14. 14. Zephir – Important Commands $ zephir init [namespace] Initialises a Zephir extension $ zephir compile Compiles a Zephir extension $ zephir fullclean Cleans the object files generated in compilation $ zephir install Installs the extension (requires root access) $ zephir help Displays help
  15. 15. Zephir – First Steps $ zephir init helloworld $ ls helloworld helloworld/ ext/ helloworld/ ## Our zephir .zep files go here config.json ## Configuration file for our extension
  16. 16. Zephir – First Steps $ cd helloworld $ cat config.json … "namespace": "helloworld", "name": "helloworld", "description": "Hello World Extension", "author": "Mark Baker", "version": "0.0.1", "verbose": false, "requires": { "extensions": [] }
  17. 17. Zephir – First Steps Organise your code into files and namespaces Uses Case-Sensitive file/folder names Always use lower-case for file/folder names Every file must contain one (and only one) class Only OOP Code, no new PHP functions Class names can be mixed-case Classes must be namespaced Top-level Namespace should match the namespace defined in config.json but may be mixed-case
  18. 18. Zephir – First Steps $ cd helloworld $ cat greetings.zep namespace HelloWorld; class greetings { public function english() { // Variables must be defined before they can be used var greeting; // "let" is used to assign values to a variable let greeting = "Hello World"; echo greeting, PHP_EOL; } }
  19. 19. Zephir – First Steps $ cd .. $ zephir compile helloworld/ ext/ /helloworld ## zephir generates C source code here /modules ## zephir builds the PHP Extension here helloworld/ compile-errors.log compile.log config.json
  20. 20. Zephir – First Steps $ zephir install or $ sudo cp ext/modules/helloworld.so /usr/lib/php5/20131226/helloworld.so $ sudo nano /etc/php5/cli/php.ini extension=helloworld.so php -m
  21. 21. Zephir – First Steps $ php -i | grep -m 2 -A 4 helloworld helloworld Hello World Extension helloworld => enabled Author => Mark Baker Version => 0.0.1 Build Date => Sep 27 2015 08:57:19 Powered by Zephir => Version 0.8.0a
  22. 22. Zephir – First Steps $ cat helloworld.php <?php $instance = new HelloWorldgreetings(); $instance->english(); $ php helloworld.php Hello World
  23. 23. Zephir – Variables Variable names don’t begin with a $ Variables must be pre-defined/declared var stringVar = "hello", boolVar = true, intVar = 1.0; int answer = 42, question = 1; PHP scope rules apply Global variables don’t exist in Zephir (except that SuperGlobals can be accessed) let requestMethod = _SERVER["REQUEST_METHOD"];
  24. 24. Zephir – Variables Variable variables do not exist in Zephir But they can be “simulated” //Set variable $name in PHP let {"name"} = "hello"; //Set variable $price in PHP let name = "price"; let {name} = 10.2;
  25. 25. Zephir – Variable Types Dynamic Typed Variables Like PHP variables, and can change datatype between the different variable types supported by PHP Declared with the keyword “var” var name = "Mark"; Static Typed Variables A subset of C-Datatypes boolean, int, uint, char, uchar, long, ulong, string, array Can’t change datatype once declared Declared with the appropriate datatype name uint counter = 1;
  26. 26. Zephir – Strings String literals (dynamic var, static string) must be wrapped in double quotes var name = "Mark Baker"; Character literals (static char, static uchar) must be wrapped in single quotes char initial = 'M'; Strings in Zephir do not support variable interpolation/parsing; use concatenation instead: let forename = "Mark"; let surname = "Baker"; let fullName = forename . " " . surname;
  27. 27. Zephir – Arrays Array variables can be declared using the keywords “var” or “array”: var a = []; // dynamic variable array b = []; // static array variable As in PHP, keys can only be string or integer values Syntax is slightly different: let elements = [ "foo": "bar", // Use of : rather than => "bar": "foo" // No trailing , permitted ];
  28. 28. Zephir – Control Structures public function compare(a, b) { if a < b { return -1; } elseif a > b { return 1; } return 0; } Brackets around the evaluated condition are optional
  29. 29. Zephir – Control Structures let counter = 0; while counter < 10 { echo counter, PHP_EOL; let counter += 1; } Brackets around the evaluated condition are optional
  30. 30. Zephir – Control Structures let n = 10; loop { let n -= 2; if n == 0 { break; } echo n, PHP_EOL; }
  31. 31. Zephir – Control Structures let items = ["a": 1, "b": 2, "c": 3, "d": 4]; for key, value in items { echo key, " : ", value, PHP_EOL; } for key, value in reverse items { echo key, " : ", value, PHP_EOL; }
  32. 32. Zephir – Control Structures string fullName = "Mark Baker"; char character; for character in fullName { echo character , PHP_EOL; } for character in reverse fullName { echo character , PHP_EOL; }
  33. 33. Zephir – Control Structures let items = ["a": 1, "b": 2, "c": 3, "d": 4]; for key, _ in items { echo key, PHP_EOL; } The value element in the for loop doesn’t need to be declared
  34. 34. Zephir – Exceptions try { // exceptions can be thrown here if (firstCase) { throw new RuntimeException("This is an exception"); } else { throw "Untyped Exception"; } } catch RuntimeException|Exception, e { // handle exception echo e->getMessage(); }
  35. 35. Special Features of Zephir Type Hints Object/Interface Type Hints public function injectFilter(<AppFilterInterface> filter) { //... } Similar to the existing type hints in PHP, although notice the syntax differences
  36. 36. Special Features of Zephir Type Hints “Scalar” Type Hints public function filterText(string text, boolean escape=false) { //... } Allows “compatible” types, e.g. this->filterText(1234, 0); Will try to convert the data passed to the type-hinted datatype
  37. 37. Special Features of Zephir Type Hints Strict Scalar Hints public function filterText(string! text, boolean escape=false) { //... } this->filterText(1234, 0); Will throw an Exception
  38. 38. Special Features of Zephir Return Type Hints public function getClassFromFactory() -> <AppMyInterface> { //... } Similar to the return type hints introduced in PHP 7, although notice the syntax differences function isValidStatusCode(int $statusCode): bool { //... }
  39. 39. Special Features of Zephir Read-Only Arguments public function filterText(const string text, boolean escape=false) { //... } Used for compiler optimisations
  40. 40. Special Features of Zephir Named Arguments public function crop(width = 600, height = 400) { //... } this->crop(height: 200); this->crop(height: 300, width: 400); Adds a slight performance overhead
  41. 41. Zephir – Pitfalls Silent compilation failures $ zephir compile helloworld/ ext/ /helloworld ## zephir generates C source code here /modules ## zephir builds the PHP Extension here helloworld/ compile-errors.log ## Always check this file compile.log config.json
  42. 42. Zephir – Pitfalls Unsupported Features of PHP Array Dereferencing Callbacks can’t use “use”
  43. 43. Zephir – Pitfalls Bad assumptions from lazy PHP practises In PHP, a pass-by-reference variable in an expression like $validComplex = preg_match('/^...$/ui', $complexNumber, $complexParts); will automatically created $complexParts if it doesn't exist; but Zephir won't do this, so you need to explicitly create it in advance var complexParts; let validComplex = preg_match("/^....$/ui", complexNumber, complexParts);
  44. 44. Zephir – Pitfalls Overly-Complex or Ambiguous Syntax An expression like if (!is_object($complex) || !$complex instanceof Complex) { … } Might logically be translated to Zephir as if !is_object(complex) || !complex instanceof Complex { … } but Zephir has a different precedence to PHP for instanceof, so you need to do if !is_object(complex) || !(complex instanceof Complex) { … } otherwise it executes !complex and then tests the result of that (always a boolean) for instanceOf Complex cf. https://github.com/phalcon/zephir/issues/277
  45. 45. Zephir – Utilities and Helpers PHP to Zephir https://github.com/fezfez/php-to-zephir
  46. 46. Zephir – Utilities and Helpers $ zephir init helloworld $ cd helloworld $ /home/vagrant/vendor/bin/php-to-zephir phpToZephir:convertDir <path to PHP source code>
  47. 47. Zephir – Testing
  48. 48. Zephir – Testing $ cd helloworld helloworld/ ext/ /helloworld /modules run-tests.php ## PHP Test execution script helloworld/ compile-errors.log compile.log config.json
  49. 49. Zephir – Testing $ cd ext/modules $ php run-tests.php *.phpt <directory with test files> $ php run-tests.php --help Useful Option -c <filename> ## Custom php.ini file to be used
  50. 50. Zephir – Testing $ cat helloWorldTest001.phpt --TEST-- Test Hello World display using helloworld extension --FILE-- <?php $instance = new HelloWorldgreetings(); $instance->english(); --EXPECT-- Hello World
  51. 51. Zephir – Testing $ php run-tests.php *.phpt <directory with test files> … ===================================================================== Running selected tests. PASS Test Hello World display using helloworld extension [/srv/phpnw2015/helloworld/tests/helloWorldTest-001.phpt] ===================================================================== Number of tests : 1 1 Tests skipped : 0 ( 0.0%) -------- Tests warned : 0 ( 0.0%) ( 0.0%) Tests failed : 0 ( 0.0%) ( 0.0%) Expected fail : 0 ( 0.0%) ( 0.0%) Tests passed : 1 (100.0%) (100.0%) --------------------------------------------------------------------- Time taken : 0 seconds =====================================================================
  52. 52. Zephir – Testing https://qa.php.net/write-test.php https://qa.php.net/phpt_details.php
  53. 53. Useful Zephir Links Zephir Documentation http://docs.zephir-lang.com/ Zephir Blog http://blog.zephir-lang.com/

×