鱼C论坛

 找回密码
 立即注册
查看: 2235|回复: 0

Php学习之命名空间、性状和生成器详解

[复制链接]
发表于 2017-8-8 15:16:08 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本文和大家分享的主要是php的命名空间、性状和生成器相关内容,一起来看看吧,希望对大家学习php有所帮助。
+ m$ h5 B! K  T- y  1.命名空间
% |- Y1 }: ]; r# V4 v  命名空间是什么?
3 k9 t7 O% V" A  1).命名空间在PHP 5.3中被引入,类似于文件夹的功能。例如Symfony框架中的Request和Response,位于Symfony的命名空间下。, B6 C* Z  L" X3 N6 K$ D( }" U0 F
  2).命名空间始终应该在<?php标签的下面一行。6 Z- D: ~' m8 q0 \3 p0 b  t
  3).PHP文件的命名空间和操作系统的物理文件系统不同,这是一个虚拟的概念,没有必要和文件系统的目录结构完全对应。虽然如此,绝大多数PHP组件为了兼容广泛使用的PSR4自动加载标准,会把子命名空间放到文件系统的子目录中去。' I/ y& m3 z2 v* q( I
  4).命名空间只是PHP语言的一种记号,PHP解释器会将这种记号作为前缀添加到类、接口、函数和常量的名称前面。5 ]' V  n# A( g8 {
  为什么需要命名空间?
; b; U6 J5 x7 f9 `1 C' _  1).命名空间使得程序可以像沙盒一样运行,可以和其他开发者编写的代码一起使用。确保了自己的代码和项目可以和项目的第三方依赖一起使用。
5 i7 g2 P$ n9 u. ?  声明命名空间3 d5 _( x5 x( `1 [
  1).顶层命名空间经常用于设定顶层厂商名。
( D( i3 x8 P; Q9 y- v- g  2).厂商的命名空间必须具有全局唯一性,子命名空间就没有那么重要,但有助于组织项目的代码。
1 N; E$ @; s* {* f  导入和别名# ]7 @6 F2 |$ o% f. C; l
  1).从PHP5.3开始可以导入PHP类、接口和其他命名空间,并为其创建别名。从PHP5.6开始可以导入PHP函数和常量,并为其创建别名。+ x. _# J& p* a- R3 w6 R
  2).使用use关键字导入代码时无须在开头加上\符号,因为PHP假定导入的是完全限定命名空间。use关键字必须出现在全局作用域中即不能出现在类或者函数中,因为这个关键字是在编译的时候使用的,不过,use关键字可以在命名空间声明语句后使用,导入其他命名空间的代码。* U' w9 j' e! B9 B
  从PHP5.6开始我们可以导入函数和常量。/ x6 D1 s7 M; H. o# K8 d
  <?phpuse func Namespace\functionName;
