鱼C论坛

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

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

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

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

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

x
本文和大家分享的主要是php的命名空间、性状和生成器相关内容,一起来看看吧,希望对大家学习php有所帮助。( W5 {) d9 `2 w) C& _1 ~
  1.命名空间
. T  }* D4 j/ a3 \# m  命名空间是什么?
5 U- j  a  f9 F1 g  1).命名空间在PHP 5.3中被引入,类似于文件夹的功能。例如Symfony框架中的Request和Response,位于Symfony的命名空间下。. t4 z* I) t! \+ f5 D
  2).命名空间始终应该在<?php标签的下面一行。
! }" n) N- i8 S1 o7 E8 _  3).PHP文件的命名空间和操作系统的物理文件系统不同,这是一个虚拟的概念,没有必要和文件系统的目录结构完全对应。虽然如此,绝大多数PHP组件为了兼容广泛使用的PSR4自动加载标准,会把子命名空间放到文件系统的子目录中去。* H  {# b# d9 j1 @" w0 |
  4).命名空间只是PHP语言的一种记号,PHP解释器会将这种记号作为前缀添加到类、接口、函数和常量的名称前面。! Z' f2 {# g/ @
  为什么需要命名空间?* @: J# C1 G/ t, N
  1).命名空间使得程序可以像沙盒一样运行,可以和其他开发者编写的代码一起使用。确保了自己的代码和项目可以和项目的第三方依赖一起使用。$ C4 f6 d9 M& O' w. @! n  r3 r
  声明命名空间
. E/ u- g3 h5 `, z; t  m: ~" |7 T  1).顶层命名空间经常用于设定顶层厂商名。
3 K, v/ i$ [- |  2).厂商的命名空间必须具有全局唯一性,子命名空间就没有那么重要,但有助于组织项目的代码。
4 p+ B5 t" _( d& U. x' K* D+ L& ~  导入和别名
1 c$ n+ G; S1 |( N9 P; r  z1 R  1).从PHP5.3开始可以导入PHP类、接口和其他命名空间,并为其创建别名。从PHP5.6开始可以导入PHP函数和常量,并为其创建别名。
: G" X4 M! c4 l' K4 I8 T" d  2).使用use关键字导入代码时无须在开头加上\符号,因为PHP假定导入的是完全限定命名空间。use关键字必须出现在全局作用域中即不能出现在类或者函数中,因为这个关键字是在编译的时候使用的,不过,use关键字可以在命名空间声明语句后使用,导入其他命名空间的代码。' H# J& [" {9 D4 b0 l5 c
  从PHP5.6开始我们可以导入函数和常量。
+ z8 I; n! m% A; i  <?phpuse func Namespace\functionName;' h; P$ W2 `9 @; Y
  functionName();0 Z& t; m/ Q' H% [4 r
  也可以导入常量,: @" V" A# Y, M$ o+ \  V( r
  use constant Namespace\CONS_NAME;
