Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Zephir - A Wind of Change for writing PHP extensions

1,449 views

Published on

Slides from the tutorial given at the PHPNW2015 conference

Published in: Software
  • Be the first to comment

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/

×