php 安装 zend opcace

1.linux 安装

wget http://pecl.php.net/get/zendopcache-7.0.5.tgz
tar xzf zendopcache-7.0.5.tgz 
cd zendopcache-7.0.5
/usr/local/php/bin/phpize
./configure   --with-php-config=/usr/local/php/bin/php-config
make
make install

Note:
If you want to use OPcache with » Xdebug, you must load OPcache before Xdebug.
如果你使用了Xdebug,您的配置中OPcache 要放到Xdebug前面。

在php.ini中加入:

zend_extension=/usr/local/php/lib/php/extensions/no-debug-zts-20100525/opcache.so
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1

 

其中:max_accelerated_files 设置的是缓存的文件,这个您需要到您的应用下面查看一下php文件的数量,可以通过下面的命令统计:

find ./* \( -name '*.php' -or -name '*.inc' \) -type f -print |wc -l

如果文件多,可以设置的高一些。

 

整理了一下其在php.ini中各参数的使用说明,供大家参考,有一些不太懂的,就留空了,还请高手赐教。

名字 默认 可修改范围 含义
opcache.enable “1” PHP_INI_ALL 是否启用opcache
opcache.enable_cli “0” PHP_INI_SYSTEM 是否在CLI(即命令行时)启用opcache
opcache.memory_consumption “64” PHP_INI_SYSTEM 为opcache分配多少共享内存,单位M
opcache.interned_strings_buffer “4” PHP_INI_SYSTEM interned string的内存大小
opcache.max_accelerated_files “2000” PHP_INI_SYSTEM 最大缓存的文件数目。

实际上这个值会使用第一个大于你配置的数字的下列素数

{ 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 },

如你将该值指定为400,则实际上该值为463.

opcache.max_wasted_percentage “5” PHP_INI_SYSTEM
opcache.use_cwd “1” PHP_INI_SYSTEM 如果置为1,则将当前路径加入到文件key中,

以避免可能产生的同文件名的文件key冲突

opcache.validate_timestamps “1” PHP_INI_ALL 如果置为1,则OPCACHE会自动检测文件的时间戳

(检测周期为revalidate_freq),

并根据文件的时间戳来更新opcode,如果置为0,

则只能手动去重启opcache或

重启webserver以使更新后的php文件生效

opcache.revalidate_freq “2” PHP_INI_ALL opcache自动检测文件是否更新的周期,单位秒。

如果是0,则每次请求时opcache都要进行检测。

当validate_timestamps为0时,本指令无效。

opcache.revalidate_path “0” PHP_INI_ALL
opcache.save_comments “1” PHP_INI_SYSTEM 是否保存文件中的注释
opcache.load_comments “1” PHP_INI_ALL 是否load comments,与save_comments联合起来使用,

如果该值为0,则即使save_comments为1,

那么php脚本中的comments也是不使用的

opcache.fast_shutdown “0” PHP_INI_SYSTEM 是否打开快速关闭,

打开时可使php在request shutdown时回收内存快

opcache.enable_file_override “0” PHP_INI_SYSTEM 如果置为1,则每次调用file_exist() is_file() is_readable()函数时,

opcache将要检查该文件是否被cache了,

这样增加了检查存在性和可读性的开销,

但避免了当validate_timestamps为disable时返回错误文件状态的风险。

opcache.optimization_level “0xffffffff” PHP_INI_SYSTEM 运行时控制优化的掩码(干什么的?)
opcache.inherited_hack “1” PHP_INI_SYSTEM 5.3以前使用。5.3后废弃
opcache.dups_fix “0” PHP_INI_ALL 为解决“cannot redecllare class” 时,可将其置为1
opcache.blacklist_filename “” PHP_INI_SYSTEM 设置黑名单文件,符合黑名单文件中定义的php文件将不被opcache。黑名单文件的例子如下:

; Matches a specific file.
/var/www/broken.php
; A prefix that matches all files starting with x.
/var/www/x
; A wildcard match.
/var/www/*-broken.php
一行为一条规则,支持通配符,注释以分号开头
opcache.max_file_size “0” PHP_INI_SYSTEM 被cache的文件的最大size,单位bytes。0表示不限
opcache.consistency_checks “0” PHP_INI_ALL 如果置为N,N非零,则opcache会每N个请求核实一下cache的检验和。

这会损害性能,应该只在debug时使用

opcache.force_restart_timeout “180” PHP_INI_SYSTEM 如果opcache处于非active状态,当N秒后opcache将自动重启
opcache.error_log “” PHP_INI_SYSTEM opcache自身的errorlog文件路径,为空时则使用stderr
opcache.log_verbosity_level “1” PHP_INI_SYSTEM 日志记录level,默认只有fatal error和error
opcache.preferred_memory_model “” PHP_INI_SYSTEM opcache首选使用的内存模型,为空时会选择最适当的模型。

常用的有,mmap shm posix 和win32

opcache.protect_memory “0” PHP_INI_SYSTEM 运行php脚本时保护共享内存防止意外的写入。

只对debug时有用。

opcache.mmap_base NULL PHP_INI_SYSTEM
0

 

 

顶级PHP大师的开发原则

1. 在合适的时候使用PHP – Rasmus Lerdorf

没有谁比PHP的创建者Rasmus Lerdorf明白PHP用在什么地方是更合理的,他于1995年发布了PHP这门语言,从那时起,PHP就像燎原之火,烧遍了整个开发阵营,改变了互联 网的世界。可是,Rasmus并不是因此而创建PHP的。PHP是为了解决web开发者的实际问题而诞生的。

和许多开源项目一样,PHP变得流行,流行的动机并不能用正常的哲学来进行解释,甚至流行得有些孤芳自赏。它完全可以作为一个案例,一个解决各种Web问题的工具需求所引起的案例,因此当PHP刚出现的时候,这种工具需求全部聚焦到PHP的身上。

但是,你不能奢望PHP可以解决所有问题。Lerdorf是第一个承认PHP只是一种工具的人,并且PHP也有很多力所不能及的情况。

根据工作的不同来选择合适的工具。我跑了很多家公司,为了说服他们部署和使用PHP,但是这并不意味着PHP对所有问题都适用。它只是可以一个解决大部分问题的front-end脚步语言。

作为一个web开发者,尝试用PHP解决所有问题是不科学的,同时也会浪费你的时间。当PHP玩不转的时候,不要犹豫,试用一下其他的语言吧。

2. 使用多表存储提高规模伸缩性 – Matt Mullenweg

没有人愿意质疑Matt Mullenweg在PHP方面的权威性,他开发了这个星球上最流行的blog系统,(依靠一个强大的社区力量支持): WordPress. 创建Wordpress以后,Matt和他的团队启动了WordPress.com平台,一个基于WordPress MU的免费blog站点。现在,Wordpress.com已经拥有大约400万用户, 这些用户每天提供超过 140,000篇的日志。 (要查看更多Wordpress.com的统计情况,请点击这里.)

如果有人知道如何让网站的规模伸缩自如,这个人一定是Matt Mullenweg。2006年的时候 Matt对Wordpress的数据结构进行了前瞻性的改进,并且解释了为什么Wordpress MU对每个blog使用独立的MYSQL表格, 而不是把所有的blog数据都塞进一个巨大的表格。

我们测试过这个方法,但是发现如果要扩展它的伸缩性,代价太高。如果用一个整体的数据结构,在大流量面前,你将会面临服务器 硬件的问题。在MU里面。用户们都被分布到独立的表格当中,并且可以轻易地组织起来。举个例子,WordPress.com把用户的数据分散存储到 4096个数据库中,这些数据库可以分散大规模的数据访问,实现流量和压力分流。

数据表的可迁移性让代码(blog)可以运行得更快,并且让系统具备更强的伸缩性。依靠强大的缓存策略和灵活的数据库运用策略, Matt向人们展示了时下最流行的Facebook和Wordpress.com都可以在PHP下稳定运行,并且处理惊人的访问量。

3. 千万不要相信用户 – Dave Child

Dave Child是Added Bytes (previously ilovejackdaniels.com) 网站的核心人物,这个网站以他出色的《cheat sheets for many programming languages》而闻名。 Dave为很多英国的公司服务,并且已经在编程世界里树立起相当的权威。

Dave为PHP开发者提供了很多深谋远虑的建议,并总结成了《writing secure code in PHP》:千万不要相信你的用户,他们甚至可能会伤害你。

有一条web开发的基本原则,我重复多少遍都觉得不够,那就是:千万不要相信你的用户,同时要假设你网站中的每个数据单元都是从用户那里收集来 的恶意代码。很多时候,你必须用javascript在客户端检验表单提交过来的内容, 如果你习惯了如此,那么,这是一个好习惯。如果安全性对你来说很重要,这就是最重要最需要学习的原则。

Dave目前正致力于为它的《Writing Secure PHP》系列书籍整理实例,书的最后他说:

最后,变得偏执一点吧。除非你认为你的站点永远不会受到攻击,否则就正视所有的问题,当问题真正发生的时候,你的情况会变得很糟。你需要把每个用户都看成会带来一场攻防站的黑客,想尽一切办法来保护站点的安全,同时想好相应问题的解决方案。

 4. 多使用PHP缓存 – Ben Balbo

Ben Balbo开发了Site Point,一个为developers和designers提供指导的网站。他是墨尔本PHP开发和开源俱乐部的成员, 因此他对PHP有一定的了解,同时对PHP caching有一定的想法和经验。

如果你拥有一个访问量很大,但更新并不频繁的站点(比如blog,基于某种CMS),或许它需要进行一些改造,这些改造不会花费太多的时间,但是对性能有突出的贡献。 如果要为一个复杂/更新频率很快的站点建立缓存机制,过程可能会很曲折,但是好处也是显而易见的。

PHP缓存技术有很多种,Ben为我们推荐了如下一些:

◆缓存函数的运行结果

◆设置过期时间

◆缓存IE下载的文件

◆模板缓存技术

◆Cache_Lite

由于PHP作为动态语言的特性,缓存机制对于更新频率并不快的站点来说非常重要。

5. 使用IDE, Templates和Snippets加速PHP开发 – Chad Kieffer

当Chad Kieffer从UI设计和数据库优化的工作中抽身出来的时候,他会在他的博客2 tablespoons上分享很多技术经验。由于Chad多方面的全面发展,他经常可以发现其他程序员不能发现的问题,并形成相关经验,尤其是他开发网站 的方法。他参与了网站开发的各个环节,因此他的建议对于提高网站开发的大局观非常有用。

Chad认为使用Eclipse PDT(Eclipse’s PHP development package) 这样的IDE,同时使用一些模板技术和开源项目可以有效地提高PHP的开发速度。

紧凑的计划,长长的to do lists以及deadlines让开发人员非常苦闷。不过有些功能,比如Eclipse Templates,可以有效减少编码的时间和出错的几率。

通常来说,任何项目都可以自动化,自动化程度越高, 你完成项目的时间就越短。花时间来开发使用频率很高的框架和模板,将会节省你以后更多时间。同时,使用像Eclipse and the PDT package这样的IDE,你会发现效率得到明显提高,IDE可以自动闭合,补全分号并且可以在本地debug。

 6. 利用好PHP的过滤函数 – Joey Sochacki

或许Joey Sochacki并不像Matt Mullenweg那样有名 ,但他也是一个经验丰富的开发者,并且通过他的博客Devolio分享了很多技术经验

Joey发现在编写php代码的过程中有很多地方需要进行过滤,但却并没有太多的coder关注php的内置过滤函数。

过滤数据是我们经常需要做的事情,但是很多功能丰富的PHP内置过滤函数却不为人知。使用类似filter_* 的PHP内置函数,我们几乎可以处理所有的过滤任务,包括数据类型验证/URL/email和IP地址验证/特殊字符处理等等。

过滤是一件复杂的事情,但是我相信joey的发现会给你很多启发,让你认识到PHP强大的过滤功能。

7. 使用PHP框架 – Josh Sharp

对于是否应该使用Zend, CakePHP, Code Igniter, 或者 其他PHP框架,一直存在着很多争议,但是在web开发者的心中,他们有自己衡量的标准。

Josh Sharp自己创建了一家提供面包和黄油服务的网站,因此他对于使用PHP框架来开发网站有一定的经验。他认为使用一个PHP框架来进行项目开发(use a PHP framework ),可以有效地节省时间,并且减少出错的几率。为什么?因为他觉得PHP实在是太好上手了。

PHP的易于使用有时候也有缺陷,因为并不严格的语法,经常会导致很多错误代码的诞生。但如果使用一个PHP框架,出错的几率就会大大减少。

PHP框架可以让你的代码结构更加规范,并且节省大量时间。

8. 不要使用PHP框架 – Rasmus Lerdorf

与Josh的观点恰恰相反,PHP的鼻祖Rasmus Lerdorf却认为最好不要使用PHP框架,为什么?因为不基于框架的PHP性能更好。Rasmus在Drupalcon 2008的演讲上,用“Hello World”的例子来对比了一些框架PHP和简单PHP之间的性能,结果显示框架PHP的性能要远远落后。

9. 使用批处理 – Jack D. Herrington

Jack Herrington对PHP世界并不陌生, 并且为大名鼎鼎的IBM developerWorks贡献过超过30篇的专搞, 同时出版过《PHP Hacks》的书,因此他是一个真正的专家。

Herrington推荐使用批处理和Cron来代替那些可以运行在后台的程序脚步,Web用户并不愿意在线等待你的处理过程,所以有些事情更适合放到后台来处理。

诚然,在某些情况下,这有点大材小用了,但是你可以清楚地看到,使用Cron, MySQL, PHP面向对象的方法以及Pear::DB这些便捷的工具来创建一个批处理工具并不是一件复杂的事情。

Jack认为使用cron, PHP和MySQL在后台处理一些任务,比起多进程的业务逻辑要划算得多。

两种方法我都尝试过,我认为Cron非常符合”Keep It Simple, Stupid” (KISS) 的原则,它让后台处理变得简单。与多进程的业务逻辑相比,它没有内存 溢出的风险。你可以创建一个简单的批处理脚本,并且在cron中运行,这个脚本会定时检查是否有任务需要处理,处理完之后就会自动退出,因此你不用担心是 否有进程卡壳,或者陷入死循环。

 10. 及时启用错误报告 – David Cummings

David Cummings有一个专门提供CMS软件服务的公司 ,并且获得过几次奖 ,他有非常丰富的PHP开发经验。David曾经写过《two PHP tips he wished he’d learned in the beginning》,其中一点就是:及时启用错误报告,这会节省大量的时间。

我告诉人们,最重要的事情就是最大程度地开启PHP的错误报告,为什么?因为PHP可能会隐藏很多小问题:

◆变量没有预定义

◆在代码片段中引用了不可用的变量

◆使用了未定义的常量这些因素看起来并不是什么大事,除非你在使用面向对象的方法编写一些类库。通常,关闭错误报告将可能使你付出更大的成本来维护你的代码。

错误报告可以帮你轻易地找到代码的问题所在,如果错误报告的等级够高,细微的错误都能被立即发现,帮助你节省整体debug的时间。

vagrant 下载部署linux环境

1. 安装 VirtualBox

虚拟机还是得依靠 VirtualBox 来搭建,免费小巧
下载地址:https://www.virtualbox.org/wiki/Downloads

* 虽然 Vagrant 也支持 VMware,不过 VMware 是收费的,对应的 Vagrant 版本也是收费的。

我下载的是:VirtualBox 5.1.6 for Windows hosts  x86/amd64


2. 下载  Vagrant

下载地址:http://downloads.vagrantup.com/

3.下载contos box,可以来这里下载:http://www.vagrantbox.es/

 

经过上面的下载,我们

下载了virtual box   vagrant   centos 6.6 box  三个文件

4.安装 virtualbox ,  vagrant ,这个基本都是下一步,安装完成后要重启

安装上面的两个成功后,重启后。

4.1

window建+r ,打开命令行,

进入命令行模式,输入vagrant,看看是否安装成功

4.2 添加centos box

进入d盘,添加centos box

进入contos box文件所在的文件夹,我的是在d:\vagrant文件路径下,按照上面截图的命令行进入d盘,在通过cd vagrant 进入相应文件夹。

D:\vagrant\centos-6.6-x86_64.box

按照这个命令添加一个box

vagrant box add 名称 路径

譬如:

D:\vagrant\vagrant box add centos-6.6-x86_64   centos-6.6-x86_64.box

这里将  box 名称:centos-6.6-x86_64  对应 D:\vagrant\vagrant\centos-6.6-x86_64.box这个文件,后面可以使用centos-6.6-x86_64,使用后直接对应上面对应的文件。

通过vagrant box list  查看添加的列表

4.3创建虚拟机:

添加了 Box 以后,我们就可以用 Vagrant 基于这个 Box 去创建虚拟机了。先找个地方去创建一个目录,这个目录就是你的项目所在的目录,它会自动跟虚拟机上的某个目录同步,也就是在你电脑上的这个目录里面的文 件,你同样可以在虚拟机里的某个目录里面找到。比如我的目录在d:\myvagrant,我创建这个目录,然后再进入到这个目录,在命令行工具下面执行:

初始化:

启动 vagrant up命令,第一次会慢一些,因为要复制文件。

在上面,发现了拨错:

Timed out while waiting for the machine to boot. This means that  
    Vagrant was unable to communicate with the guest machine within  
    the configured ("config.vm.boot_timeout" value) time period.  
  
    If you look above, you should be able to see the error(s)  that Vagrant had when attempting to connect to the machine. These errors are usually good hints as to what may be wrong.  
  
    If you're using a custom box, make sure that networking is properly working and you're able to connect to the machine. It is a common problem that networking isn't setup properly in these boxes. Verify that authentication configurations are also setup properly,as well.  
  
    If the box appears to be booting properly, you may want to increase the timeout ("config.vm.boot_timeout") value.

 

打开文件:D:\myvagrant\Vagrantfile

将Vagrantfile配置文件中vb.gui = true的注释去掉,下面将三行的代码的注释去掉了,也就是前面的  # 号,而不是一行,这里要注意,如果仅仅去掉vb.gui = true的注释,会报错。

config.vm.provider "virtualbox" do |vb|  
#   # Don't boot with headless mode  
    vb.gui = true  
#  
#   # Use VBoxManage to customize the VM. For example to change     memory:  
#   vb.customize ["modifyvm", :id, "--memory", "1024"]  
 end

然后关闭  vagrant  halt  ,重启,查看报错。
运行vagrant up 启动 virtualbox 后,GUI会给出提示:

VT-x/AMD-V硬件加速在您的系统中不可用。您的64-位虚拟机将无法检测到 64-位处理器,从而无法启动。  
这是由于在BOIS中没有开启cpu虚拟化支持,重启F2或F10等进入BIOS设置Virtualization为Enable(我的Thinkpad是Security=>Virtualizatio设置为Enable);

电脑重启后,再次vagrant up启动虚拟机还是有一些问题,当时也没有记录下来错误信息,只记得解决方案是使用vagrant destroy将虚拟机从磁盘中删除,然后使用vagrant up命令重新创建。

重启后,换一个文件路径,我原来的是d:\myvagrant,我换到了另外一个路径d:\disk\va1

上面出现waining,是没有问题的,现在我们可以通过ssh直连了。

查看vagrant的状态  vagrant status

关闭VM     vagrant halt

在启动  vagrant up, 第二次启动会比较快,因为不会复制文件,但是还是很慢,哈哈,多等下就好了。

ssh 连接

ip:127.0.0.1

端口:2222

用户名:vagrant

密码:vagrant

root的密码也是vagrant  ,上面连接一定要注意,更改ssh的默认端口22 为 2222

ssh 登录后,我发现语言是德语的,日,使用root账号登录,更改语言

 

vim /etc/sysconfig/i18n

语言改成英语

LANG="en_US.UTF-8"  
SYSFONT="latarcyrheb-sun16"

重启一下linux

查看centos 版本:

[root@localhost ~]# cat /etc/redhat-release  
CentOS release 6.6 (Final)  
[root@localhost ~]#

 

到此为止,初始环境搭配好了,下面需要安装 lnmp环境了。

具体参看下一节

vagrant 配置

Vagrant 初始化成功后,会在初始化的目录里生成一个 Vagrantfile 的配置文件,可以修改配置文件进行个性化的定制。

Vagrant 默认是使用端口映射方式将虚拟机的端口映射本地从而实现类似 http://localhost:80 这种访问方式,这种方式比较麻烦,新开和修改端口的时候都得编辑。

相比较而言,host-only 模式显得方便多了。打开 Vagrantfile,将下面这行的注释去掉(移除 #)并保存:

config.vm.network :private_network, ip: "192.168.33.10"

重启虚拟机,这样我们就能用 192.168.33.10 访问这台机器了,你可以把 IP 改成其他地址,只要不产生冲突就行。

注意:对于端口映射一定要配置,譬如:

config.vm.network “forwarded_port”, guest: 80, host: 80

不然,在开启nginx后,通过127.0.0.1是无法访问的,这个一定不要忘记

我暂时采用的是单个匹配的方式:如下:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://atlas.hashicorp.com/search.
  config.vm.box = "centos6.6"

  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  config.vm.network "forwarded_port", guest: 8080, host: 8080
  config.vm.network "forwarded_port", guest: 80, host: 80
  config.vm.network "forwarded_port", guest: 2001, host: 2001
  config.vm.network "forwarded_port", guest: 2030, host: 2030
  
  config.vm.network "forwarded_port", guest: 2030, host: 2030
  config.vm.network "forwarded_port", guest: 2020, host: 2020
  config.vm.network "forwarded_port", guest: 2010, host: 2010
  config.vm.network "forwarded_port", guest: 2000, host: 2000
  config.vm.network "forwarded_port", guest: 1000, host: 1000
  config.vm.network "forwarded_port", guest: 1010, host: 1010
  #config.vm.network :private_network, ip: "192.168.111.1"
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  # config.vm.network "private_network", ip: "192.168.33.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  # config.vm.network "public_network"

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  # config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
  #   vb.memory = "1024"
  # end
  #
  # View the documentation for the provider you are using for more
  # information on available options.

  # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
  # such as FTP and Heroku are also available. See the documentation at
  # https://docs.vagrantup.com/v2/push/atlas.html for more information.
  # config.push.define "atlas" do |push|
  #   push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
  # end

  # Enable provisioning with a shell script. Additional provisioners such as
  # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
end

6. 打包分发

当你配置好开发环境后,退出并关闭虚拟机。在终端里对开发环境进行打包:

vagrant package

打包完成后会在当前目录生成一个 package.box 的文件,将这个文件传给其他用户,其他用户只要添加这个 box 并用其初始化自己的开发目录就能得到一个一模一样的开发环境了。

这个box文件,如果给了其他人用,先通过下面的命令行添加

vagrant box add  fecshop  fecshop.box

 

然后,和上面一样,找一个新的文件夹,

vagrant init fecshop

执行成功后,启动

vagrant up

 

另外需要注意的是,需要把 Vagrantfile 这个里面的配置复制到新的地方,配置一致才可以。这样就完成了分发。
7. 常用命令

vagrant init  # 初始化
vagrant up  # 启动虚拟机
vagrant halt  # 关闭虚拟机
vagrant reload  # 重启虚拟机
vagrant ssh  # SSH 至虚拟机
vagrant status  # 查看虚拟机运行状态
vagrant destroy  # 销毁当前虚拟机

更多内容请查阅官方文档 http://docs.vagrantup.com/v2/cli/index.html
8. 注意事项

使用 Apache/Nginx 时会出现诸如图片修改后但页面刷新仍然是旧文件的情况,是由于静态文件缓存造成的。需要对虚拟机里的 Apache/Nginx 配置文件进行修改:

# Apache 配置添加:
EnableSendfile off

# Nginx 配置添加:
sendfile off;

 

其他问题:

问题2: vagrant启动报错The following SSH command responded with a non-zero exit status.

The following SSH command responded with a non-zero exit status.  
Vagrant assumes that this means the command failed!  
  
ARPCHECK=no /sbin/ifup eth1 2> /dev/null  
  
Stdout from the command:  
  
Device eth1 does not seem to be present, delaying initialization.  
  
Stderr from the command:

解决方案
虽然vagrant up启动报错,但是vagrant ssh还是能登陆虚拟机的,进入虚拟机后,执行如下命令

sudo rm -f /etc/udev/rules.d/70-persistent-net.rules

对, 问题就处在在持久网络设备udev规则(persistent network device udev rules)是被原VM设置好的,再用box生成新VM时,这些rules需要被更新。而这和Vagrantfile里对新VM设置private network的指令发生冲突。删除就好了。
vagrant reload 再次启动就OK。

问题3:在配置好vagrant和虚拟机中的nginx后,当你通过宿主机访问虚拟机中的web站点时,出现页面一直在加载,无法正常显示页面
(此块由程序员 Young 614168741 添加)
解决方法:因为centos7.0(含7.0)及以上版本会默认安装firewalld防火墙,firewalld有zone的概念默认在public区,只能指定外部连接进入,首先systemctl status firewalld 查看防火墙状态,active:running表示开启转态,然后我们firewall-cmd –zone=public –add-port=80/tcp –permanent,或者firewall-cmd –zone=public –add-port=8080/tcp –permanent(取决于你的Vagrantfile端口端口那一个是映射到虚拟机的80),执行完,firewall-cmd –zone=public –list-ports检查下public区上的端口,出现刚才添加的端口说明成功,再firewall-cmd –reload重启下firewalld,这个时候通过宿主机通过制定的配置的端口访问虚拟机站点应该就可以了

yii2 AR 结构进行数据类型转换的原理(PDO)

通过PDO,默认出来的数据都是string类型,在Yii2的AR(Active Record)中,按照类型进行了数据转换,但是如果查询的时候使用了asArray(),则不会进行转换,也就是说

User::find()->asArray()->all()

查询的结果,包括id在内的所有结果,都是字符串类型

User::find()->all() ,返回的是对象数组,结果会进行类型转换

ActiveRecord转换的原理为下面:

yii\db\ActiveRecord

public static function populateRecord($record, $row)
   {
       $columns = static::getTableSchema()->columns;
       foreach ($row as $name => $value) {
           if (isset($columns[$name])) {
               $row[$name] = $columns[$name]->phpTypecast($value);
           }
       }
       parent::populateRecord($record, $row);
   }

通过上面的方法进行了类型的转换,也就是phpTypecast方法。

 

如果查询的时候加上了asArray(),则不会进行类型转换,出来的数据都是String

譬如代码:

$data = \fecadmin\models\AdminMicroRoleBrand::find()->asArray()
          ->where([
            'in','role_id',$micro_role_arr
          ])->all();

出来的是数据都是字符串

如果按照下面的代码,查询出来的对象里面的属性都是相应的数据库的类型:

$data = \fecadmin\models\AdminMicroRoleBrand::find()
          ->where([
            'in','role_id',$micro_role_arr
          ])->all();

所以,在加入asArray()查询的时候,速度是最快的,但是要注意一下数据类型,适当的时候需要手动转换。

Yii2 Mongodb 数据库报错:remote connect close

我使用了mongodb的复制集,报错remote connect close

Yii2中我更改下了配置如下:

'mongodb_erp' => [
            'class' => 'yii\mongodb\Connection',
            'dsn' => 'mongodb://192.168.220.105:27017/erp,192.168.220.106:27017/erp?replicaSet=rs0&readPreference=secondaryPreferred', # primaryPreferred |  secondaryPreferred
      'options' => [
        'socketTimeoutMS' => 300000,  # 设置超时时间
        'connectTimeoutMS'=> 600000,  # 设置连接超时时间
      ],
],

 

将读改成副本读优先,对于读的优先级的设置解释如下:

/**
        const string RP_PRIMARY = "primary" ;  						# 始终用主读
        const string RP_PRIMARY_PREFERRED = "primaryPreferred" ;	# 主读优先
        const string RP_SECONDARY = "secondary" ;					# 始终用副本读
        const string RP_SECONDARY_PREFERRED = "secondaryPreferred" ;# 副本读优先
        const string RP_NEAREST = "nearest" ;						# 主和副本随机读
      */

