资讯专栏INFORMATION COLUMN

Zephir入门 —— 语法篇

shiina / 3139人阅读

摘要:变量对象属性数组静态变量不支持全局变量,也不允许访问用户域的全局变量,但是可以访问的超级全局变量变量类型支持动态和静态类型。虽然失去了动态型变量的灵活性,但是在编译时静态变量能进行更多的优化。

概述

Zephir的语法跟PHP很相似,所以这里不会把官网的文档照搬过来翻译一遍,而是会把一些Zephir相较于PHP比较特别的语法挑出来讲一下。如果想要要完整学习Zephir的语法,没有比官网的文档更好的地方了。

基本语法

Zephir的文件后缀名为zep,每个文件都必须包含且只能包含一个类。每个类必须有一个命名空间,且目录结构必须跟类名和命名空间匹配。例如下面的目录结构:

</>复制代码

  1. mylibrary/
  2. router/
  3. exception.zep # MyLibraryRouterException
  4. router.zep # MyLibraryRouter

那么exception.zep的命名空间和类名如下:

</>复制代码

  1. phpnamespace MyLibraryRouter;
  2. class Exception extends Exception
  3. {
  4. }

Zephir里的变量名不需要像PHP那样带$符号,且有两种声明的方式:

</>复制代码

  1. // 可以使用var来定义变量,或者指定具体的变量类型
  2. var a;
  3. int b;
  4. bool c = true;
  5. // 可以在一行里声明多个变量
  6. var a = "hello", b = 0, c;

要修改变量,属性或者数组的值,需要使用let关键字。

</>复制代码

  1. let name = "Tony"; // 变量
  2. let this->name = "Tony"; // 对象属性
  3. let data["name"] = "Tony"; // 数组
  4. let self::_name = "Tony"; // 静态变量

Zephir不支持全局变量,也不允许访问用户域的全局变量,但是可以访问PHP的超级全局变量:

</>复制代码

  1. var price = _POST["price"];
  2. var requestMethod = _SERVER["REQUEST_METHOD"];
变量类型

Zehpir支持动态和静态类型。

动态类型

动态类型变量跟PHP一样,可以在赋值后修改为不同类型的值。动态类型变量必须用var来声明。

</>复制代码

  1. var a, b, c;
  2. // 初始化变量
  3. let a = "hello", b = false;
  4. // 改变它们的值
  5. let a = 10, b = "140";
  6. // 对它们进行操作
  7. let c = a + b;

Zephir不会检查整型的溢出,如果要操作比较大的数字,可以使用浮点型或者静态型变量"unsigned long":

</>复制代码

  1. unsigned long my_number = 2147483648;

Zephir不支持在字符串里使用变量的方式,你可以使用拼接方式:

</>复制代码

  1. var name = "peter";
  2. echo "hello: " . name;

数组的定义要用中括号[],且字符串型的键需要使用双引号:

</>复制代码

  1. let myArray = [1, 2, 3];
  2. let myHash = [0: "first", 1: true, 2: null];
  3. let myHash = ["first": 7.0, "second": "some string", "third": false];
静态变量

静态变量一旦声明类型后就不能再改变。虽然失去了动态型变量的灵活性,但是在编译时静态变量能进行更多的优化。

Zephir支持以下的静态类型:

boolean: A boolean expresses a truth value. It can be either ‘true’ or ‘false’.

integer: Signed integers. At least 16 bits in size.

unsigned integer: Unsigned integers. At least 16 bits in size.

char: Smallest addressable unit of the machine that can contain basic character set.

unsigned char: Same size as char, but guaranteed to be unsigned.

long: Long signed integer type. At least 32 bits in size.

unsigned long: Same as long, but unsigned.

float/double: Double precision floating-point type. The size is platform-dependent.

string: A string is series of characters, where a character is the same as a byte.

unsigned long: Same as long, but unsigned.

array: An structure that can be used as hash, map, dictionary, collection, stack, etc.

布尔型,非布尔值会自动转化为true或者false:

</>复制代码

  1. boolean a;
  2. let a = true,
  3. a = 100, // 自动转换为true
  4. a = null, // 自动转换为false
  5. a = "hello"; // 抛出编译器异常

整型:

</>复制代码

  1. int a;
  2. let a = 50,
  3. a = -70,
  4. a = 100.25, // 自动转换为100
  5. a = null, // 自动转换为0
  6. a = false, // 自动转换为0
  7. a = "hello"; // 抛出编译器异常