2 t# N9 ~' T4 K8 J  echo CONS_NAME;/ X& ]  ^. V% X/ ^5 R9 r
  函数和常量的别名与类名的创建方式一样。1 i3 I% s. e. j4 A( T
  最佳实践$ p( T9 `! h; ~
  1).PHP允许在一个PHP文件中定义多个命名空间。但是这么做容易让人困惑,违背了一个文件一个类的良好实践。- {0 K/ s, W5 y: s( k2 w: H! Q. B
  2).在一个命名空间中引用全局的命名空间的代码时,需要加上\前缀,告诉PHP需要在全局中查找该类,例如PHP原生的异常类。& Z8 m3 L, [' j% ]: Y1 v3 b' l
  自动加载; V2 U& i* v+ U3 g2 x3 j% H3 L
  1).命名空间为PHP-FIG制定的PSR4自动加载器奠定了坚实的基础。% T9 y4 ~" E. L# g! Z
  2.使用接口0 r7 x1 k  m4 i8 p
  1).就像我可以选择开不一样的车。因为他们都有方向盘、油门和刹车,并且燃料都是汽油。
7 t: J3 I/ @2 J0 L9 t  3.性状
* K. k1 Q; Z0 H$ W* R  1).形状是类的部分实现(常量、属性和方法),可以混入一个或者多个现有的PHP类中,性状有两个作用,表明类可以做什么(类似接口),提供模块化实践(类似类)。
2 z: M, f. Y; Y- |% ~  2).性状使得两个无关的类可以使用相同属性和方法。
' j; T% s7 U/ S+ F1 O  3).PHP解释器会把性状复制粘贴到类的定义体中。
) H, D- A/ n  `2 x9 h1 s  4.创建生成器0 m: c4 a* N8 R3 Y% C& v. \
  1)在普通函数中一次或者多次使用yield关键字,不返回值,只生成值,这个函数就是一个生成器。例如:3 M; ?, j4 k' p' I
  <?phpfunction myGenerator() {
8 g0 t1 f' ~6 @1 e% v, {  yield 'value1';5 l( {* z+ D2 L2 f
  yield 'value2';
( g+ M5 U; l1 K: h  H; M  }
; `7 U$ o7 q; O! M9 V7 M4 m- w  调用生成器函数的时候,PHP会返回一个属于Generator类的对象,这个对象可以使用foreach()函数迭代,每次迭代,PHP会要求这个对象的实例计算并提供下一个要迭代的值,生成器的优雅之处就是在每产出一个值之后,生成器内部状态会一直停顿和恢复之间切换,直到抵达定义体的末尾或者遇到空的return;语句为止,例如:
! k: R1 T# G, c# n9 r- B) O  <?phpforeach (myGenerator() as $yieldedValue) {
4 `9 j- `. |& ]; M1 T  echo $yieldedValue, PHP_EOL;
" X4 T5 ^/ e$ y7 }* i  }
2 ^& a7 o/ g) ~( Y* j( P0 s  以上例子会输出
) Y8 J8 _9 D- Z- A! I  value1/ m5 X& N' |& r$ X3 O
  value2! W3 R0 n8 v) G- j9 B. h
  2).生成器是如何节约内存的?生成一个范围内的数值(错误方式)
! ?6 S; C8 r' k- P  function makeRange($length) {
0 d. |( c! c$ Y% J  $dataset = [];& z" ?1 ?- R. }: d
  for ($i=0; $i < $length; $i++) {
3 u" m0 G, g, n4 @& n+ l7 V& Z  $dataset[] = $i;1 S4 u/ f! ~+ n9 M
  }! k5 Y; X8 z* p  X8 y
  return $dataset;; _1 m4 q& A9 a: u; z2 @
  }
9 ?$ Q/ ^9 A8 R. ~% D1 W  $customRange = makeRange(1000000);foreach ($customeRange as $i) {
- {$ h  H  E' \& ?  echo $i, PHP_EOL;
. x# O5 z0 {' [! i7 J- V  @  }- T! C: i6 Y3 D
  预先创建了一个包含很大整数组成的数组,再看使用生成器的例子。2 q" s7 P+ Q' B& Y+ u
  function makeRange($length) {# g. o8 V2 q" r3 y% \. H  N5 q
  for ($i = 0; $i < $length; $i++) {
% |+ G0 v! I. N  yield $i;% [" l+ G: f2 R4 u$ x
  }& o7 `) D+ |4 O1 t
  }* ]3 X* M. x- V3 ?9 j4 _& i
  foreach(makeRange(1000000) as $i) {3 P* Z7 F. k/ _
  echo $i, PHP_EOL;4 [- t( I3 g) G, S% g* K9 ~4 x) @, V
  }
: D. x/ u( c4 X" B4 k+ z& a  在实际的例如迭代一个4GB大小的文件中功能中,迭代器大展身手。
5 y$ N# \& ^% @2 i5 w' o  function getRows($file) {
/ K* a3 J* ?% `  E9 W. E  $handle = fopen($file, 'rb');' \( ^7 Z2 f! t$ V; r/ X. T
  if ($handle === false) {+ `& k7 X3 a4 i0 a, e. o5 J1 O/ P
  throw new Exception();) I' a. |! C7 B2 `+ `7 {  h
  }
4 R" C( D+ b$ R8 p8 n/ c1 j3 W  //feof()函数检测是否到达文件末尾
6 ?8 c) X' g1 _  while (feof($handle) === false) {
5 d4 O- ?" o. f7 k) r8 K  //fgetcsv()一次读取csv文件的一行* C7 R& P# T1 U
  yield fgetcsv($handle);9 {5 o1 [  }! }, h
  }* Q9 C1 k- u3 p2 m8 }5 ~
  fclose($handle)
0 g  V+ G0 \3 F  }
; ]3 v/ n! z. E  foreach (getRows('data.csv') as $row) {
5 z6 H& {: o# W6 T, [  print_r($row);
" a" s: S9 [3 q& l5 B4 g  }
7 f. |1 @, N% a+ Z6 q' U  3).生成器没有为PHP添加新功能,需要实现在数据集中执行快进、快退和查找,最好自己编写类实现Iterator接口,或者使用PHP标准库中的某个原生迭代器。
. X) S- ~9 T/ ~* ?0 @
% a7 C- a7 m- B' b, F- f7 I& g% {9 ~+ w: Y5 D! {
来源:稀土掘金
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

GMT+8, 2025-7-4 07:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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