另外,长连接可能存在失效问题,在连接mongodb的时候,需要循环一下:

Yii2 随机发生 php mongo报错:’Failed to connect to: XXXXX: Remote server has closed the connection’的解决方法

 

Yii2 随机发生 php mongo报错:’Failed to connect to: XXXXX: Remote server has closed the connection’的解决方法

 

运行mongodb连接的时候,遇到了 Remote server has closed the connection 的错误问题。而且是随机性发生的。

在Yii2中,需要进行的修改为:

Yii2-mongodb/Connecting.php

修改函数:

public function open()
   {
       if ($this->mongoClient === null) {
           if (empty($this->dsn)) {
               throw new InvalidConfigException($this->className() . '::dsn cannot be empty.');
           }
           $token = 'Opening MongoDB connection: ' . $this->dsn;
           try {
               Yii::trace($token, __METHOD__);
               Yii::beginProfile($token, __METHOD__);
               $options = $this->options;
               $options['connect'] = true;
               if ($this->defaultDatabaseName !== null) {
                   $options['db'] = $this->defaultDatabaseName;
               }
              // $this->mongoClient = new \MongoClient($this->dsn, $options);
         $this->mongoClient = $this->getCustomMongoClient($options);
               $this->initConnection();
               Yii::endProfile($token, __METHOD__);
           } catch (\Exception $e) {
               Yii::endProfile($token, __METHOD__);
               throw new Exception($e->getMessage(), (int) $e->getCode(), $e);
           }
       }
   }

 

添加函数

public function getCustomMongoClient($options,$retry = 4) {
    try {
      return new \MongoClient($this->dsn, $options);
    } catch(Exception $e) {
      /* Log the exception so we can look into why mongod failed later */
      //logException($e);
    }
    if ($retry > 0) {
      return $this->getCustomMongoClient($options, --$retry);
    }
    throw new Exception("I've tried several times getting MongoClient.. Is mongod really running?");
  }

也就是通过多次尝试连接的方式。