无符号整型,带符号整型的值会自动转换为无符号。另外要注意的是,无符号整型的最大值要比普通整型大一倍,所以在把无符号整型的值赋予普通整型时要注意下:

</>复制代码

  1. uint a, int b;
  2. let a = 50,
  3. a = -70, // 自动转换为70
  4. let a = 2147483648,
  5. b = a; // 可能会丢失数据

长整型/无符号长整型变量的值范围是普通整型/无符号整型的两倍,除此以外跟普通整型/无符号整型一致。

</>复制代码

  1. ulong a, long b;
  2. let a = 4294967296,
  3. b = a; // 可能会丢失数据

字符型:

</>复制代码

  1. har ch, string name = "peter";
  2. let ch = name[2]; // 存储"t"
  3. let ch = "Z"; // 需要用单引号

字符串:

</>复制代码

  1. string a;
  2. let a = "",
  3. a = "hello", // 使用用双引号
  4. a = "A", // 自动转换为"A"
  5. a = null; // 自动转换为""

</>复制代码

  1. 更详细的类型语法请看这里:http://zephir-lang.com/types.html

操作符

Zephir支持的运算符基本跟PHP一致:

</>复制代码

  1. // 算术运算符
  2. // Zephir支持PHP中除了`$a ** $b`(PHP 5.6才开始支持)这种方式外的算术运算符。
  3. let c = a + b;
  4. // 比较运算符
  5. // Zephir支持的比较运算符跟PHP一致(除了PHP 7增加支持的两个比较运算符外)。
  6. if a == b {
  7. return 0;
  8. }
  9. // 逻辑运算符
  10. // Zephir支持`&&``||``!`这三个逻辑运算符,但不支持PHP里`And``Or``Xor`这三个逻辑运算符。
  11. if a && b || !c {
  12. return -1;
  13. }
  14. // 位运算符
  15. // 跟PHP一致
  16. if a & SOME_FLAG {
  17. echo "has some flag";
  18. }
  19. // 三元运算符
  20. // 跟PHP一致
  21. let b = a == 1 ? "x" : "y";

然后,Zephir还支持emptyisset等特殊的运算符:

</>复制代码

  1. // empty
  2. // 如果表达式的值为null、空字符串或者空数组,则为empty
  3. let someVar = "";
  4. if empty someVar {
  5. echo "is empty!";
  6. }
  7. // isset
  8. // 用于检查数组的索引或者对象的属性是否已定义
  9. // 功能更类似于PHP中的array_key_exists方法
  10. let someArray = ["a": 1, "b": 2, "c": 3];
  11. if isset someArray["b"] {
  12. echo "yes, it has an index "b"
  13. ";
  14. }
  15. // fetch
  16. // 用于简化在PHP中以下的操作:
  17. if (isset($myArray[$key])) {
  18. $value = $myArray[$key];
  19. echo $value;
  20. }
  21. // 使用fetch可以用以下代码实现,只有在key存在的情况下,fetch才返回true
  22. if fetch value, myArray[key] {
  23. echo value;
  24. }
  25. // typeof
  26. // 用于检查变量的类型
  27. if (typeof str == "string") {
  28. echo str;
  29. }

</>复制代码

  1. 更详细的操作符语法请看这里:http://zephir-lang.com/operators.html

数组

数组可以使用关键字vararray进行声明:

</>复制代码

  1. var a = []; // 类型可以改变
  2. array b = []; // 运行过程中,类型不可以改变

数组使用中括号进行创建,操作方式跟PHP一样:

</>复制代码

  1. let elements = [];
  2. let elements = [1, 3, 4];
  3. let elements = ["first", 2, true];
  4. let elements[0] = "bar";
  5. let elements = ["foo": "bar", "bar": "foo"];
  6. let foo = elements["foo"];

</>复制代码

  1. 更详细的数组操作语法请看这里:http://zephir-lang.com/arrays.html

类和对象

前面说过,每个zephir文件都必须包含一个类,而且只能包含一个类。

Zehpir的类支持finalabstract两个修饰符,修饰符的作用跟PHP中的一致,例如:

</>复制代码

  1. namespace Test;
  2. /**
  3. * 这个类不能被扩展
  4. */
  5. final class MyClass
  6. {
  7. }
方法

