MVC框架是怎样工作的呢?这其实是一个很重要的问题,对于标准的MVC框架来说, Controller层往往是程序的入口(网页的地址就是 Controller层的地址 ) ,然后由Controller层加载 View层进行显示(显示在浏览器上的页面其实并不是你输入的地址),在View层用户通过表单实现交互,表单将数据传回 Controller层,由 Controller层调用Model层进行数据处理、存储、读取等操作,然后Model层将处理结果返回给Controller层, Controller层再次加载View层显示处理的结果,这样就完成了一次完整的、标准的MVC框架下的用户交互动作,在我描述的这个交互过程中,请大家注意两个关键的词语:加载和调用,现在可能还不理解,在接下来的学习中,你将逐步体会到这两个词的区别和关系。为了更加直观的表示,我将整个交互过程用一幅流程图表示,如下所示:
nginx 配置 /usr/local/nginx/conf/nginx.conf
在 nginx.conf中增加依稀配置
location / {try_files $uri index.php?$args;}location ~ \.php$ {include fastcgi.conf;include fastcgi_params;fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;fastcgi_param CI_ENV DEVELOPMENT;fastcgi_param SCRIPT_NAME $fastcgi_script_name;fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;}
/usr/local/php/etc/php.ini和/etc/php.ini 有连个php配置文件,使用的是/usr/local/php/etc/php.ini
注释掉opcache相关的代码
;opcache[Zend Opcache];zend_extension=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;opcache end
1.4 PHP之类和对象
- 一个普通的类的示例:
name; } } //实例化一个car对象 $car = new Car(); $car->name = '奥迪A6'; //设置对象的属性值 echo $car->getName(); //调用对象的方法 输出对象的名字
- 使用 class 定义类;
- 使用 new 实例化对象
- $objectName -> attributeName 访问对象的属性,注意:属性名前不要加$.
- 类名的命名规范必须是字母或下划线开头,后面紧跟若干个字母、数字或下划线,类名最好能够表意,可以采用名词或者英文单词。
- 属性在类中定义的变量称之为属性,通常属性跟数据库中的字段有一定的关联,因此也可以称作“字段”。属性声明是由关键字 public,protected 或者 private 开头,后面跟一个普通的变量声明来组成。属性的变量可以设置初始化的默认值,默认值必须是常量。
class Car { //定义公共属性 public $name = '汽车'; //定义受保护的属性 protected $corlor = '白色'; //定义私有属性 private $price = '100000'; }
默认都为public,外部可以访问。一般通过 -> 对象操作符来访问对象的属性或者方法,对于静态属性则使用 :: 双冒号进行访问。当在类成员方法内部调用的时候,可以使用 $this 伪变量调用当前对象的属性。$car = new Car();echo $car->name; //调用对象的属性 echo $car->color; //错误 受保护的属性不允许外部调用 echo $car->price; //错误 私有属性不允许外部调用
受保护的属性与私有属性不允许外部调用,在类的成员方法内部是可以调用的。class Car{ private $price = '1000'; public function getPrice() { return $this->price; //内部访问私有属性 } }
- 定义类的方法方法就是在类中的function,很多时候我们分不清方法与函数有什么差别,在面向过程的程序设计中function叫做函数,在面向对象中function则被称之为方法。同属性一样,类的方法也具有public,protected 以及 private 的访问控制。我们可以这样定义方法:
class Car { public function getName() { return '汽车'; } } $car = new Car(); echo $car->getName();
使用关键字 static 修饰的,称之为静态方法,静态方法不需要实例化对象,可以通过类名直接调用,操作符为双冒号 :: 。class Car { public static function getName() { return '汽车'; } } echo Car::getName(); //结果为“汽车”
-
构造函数与析构函数
PHP5可以在类中使用 __construct() 定义一个构造函数,具有构造函数的类,会在每次对象创建的时候调用该函数,因此常用来在对象创建的时候进行一些初始化工作。class Car { function __construct() { print "构造函数被调用\n"; } } $car = new Car(); //实例化的时候 会自动调用构造函数__construct,这里会输出一个字符串
在子类中如果定义了_construct则不会调用父类的_construct,如果需要同时调用父类的构造函数,需要使用 parent::__construct() 显式的调用。
class Car { function __construct() { print "父类构造函数被调用\n"; } } class Truck extends Car { function __construct() { print "子类构造函数被调用\n"; parent::__construct(); } } $car = new Truck();
同样,PHP5支持析构函数,使用 __destruct() 进行定义,析构函数指的是当某个对象的所有引用被删除,或者对象被显式的销毁时会执行的函数。
class Car { function __construct() { print "构造函数被调用 \n"; } function __destruct() { print "析构函数被调用 \n"; } } $car = new Car(); //实例化时会调用构造函数 echo '使用后,准备销毁car对象 \n'; unset($car); //销毁时会调用析构函数
当PHP代码执行完毕以后,会自动回收与销毁对象,因此一般情况下不需要显式的去销毁对象。
-
static 静态关键字
静态属性与方法可以在不实例化类的情况下调用,直接使用类名::方法名的方式进行调用。静态属性不允许对象使用->操作符调用。class Car { private static $speed = 10; public static function getSpeed() { return self::$speed; } } echo Car::getSpeed(); //调用静态方法
静态方法也可以通过变量来进行动态调用
$func = 'getSpeed';$className = 'Car'; echo $className::$func(); //动态调用静态方法
静态方法中,$this伪变量不允许使用。可以使用self,parent,static在内部调用静态方法与属性。
class Car { private static $speed = 10; public static function getSpeed() { return self::$speed; } public static function speedUp() { return self::$speed+=10; } } class BigCar extends Car { public static function start() { parent::speedUp(); } } BigCar::start(); echo BigCar::getSpeed();
-
访问控制
访问控制通过关键字public,protected和private来实现。- 被定义为公有的类成员可以在任何地方被访问。
- 被定义为受保护的类成员则可以被其自身以及其子类和父类访问。
- 被定义为私有的类成员则只能被其定义所在的类访问。
类属性必须定义为公有、受保护、私有之一。为兼容PHP5以前的版本,如果采用 var 定义,则被视为公有。
class Car { $speed = 10; //错误 属性必须定义访问控制 public $name; //定义共有属性 }
类中的方法可以被定义为公有、私有或受保护。如果没有设置这些关键字,则该方法默认为公有。
class Car { //默认为共有方法 function turnLeft() { } }
如果构造函数定义成了私有方法,则不允许直接实例化对象了,这时候一般通过静态方法进行实例化,在设计模式中会经常使用这样的方法来控制对象的创建,比如单例模式只允许有一个全局唯一的对象。
class Car { private function __construct() { echo 'object create'; } private static $_object = null; public static function getInstance() { if (empty(self::$_object)) { self::$_object = new Car(); //内部方法可以调用私有方法,因此这里可以创建对象 } return self::$_object; } } //$car = new Car(); //这里不允许直接实例化对象 $car = Car::getInstance(); //通过静态方法来获得一个实例
- 对象继承继承是面向对象程序设计中常用的一个特性。汽车是一个比较大的类,我们也可以称之为基类,除此之外,汽车还分为卡车、轿车、东风、宝马等,因为这些子类具有很多相同的属性和方法,可以采用继承汽车类来共享这些属性与方法,实现代码的复用。
speed += 10; return $this->speed; } } //定义继承于Car的Truck类 class Truck extends Car { public function speedUp() { $this->speed = parent::speedUp() + 50; } } $car = new Truck(); $car->speedUp(); echo $car->speed;
- 重载PHP中的重载指的是动态的创建属性与方法,是通过魔术方法来实现的。属性的重载通过 __set,__get,__isset,__unset来分别实现对不存在属性的赋值、读取、判断属性是否设置、销毁属性。
class Car { private $ary = array(); public function __set($key, $val) { $this->ary[$key] = $val; } public function __get($key) { if (isset($this->ary[$key])) { return $this->ary[$key]; } return null; } public function __isset($key) { if (isset($this->ary[$key])) { return true; } return false; } public function __unset($key) { unset($this->ary[$key]); } } $car = new Car(); $car->name = '汽车'; //name属性动态创建并赋值 echo $car->name;
方法的重载通过 call 来实现,当调用不存在的方法的时候,将会转为参数调用call方法,当调用不存在的静态方法时会使用 __callStatic 重载。class Car { public $speed = 0; public function __call($name, $args) { if ($name == 'speedUp') { $this->speed += 10; } } } $car = new Car(); $car->speedUp(); //调用不存在的方法会使用重载 echo $car->speed;
- 对象的高级属性对象比较:当同一个类的两个实例的所有属性都相等时,可以使用比较运算符==进行判断,当需要判断两个变量是否为同一个对象的引用时,可以使用全等运算符===进行判断。
class Car {}$a = new Car(); $b = new Car(); if ($a == $b) echo '=='; //true if ($a === $b) echo '==='; //false
对象复制:在一些特殊情况下,可以通过关键字clone来复制一个对象,这时__clone方法会被调用,通过这个魔术方法来设置属性的值。class Car { public $name = 'car'; public function __clone() { $obj = new Car(); $obj->name = $this->name; } } $a = new Car(); $a->name = 'new car'; $b = clone $a; var_dump($b);
对象序列化:可以通过 serialize 方法将对象序列化为字符串,用于存储或者传递数据,然后在需要的时候通过 unserialize 将字符串反序列化成对象进行使用。class Car {public $name = 'car'; } $a = new Car(); $str = serialize($a); //对象序列化成字符串 echo $str.''; $b = unserialize($str); //反序列化为对象 var_dump($b);
phpredis是个人觉得最好的一个php-redis客户端,因为其提供的function与redis的命令基本一致,降低的了学习成本,同时功能也很全面。
一。linux安装方法
phpredis下载地址:
unzip phpredis-master.zip
cd phpredis-master
phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make
make install
vi /usr/local/php5/etc/php.ini
加入
extension=redis.so
保存后重启Apache,如果是连接的nginx,则需要重启php-fpm。
查看php运行目录命令:
which php/usr/bin/php查看php-fpm进程数:
ps aux | grep -c php-fpm查看运行内存
/usr/bin/php -i|grep mem重启php-fpm
/etc/init.d/php-fpm restart
PHP 变量名大小写问题:
1. 变量名区分大小写
2. 函数名、方法名、类名不区分大小写
===是包括变量值与类型完全相等,而==只是比较两个数的值是否相等。
比如:100==“100” 这里用==,因为它们的值相等,都是100,结果为真但是若用===,因为左边是一个整型而右边则是一个字符串类型的数,类型不相同所以结果为假。
@符号在php中是抑制错误提示用的。一般在可预知bug 的地方,加一个@符号来防止程序崩溃停止。比如unlink删除文件,如果没有找到要删除的文件,系统会报错,可以加一个@来防止程序停止。 不过一般用的很少,也尽量少用。
PHP 时间戳:
”;echo strtotime($stringtime).””;echo date(“Y/m/d G:i:s A”,strtotime($stringtime));?>
运行结果:
2010-06-21 17:29:32
1277112572 2010/06/21 17:29:32 PM
PHP 处理从命令行获取的参数
列表C代码");}// remove first argumentarray_shift($argv);// get and use remaining arguments$checkin = $argv[0];$nights = $argv[1];$type = $argv[2];echo "You have requested a $type room for $nights nights, checking in on $checkin. Thank you for your order! ";?>下面是其用法的示例:shell> php phpbook.php 21/05/2005 7 singleYou have requested a single room for 7 nights, checking in on 21/05/2005. Thank you for your order!在这里,脚本首先会检查$argc,以确保自变量的数量符合要求。它然后会从$argv里提取出每一个自变量,把它们打印输出到标准的输出。
原 Mac OSX 10.9搭建nginx+mysql+php-fpm环境
安装homebrew
homebrew是mac下非常好用的包管理器,会自动安装相关的依赖包,将你从繁琐的软件依赖安装中解放出来。
安装homebrew也非常简单,只要在终端中输入:ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
homebrew的常用命令:
brew update #更新可安装包的最新信息,建议每次安装前都运行下brew search pkg_name #搜索相关的包信息brew install pkg_name #安装包
想了解更多地信息,请参看
安装nginx
安装
brew search nginxbrew install nginx
当前的最新版本是1.4.4
。
配置
cd /usr/local/etc/nginx/mkdir conf.d vim nginx.conf vim ./conf.d/default.conf
nginx.conf内容,
worker_processes 1; error_log /usr/local/var/log/nginx/error.log warn; pid /usr/local/var/run/nginx.pid; events { worker_connections 256; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /usr/local/var/log/nginx/access.log main; port_in_redirect off; sendfile on; keepalive_timeout 65; include /usr/local/etc/nginx/conf.d/*.conf; }
default.conf文件内容,
server { listen 8080; server_name localhost; root /Users/user_name/nginx_sites/; # 该项要修改为你准备存放相关网页的路径 location / { index index.php; autoindex on; } #proxy the php scripts to php-fpm location ~ \.php$ { include /usr/local/etc/nginx/fastcgi.conf; fastcgi_intercept_errors on; fastcgi_pass 127.0.0.1:9000; } }
安装php-fpm
Mac OSX 10.9的系统自带了PHP、php-fpm,省去了安装php-fpm的麻烦。
这里需要简单地修改下php-fpm的配置,否则运行php-fpm
会报错。 sudo cp /private/etc/php-fpm.conf.default /private/etc/php-fpm.confvim /private/etc/php-fpm.conf
修改php-fpm.conf文件中的error_log
项,默认该项被注释掉,这里需要去注释并且修改为error_log = /usr/local/var/log/php-fpm.log
。如果不修改该值,运行php-fpm的时候会提示log文件输出路径不存在的错误。
安装mysql
安装
brew install mysql
常用命令
mysql.server start #启动mysql服务mysql.server stop #关闭mysql服务
配置
在终端运行mysql_secure_installation
脚本,该脚本会一步步提示你设置一系列安全性相关的参数,包括:设置root密码
,关闭匿名访问
,不允许root用户远程访问
,移除test数据库
。当然运行该脚本前记得先启动mysql服务。 测试nginx服务
在之前nginx配置文件default.conf中设置的root
项对应的文件夹下创建测试文件index.php:
启动nginx服务,sudo nginx
;
sudo nginx -s reload
启动php服务,sudo php-fpm
; 在浏览器地址栏中输入localhost:8080
,如果配置正确地话,应该能看到PHP相关信息的页面。 参考资料
-
- Chen Shan的博文:
- 英文资料:
- D.H.Q的博文:
server { listen 80; server_name localhost; index index.html index.htm index.php; #root /Users/diego/work/; # 该项要修改为你准备存放相关网页的路径 root /Users/diego/work/activity; #location / { # index index.php; # autoindex on; #} location ~ \.(html|jpg|png|gif|ico|js|css|mp4|eot|svg|ttf|woff|mp3|json|woff2|pom|jar)$ { add_header Cache-Control no-store; root /Users/diego/work/activity/static; access_log /Users/diego/work/activity/static.log; index index.html; } location / { try_files $uri index.php?$args; }#proxy the php scripts to php-fpm #location ~ \.php$ { # include /usr/local/etc/nginx/fastcgi.conf; # fastcgi_intercept_errors on; # fastcgi_pass 127.0.0.1:9000; #} location ~ \.php$ { include fastcgi.conf; include fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param CI_ENV DEVELOPMENT; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; }}
Cannot find autoconf. Please check your autoconf installation and the $PHP_AUTOCONF environment variable. Then, rerun this script.
运行/usr/local/webserver/php/bin/phpize时出现:Configuring for:PHP Api Version: 20041225Zend Module Api No: 20060613Zend Extension Api No: 220060519Cannot find autoconf. Please check your autoconf installation and the$PHP_AUTOCONF environment variable. Then, rerun this script.根据网上的解决办法是:# cd /usr/src# wget http://ftp.gnu.org/gnu/m4/m4-1.4.9.tar.gz# tar -zvxf m4-1.4.9.tar.gz# cd m4-1.4.9/# ./configure && make && make install# cd ../# wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.62.tar.gz# tar -zvxf autoconf-2.62.tar.gz# cd autoconf-2.62/# ./configure && make && make install更简单的办法# yum install m4# yum install autoconf
如何安装 Composer
安装前请务必确保已经正确安装了 。打开命令行窗口并执行
php -v
查看是否正确输出版本号。
打开命令行并执行下列命令安装最新版本的 Composer (以下指令摘自 ,请前往查看最新的安装指令):
php -r "readfile('https://getcomposer.org/installer');" > composer-setup.phpphp composer-setup.phpphp -r "unlink('composer-setup.php');"
执行第一条命令下载下来的 composer-setup.php
脚本将简单的检测 php.ini
中的参数设置,如果某些参数未正确设置则会给出警告;然后下载最新版本的 composer.phar
文件到当前目录。
上述 3 条命令的作用依次是:
- 下载安装脚本(
composer-setup.php
)到当前目录。 - 执行安装过程。
- 删除安装脚本 --
composer-setup.php
。
然后把composer.phar移动到环境下让其变成可执行[root@localhost opt]# mv composer.phar /usr/local/bin/composer[root@localhost opt]# composer -VComposer version 1.0-dev (8775c948956c9e0e0a5fd723cd84c94b3ea3d7e9) 2015-07-01 09:29:53
composer 安装
'; echo '还传了一个参数'; echo print_r($arg),''; }//魔术方法__callStaticpublic static function __callStatic($method,$arg){ echo '你想调用我不存在的',$method,'静态方法'; echo '还传了一个参数'; echo print_r($arg),''; }}$li=new human();$li->say(1,2,3);/*调用一个未定义的方法Fatal error: Call to undefined method human::say() in D:\wamp\www\php\59.php on line 8*/$li->t('a','b');/* __call是调用不可见(不存在或无权限)的方法时,自动调用 $lisi->say(1,2,3);-----没有say()方法----> __call('say',array(1,2,3))运行 */ human::cry('痛哭','鬼哭','号哭');/* __callStatic 是调用不可见的静态方法时,自动调用. Human::cry('a','b','c')----没有cry方法---> Human::__callStatic('cry',array('a','b','c')); */ ?>
user}, current pwd:{$this->pwd}\n"; }}$a = new Account();echo $a;echo PHP_EOL;print_r($a);var_dump($a);
输出
current user:1, current pwd:2Account Object( [user] => 1 [pwd] => 2)object(Account)#1 (2) { ["user"]=> int(1) ["pwd"]=> int(2)}
interface
interface employee { public function working() ;}class teacher implements employee{ public function working() { echo 'teaching'; echo PHP_EOL; }}class coder implements employee{ public function working() { echo 'coding'; echo PHP_EOL; }}function doprint(employee $i) { $i->working();}$a = new teacher();$b = new coder();doprint($a);doprint($b);
继承
class employee { protected function working() { echo 'emplyee working'; echo PHP_EOL; }}class teacher extends employee { public function working() { echo 'teaching'; echo PHP_EOL; }}class coder extends employee { public function working() { echo 'coding'; echo PHP_EOL; }}function doprint($obj) { if(get_class($obj) == 'employee') { echo 'Error'; echo PHP_EOL; } else { $obj->working(); }}doprint(new employee);doprint(new teacher);doprint(new coder);
PHP 中对象的赋值默认是引用赋值。 基本类型是传值赋值
?phpclass teacher { public $name = "tc"; public function working() { echo 'teaching'; echo PHP_EOL; }}$a = new teacher();$b = $a;$b->name = "TC";var_dump($a);var_dump($b);$c = "abc";$d = $c;$d = "bcd";var_dump($c);var_dump($d);$e = "cde";$f = &$e;//引用$f = "def";var_dump($e);var_dump($f);
output
➜ phpTest php assign.phpobject(teacher)#1 (1) { ["name"]=> string(2) "TC"}object(teacher)#1 (1) { ["name"]=> string(2) "TC"}string(3) "abc"string(3) "bcd"string(3) "def"string(3) "def"
file_exist 文件是否存在
class_exist 类是否存在
ge't_class 获取对象的类名
get_class_methods 获取类的方法Array
get_class_vars 获取类的成员变量(属性)(public only)
is_callable/method_exist 函数是否可以调用
get_parent_class 获取父类
is_subclass_of 判断某个对象是否是某个类的子类
class_implements 某个对象实现的接口的数组
call_user_func/call_user_func_array 函数调用
PHP array和别的语言不一样。
PHP数组的key可以为int,也可以为string,引申出下面的问题。
'as', 2 => '22',);var_dump($a[0]);var_dump($a[2]);var_dump($a['2']);exit;?>
结果:$a[0]未定义,$a[2] 与 $a['2']相同。
'as', '2' => '22',);var_dump($a[0]);var_dump($a[2]);var_dump($a['2']);exit;
结果:$a[0]未定义,$a[2] 与 $a['2']相同。
问题:string作为key,然后输出是string还是int。
'as', '2' => '22',);foreach($a as $k=>$v) { if($k === 1) { echo 'int'; }}exit;
结果:输出int。
问题:现在可以得出结论说php array会自动把数字字符串的key转成int?请看下面的例子。
参考:
'a', '2' => '22', '2147483647' => '32 max', '2147483648' => '32 max + 1', '9223372036854775807' => '64 max', '9223372036854775808' => '64 max + 1', 9223372036854775809 => '64 max + 2',);foreach($a as $k=>$v) { var_dump($k); echo ' '; var_dump($v);}exit;
在64位的机器上输出:
string(4) "asdf" string(1) "a"int(2) string(2) "22"int(2147483647) string(6) "32 max"int(2147483648) string(10) "32 max + 1"int(9223372036854775807) string(6) "64 max"string(19) "9223372036854775808" string(10) "64 max + 1"int(-9223372036854775808) string(10) "64 max + 2"
结论:php的int取值范围与系统有关,在int的有效范围内,php array会把数字字符串的key转成int;当key超过int范围时,不再转换。
但是php用json_encode方法时候,会遇到问题。
因为:
PHP支持两种数组,一种是只保存"值"(value)的索引数组(indexed array),另一种是保存"名值对"(name/value)的关联数组(associative array)。
由于javascript不支持关联数组,所以json_encode()只将索引数组(indexed array)转为数组格式,而将关联数组(associative array)转为对象格式。
比如,现在有一个索引数组
$arr = Array('one', 'two', 'three'); echo json_encode($arr);
结果为:
["one","two","three"]
如果将它改为关联数组:
$arr = Array('1'=>'one', '2'=>'two', '3'=>'three'); echo json_encode($arr);
结果就变了:
{"1":"one","2":"two","3":"three"}
浏览器使用x-www-form-urlencoded 方式发送数据额的时候,数据都是key=value$key=value 这种方式 详见http://www.cnblogs.com/diegodu/p/5481225.html
CI客户端可以直接使用$this->input->post('some_data');来获取数据
例如
POST /sendNote/testPost HTTP/1.1Host: 10.211.55.3Content-Type: application/x-www-form-urlencodedCache-Control: no-cachePostman-Token: 110094e2-8307-20ef-1146-5a7ed5be3dbename=zhangsan&pwd=123456
服务器端可以这样接收:
public function testPost() { // 1. get user list $name= $this->input->post('name'); $pwd= $this->input->post('pwd'); echo "$name\t"; echo "$pwd"; return ; }