! D2 N5 d( r8 l" ]- ^  functionName();
, |8 m1 z  r5 C& n' ~7 t# Y  也可以导入常量,
9 Y; a- [5 w7 w* }: X! y3 \: S  use constant Namespace\CONS_NAME;/ d9 e( c  |0 q! c6 z
  echo CONS_NAME;3 R* j: C) d- y7 E1 ~
  函数和常量的别名与类名的创建方式一样。
2 ]/ \2 ]* S6 \4 Z/ a) c; h4 W+ I  最佳实践/ }4 L, R9 p1 K4 K
  1).PHP允许在一个PHP文件中定义多个命名空间。但是这么做容易让人困惑,违背了一个文件一个类的良好实践。/ n8 `- A" K+ ~, p- M
  2).在一个命名空间中引用全局的命名空间的代码时,需要加上\前缀,告诉PHP需要在全局中查找该类,例如PHP原生的异常类。
  D9 S( E$ {0 p  自动加载& x5 A' S' W! o; g4 _' Z
  1).命名空间为PHP-FIG制定的PSR4自动加载器奠定了坚实的基础。
( A- e4 @% Z3 m2 S  ]% B* Z8 N  2.使用接口
  e; y! X/ B; s2 u8 Q. b  1).就像我可以选择开不一样的车。因为他们都有方向盘、油门和刹车,并且燃料都是汽油。
# D4 \0 D% H( b/ P  3.性状5 t% T& R" \" {4 Z7 l: {1 l. s  X
  1).形状是类的部分实现(常量、属性和方法),可以混入一个或者多个现有的PHP类中,性状有两个作用,表明类可以做什么(类似接口),提供模块化实践(类似类)。
! q5 P; z% q9 ~  ~  2).性状使得两个无关的类可以使用相同属性和方法。
0 n2 d# V( ^# z6 \7 I8 ^9 ^  3).PHP解释器会把性状复制粘贴到类的定义体中。
7 o% @) b: l9 K3 s& D# k  4.创建生成器$ F$ G: [- Z: k: q
  1)在普通函数中一次或者多次使用yield关键字,不返回值,只生成值,这个函数就是一个生成器。例如:; f3 ~, ]/ u8 c# L. ?* l+ A
  <?phpfunction myGenerator() {
& ^* K# o; e* @( @  yield 'value1';
2 a( e% |" g1 C7 x0 q  yield 'value2';- Q* T9 D% T- Z! s6 y  u
  }) }& M7 R/ y" q& y) G
  调用生成器函数的时候,PHP会返回一个属于Generator类的对象,这个对象可以使用foreach()函数迭代,每次迭代,PHP会要求这个对象的实例计算并提供下一个要迭代的值,生成器的优雅之处就是在每产出一个值之后,生成器内部状态会一直停顿和恢复之间切换,直到抵达定义体的末尾或者遇到空的return;语句为止,例如:
( Y8 S) Z" [4 `) [- V  <?phpforeach (myGenerator() as $yieldedValue) {6 s' E$ M1 ~! e" l/ @- u
  echo $yieldedValue, PHP_EOL;
/ N' B; _8 M9 P  j& p! |" D  }0 N" W7 l  |( Q* a
  以上例子会输出1 c+ \5 C. @1 |2 F9 t
  value1
; [5 @4 u% y4 ?' }  value2
4 h! B" k: {+ o! m  2).生成器是如何节约内存的?生成一个范围内的数值(错误方式)
5 F! [* I6 k) \+ P1 \  function makeRange($length) {
) I+ n* ?* W8 Y" D  $dataset = [];. M+ I: _$ `6 E4 Z  _
  for ($i=0; $i < $length; $i++) {# c( H3 y0 p9 J- W" W6 D% ?: y
  $dataset[] = $i;
* x3 C& _$ x9 N) j; V" l2 I  }! D2 u- N$ G) r4 j5 E
  return $dataset;
+ B3 L* V% n. f3 A0 Z- t  }* I6 c; o" {/ R0 R9 ^, d- D
  $customRange = makeRange(1000000);foreach ($customeRange as $i) {" D! ~7 y0 H1 ?. d8 U
  echo $i, PHP_EOL;. E; O  Y- N# N. N! G& c' x
  }
- K8 `4 S4 h- b" M  预先创建了一个包含很大整数组成的数组,再看使用生成器的例子。
, ^6 |  @& i1 Y( b( A  R  function makeRange($length) {! J7 H; U7 W1 E# b7 |( S
  for ($i = 0; $i < $length; $i++) {
$ W7 o- g7 L. O" R* Z4 G! T) T* t  yield $i;. W+ v. Z- I: E6 y2 ?0 h; _0 @
  }% w- t/ J& G3 w
  }
$ I7 F# g1 a5 r( ^  foreach(makeRange(1000000) as $i) {0 K% J! `; y$ Y# l" e. K7 R- n5 E9 v
  echo $i, PHP_EOL;
6 {$ z5 W0 G; t6 P  d! c, z  }- ?! ~, F7 ^' K" H; c! N
  在实际的例如迭代一个4GB大小的文件中功能中,迭代器大展身手。, Z2 m5 ]$ ~5 ]1 [' M
  function getRows($file) {
% q1 ?$ |! t1 k3 W4 }  $handle = fopen($file, 'rb');
; X; v, I1 N& o) R  if ($handle === false) {+ m/ P: i, H' Y7 n# r# M9 s
  throw new Exception();
' }8 c6 q6 U5 Z0 Y* z+ b8 H  }$ V7 w6 b- g& B" B( D3 `. q! E# _: p
  //feof()函数检测是否到达文件末尾3 w1 {5 G* I2 z) z! e$ @# r& x
  while (feof($handle) === false) {" O' L8 l7 [- U1 e9 @
  //fgetcsv()一次读取csv文件的一行
1 B2 O9 b/ O# j8 d% `  yield fgetcsv($handle);
9 Z. M' ]9 l( F( V& G; [  }! Y6 E" N- b# J4 ?6 q$ |5 L* M
  fclose($handle)
& ~) b4 o; W- ~$ F0 z$ y  }
7 C! \+ W3 u  H4 N/ ~+ J  foreach (getRows('data.csv') as $row) {9 ?& D4 X. b: C+ L4 n
  print_r($row);2 Z4 e2 E- Q" C3 a4 u7 _; I% y
  }
1 ?# d- X' d! `8 z4 Z8 [( W, v  3).生成器没有为PHP添加新功能,需要实现在数据集中执行快进、快退和查找,最好自己编写类实现Iterator接口,或者使用PHP标准库中的某个原生迭代器。
5 ^- g1 e5 K6 h5 |4 c5 z: K# u$ Q2 [) F: i

( h$ s) ~4 ]% s8 {, \+ i来源:稀土掘金
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-1-19 21:55

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表