类的成员方法支持的可见性修饰符也跟PHP一致,支持publicprotectedprivate,但Zephir强制方法必须显式的带上修饰符。

同时方法还支持finaldeprecated两个修饰符:

</>复制代码

  1. // 这个方法不能被重写
  2. public final function foo()
  3. {
  4. }
  5. // 调用此方法会抛出E_DEPRECATED 异常
  6. public deprecated function foo()
  7. {
  8. }

方法的参数也支持PHP中可选参数的方式,同时也支持静态类型:

</>复制代码

  1. public function doSum(a, b = 3)
  2. {
  3. return a + b;
  4. }
  5. public function doSum2(int a = 4, int b = 2)
  6. {
  7. return a + b;
  8. }

使用静态类型参数时,如果传入的参数类型不一致,Zephir会试图对传入值进行类型的转换。如果基于某些考虑不想Zephir自动去做这个事情,我们可以通过添加一个!号禁止这个行为:

</>复制代码

  1. public function filterText(string! text, boolean escape=false)
  2. {
  3. //...
  4. }

另外我们还能通过const关键字设置参数为只读:

</>复制代码

  1. // a为只读
  2. public function getSomeData(const string a)
  3. {
  4. // 这里会抛出编译错误
  5. let a = "hello";
  6. }

Zephir还提供了方法返回类型的提示功能,使得编译器可以知道方法返回的类型:

</>复制代码

  1. namespace App;
  2. class MyClass
  3. {
  4. public function getSomeData() -> string
  5. {
  6. // 这里会抛出编译异常。因为返回值是布尔型,跟期待的返回类型不一致
  7. return false;
  8. }
  9. public function getSomeOther() ->
  10. {
  11. // 这里会抛出编译异常,如果返回的对象不是AppMyInterface接口的一个实现
  12. return new AppMyObject;
  13. }
  14. public function process()
  15. {
  16. var myObject;
  17. // 类型提示会告诉编译器myObject是AppMyInterface的一个实例
  18. let myObject = this->getSomeOther();
  19. // 编译器会检查AppMyInterface是否实现了一个叫someMethod的方法
  20. echo myObject->someMethod();
  21. }
  22. // 一个方法可以有多个的返回类型,使用|进行分隔
  23. public function getSomeData2(a) -> string | bool
  24. {
  25. if a == false {
  26. return false;
  27. }
  28. return "error";
  29. }
  30. // 如果返回类型为void,则表示此方法不允许返回任何数据
  31. public function setConnection(connection) -> void
  32. {
  33. let this->_connection = connection;
  34. }
  35. }
属性

类的属性同样支持publicprotectedprivate三个修饰符,而且必须显式指定:

</>复制代码

  1. namespace Test;
  2. class MyClass
  3. {
  4. public myProperty1;
  5. protected myProperty2;
  6. private myProperty3;
  7. // 属性可以赋予默认值,但是这个值必须在编译的时候就能知道而不需要依赖于运行环境
  8. protected myProperty4 = 5;
  9. protected myProperty5 = "my value";
  10. public function setMyProperty1(var myProperty)
  11. {
  12. // 修改属性的值
  13. let this->myProperty1 = myProperty;
  14. }
  15. public function getMyProperty1()
  16. {
  17. // 读取属性的值
  18. return this->myProperty1;
  19. }
  20. }

Zephir还提供了一个快捷的方式去实现Getter和Setter,例如下面的代码:

</>复制代码

  1. namespace App;
  2. class MyClass
  3. {
  4. protected myProperty {
  5. set, get, toString
  6. };
  7. protected someProperty = 10 {
  8. set, get
  9. };
  10. }

相当于:

</>复制代码

  1. namespace Test;
  2. class MyClass
  3. {
  4. protected myProperty;
  5. protected someProperty = 10;
  6. public function setMyProperty(myProperty)
  7. {
  8. this->myProperty = myProperty;
  9. }
  10. public function getMyProperty()
  11. {
  12. return this->myProperty;
  13. }
  14. public function setSomeProperty(someProperty)
  15. {
  16. this->someProperty = someProperty;
  17. }
  18. public function getSomeProperty()
  19. {
  20. return this->someProperty;
  21. }
  22. public function __toString()
  23. {
  24. return this->myProperty;
  25. }
  26. }

另外常量的使用也是支持的:

</>复制代码

  1. namespace Test;
  2. class MyClass
  3. {
  4. const MYCONSTANT1 = false;
  5. const MYCONSTANT2 = 1.0;
  6. public function someMethod()
  7. {
  8. return MyClass::MYCONSTANT1;
  9. }
  10. }

</>复制代码

  1. 更详细的类和对象的使用方式请看这里:http://zephir-lang.com/oop.html

内置方法

Zephir自身也内置了不少的方法,这些方法基本都是PHP中某些方法的OO实现。例如:

</>复制代码

  1. public function foo(string! s)
  2. {
  3. return strlen(s);
  4. }
  5. // 使用内置方法
  6. public function foo(string! s)
  7. {
  8. return s->length();
  9. }

</>复制代码

  1. 更详细的内置方法使用方式请看这里:http://zephir-lang.com/builtin-methods.html

流程控制 条件语句

条件判断语句中,ifswitch语句跟PHP类似,但需要注意的是,条件表达式的括号可以省略:

</>复制代码

  1. if a > 100 {
  2. echo "to big";
  3. } elseif a < 0 {
  4. echo "to small";
  5. } else {
  6. echo "ok";
  7. }
  8. switch count(items) {
  9. }
循环语句

循环语句中,用whileloopfor三种语句。

while语句跟PHP差不多,loop为Zephir增加的语句,用于创建一个无限的循环:

</>复制代码

  1. let n = 40;
  2. loop {
  3. let n -= 2;
  4. if n % 5 == 0 { break; }
  5. echo x, "
  6. ";
  7. }

for的用法跟PHP有很大不同,例如:

</>复制代码

  1. // 循环数组
  2. for item in ["a", "b", "c", "d"] {
  3. echo item, "
  4. ";
  5. }
  6. let items = ["a": 1, "b": 2, "c": 3, "d": 4];
  7. for key, value in items {
  8. echo key, " ", value, "
  9. ";
  10. }
  11. // 遍历字符串
  12. string language = "zephir"; char ch;
  13. for ch in language {
  14. echo "[", ch ,"]";
  15. }

三种循环语句中均支持break语句和continue语句。

文件包含

Zephir中也提供了类似PHP中require语句的语句:

</>复制代码

  1. if file_exists(path) {
  2. require path;
  3. }

注意这个语句只能用于包含PHP文件,而不能包含zephir文件。

</>复制代码

  1. 更详细的流程控制语法请看这里:http://zephir-lang.com/control.html

异常处理

异常处理跟PHP也类似:

</>复制代码

  1. try {
  2. // 可以在这里抛出异常
  3. throw new Exception("This is an exception");
  4. } catch Exception, e {
  5. // 异常处理
  6. echo e->getMessage();
  7. }

如果不需要的话,保存异常信息的变量e可以省略:

</>复制代码

  1. try {
  2. throw new Exception("This is an exception");
  3. } catch Exception {
  4. echo e->getMessage();
  5. }

同时捕捉不同类型的异常:

</>复制代码

  1. try {
  2. throw new Exception("This is an exception");
  3. } catch RuntimeException|Exception, e {
  4. echo e->getMessage();
  5. }

</>复制代码

  1. 更详细的异常处理的使用方式请看这里:http://zephir-lang.com/exceptions.html

调用PHP函数

可以直接调用PHP中内置的函数,例如调用base64_encode函数:

</>复制代码

  1. namespace MyLibrary;
  2. class Encoder
  3. {
  4. public function encode(var text)
  5. {
  6. if strlen(text) != 0 {
  7. return base64_encode(text);
  8. }
  9. return false;
  10. }
  11. }

用户自己定义的函数也可以调用:

</>复制代码

  1. namespace MyLibrary;
  2. class Encoder
  3. {
  4. public function encode(var text)
  5. {
  6. if strlen(text) != 0 {
  7. if function_exists("my_custom_encoder") {
  8. return my_custom_encoder(text);
  9. } else {
  10. return base64_encode(text);
  11. }
  12. }
  13. return false;
  14. }
  15. }

由于PHP的函数只接收和返回动态变量,所以如果你传入静态变量的话,Zephir会隐式的创建一个临时变量用于函数的调用。而返回的结果如果要赋值给静态变量的话,需要作适当的类型转换:

</>复制代码

  1. namespace MyLibrary;
  2. class Encoder
  3. {
  4. public function encode(string text)
  5. {
  6. string encoded = "";
  7. if strlen(text) != 0 {
  8. let encoded = (string) base64_encode(text);
  9. return "(" . encoded . ")";
  10. }
  11. return false;
  12. }
  13. }

最后,如果我们需要动态的对函数进行调用,可以使用以下的方式:

</>复制代码

  1. namespace MyLibrary;
  2. class Encoder
  3. {
  4. public function encode(var callback, string text)
  5. {
  6. return {callback}(text);
  7. }
  8. }

</>复制代码

  1. 更详细的函数的调用方法请看这里:http://zephir-lang.com/functions.html

闭包

Zephir里也支持闭包和匿名函数,你可以把它返回给PHP:

</>复制代码

  1. namespace MyLibrary;
  2. class Functional
  3. {
  4. public function map(array! data)
  5. {
  6. return function(number) {
  7. return number * number;
  8. };
  9. }
  10. }

也可以直接调用:

</>复制代码

  1. namespace MyLibrary;
  2. class Functional
  3. {
  4. public function map(array! data)
  5. {
  6. return data->map(function(number) {
  7. return number * number;
  8. });
  9. }
  10. }

另外Zephir还提供了一个短语法用来定义闭包:

</>复制代码

  1. namespace MyLibrary;
  2. class Functional
  3. {
  4. public function map(array! data)
  5. {
  6. return number => number * number;
  7. }
  8. }
参考

http://zephir-lang.com/index.html

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21045.html

相关文章

  • Zephir入门 —— Hello world

    摘要:概述是一个开源的用于简化扩展的创建和维护的语言。它使得不擅长的开发人员也能写出扩展。是缩写,读音为。然后我们在里调用方法正常的话会输出。至此我们也完成了我们的第一个扩展。 概述 Zephir是一个开源的用于简化PHP扩展的创建和维护的语言。它使得不擅长C/C++的PHP开发人员也能写出PHP扩展。Zephir是Zend Engine/PHP/Intermediate缩写,读音为zep...

    Vicky 评论0 收藏0
  • 【PHP 扩展开发】Zephir 基础

    摘要:变量作为函数返回值时,必须声明为动态类型。动态变量与中的变量基本完全相同支持在使用时改变类型。比较运算符在运算时考虑变量类型,如果是动态变量与一致。与不一致,语句可以没有,表示忽略所有异常。 上一篇 《Zephir 简介》 简单介绍了环境搭建,编写了一个的简单示例。这一篇继续介绍 Zephir 基础。 基本语法Zephir 中,每个文件都必须有且只有一个类,每个类都必须有一个命名空间,...

    wawor4827 评论0 收藏0
  • PHP扩展开发教程1 - 相关开发技术对比及介绍

    摘要:四使用语言开发是我重点推荐的扩展开发框架,简明易懂,功能强大,开发效率高,代码易维护,执行速度快。优点三支持,的扩展开发有两套扩展开发框架,分别支持,,虽然框架代码有两个,但是接口却是一样的。 PHP扩展是高级PHP程序员必须了解的技能之一,对于一个初入门的PHP扩展开发者,怎么才能开发一个成熟的扩展,进入PHP开发的高级领域呢?本系列开发教程将手把手带您从入门进入高级阶段。本教程系列...

    alaege 评论0 收藏0
  • 【PHP 扩展开发】Zephir 简介

    摘要:什么是是一种中间语言,以接近的语法来编写代码,然后转换编译成扩展,旨在简化扩展的创建和可维护性。如果成功,会自动生成文件到目录你需要编辑填加扩展测试一下就这样,你也会扩展开发了附附编译扩展的方法 什么是 Zephir Zephir 是一种中间语言,以接近 PHP 的语法来编写代码,然后转换编译成 PHP 扩展,旨在简化 PHP 扩展的创建和可维护性。利用编译来提高性能和资源消耗,又不需...

    arashicage 评论0 收藏0
  • Zephir--最简单的php扩展开发工具

    摘要:更多关于的技术文章的扩展是用语言编写,是语言引擎,内核。见提供了一种类似的高级语言语法的方式,来自动生成扩展的语言代码,使编写扩展变得非常的简单。直接修改该文件的代码,使用原扩展的编辑方法也是可以滴。 更多关于PHP的技术文章http://www.codefrom.com/ php的扩展是用c语言编写,Zend是语言引擎,PHP内核。在实际编写php扩展的时候,需要使用大量的...

    dinfer 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<