Shi Zhuolin's Blog - PHP
type: channel
link: https://www.shizhuolin.com/tag/PHP/
items: configuring the fastcgi extension for iis 6.0
items: 在Netbeans中集成Composer管理PHP项目依赖
items: 在Yaf中使用Zf2的配置和服务管理器
items: 设置内存GC提高IIS+PHP运行稳定性
items: zend2数据层代码示例
items: PHP实现RGB,HSL,HSV色彩空间转换
items: 用PHP+GD扩展实现图像高斯模糊处理

configuring the fastcgi extension for iis 6.0
type: item
date: 2015-01-26T02:27:00+00:00
description: 转载: http://www.iis.net/learn/application-frameworks/install-and-configure-php-on-iis/configuring-the-fastcgi-extension-for-iis-60IntroductionFrom its first version, Internet Information Services (IIS) has supported Common Gateway Interface (CGI), which is a standards-based protocol that allows information servers, such as IIS, to interface with external applications. FastCGI was introduced to address the scalability shortcomings of CGI.This article describes the shortcomings of earlier versions of CGI and defines the need for the FastCGI extension for IIS 6.0. This article also describes the configuration settings for the FastCGI extension.CGI, ISAPI, and FastCGI in IIS 6.0 and IIS 5.1CGICGI is a protocol that allows information servers to interface with external applications. Because HTTP is stateless, any requests that are made over HTTP create a new instance of the external application in a new operating system process.Within the new process, the stdin handle is remapped so that it receives request data from the client, the stdout handle is remapped so that it writes response data to the client, and the command line and operating system environment variables are set to provide other server and request information to the CGI process.The disadvantage with CGI on IIS is the relatively expensive process creation on Windows operating systems. Every HTTP request creates a new process, performs the work inside the CGI application, and shuts down the process. On operating systems with light-weight process creation, performance is bound by the work that is completed inside the CGI application. On operating systems where process creation is expensive, such as Windows, performance of the CGI application is bound by spinning up the new process. This is the reason why CGI has performed well on a Unix-based platform, but has not been recommended for IIS.ISAPIDespite the disadvantage of CGI on Windows, IIS is capable of keeping up with, and often surpassing, the performance of …

在Netbeans中集成Composer管理PHP项目依赖
type: item
date: 2014-05-30T06:09:00+00:00
description: 相信很多PHP开发人员都碰到开发过程中需要共用多个php类库的问题，传统的做法是把这些类库放到项目中的独立文件夹，创建新项目就复制一份共用类库到此文件夹以做到代码重用，但这么做容易造成多个项目的共用类库版本不同步.而且每次复制也很麻烦,在团队多人开发或公司多团队配合时维护类库工作往往很繁琐，在java中这个问题是通过maven解决.maven中的依赖仓库设置可以让当前项目自动依赖其他项目类库代码.并且同步更新公用类库. php中现在有composer同样可以做到这点.composer可以在php项目中实现类似Maven功能.composer并不是一个完整的PHP项目管理工具,它没有自动化任务功能,但其解决了代码依赖和自动加载.本文分几个部分讲解如何在NetBeans中集成Composer并且管理PHP代码依赖.其也适用命令行Composer. Composer的官网地址是 https://getcomposer.org/在NetBeans中集成Composer构建Composer依赖管理项目设置自动加载导入依赖库导入私有依赖库构建可以被Composer导入的类库一. 在NetBeans中集成Composer准备工作: 我使用的是NetBeans IDE 7.4版和PHP 5.4,操作系统是Windows7 64位. 当然你使用最新的NetBeans 8.0或其他IDE也可以. 步骤都差不多. 注意在NetBeans执行Composer命令时在IDE底部输出窗口可以看到具体被执行的Composer命令,其可以作为你在命令行中使用Composer的参考. 这里就不讲解如何安装NetBeans和PHP了. 不过要注意的是NetBeans最好不要比我的版本低,而且php也要求php5.3.2以上. 这是使用Composer的最低要求.Composer集成NetBeans步骤:确保PHP安装目录已经被加载到操作系统PATH环境变量中.从 https://getcomposer.org/composer.phar 下载Composer.phar文件,将其放到PHP安装目录(就是php.exe所在目录).可选(命令行调用): 在PHP安装目录创建 composer.bat 文件,内容为@php "%~dp0composer.phar" %*注意:在linux中你需要用bash命令作为替代在NetBeans的tools - options - php - general 界面中设置PHP解释器.类似以下效果: 在NetBeans的Tools - options - php - composer 界面中设置composer路径,类似以下效果:注意:其中的联系信息和供应商改为你自己的信息.在composer使用过程中可能会提示需要svn,git,curl,openssl等支持,这个可以在具体使用时根据提示安装对应软件或php库二. 构建Composer依赖管理项目这里只介绍使用netbeans创建composer依赖管理php项目的方法. 完全手工命令行创建过程也差不多，具体需要的命令可以查看netbeans执行时的output窗口.使用netbeans创建php项目.在项目中应用composer初始化composer.其会出现一个composer.json文件，此文件就是composer的配置文件（就如同maven的pom.xml，只是功能没有那么强大）这里有必要解释composer.json的各项内容:name: 这个是当前项目名称, 其格式为 “厂商名/项目名”description: 项目描述authors: 作者信息, 具体字段可以参考 authorsrequire: 这个就是依赖库设置，等同于maven的仓库依赖设置将项目设置为web站点项目(这里只是用其做示例，实际使用中根据自己的情况可以选择)a. 在项目根目录建立public文件夹，此文件夹作为web根目录，避免暴露compoer或项目其他敏感文件.b. 在public目录创建index.php文件（我们在这里将其作为网站首页示范文件）c. 在composer.json中增加"type" : "project" 配置，增加 "license" : "proprietary" 配置. 在这里我们把其配置为项目而不是库，这样在依赖加载此项目时才可以加载所有项目文件.证书设置为私有（想来web网站大部分代码都不是开源的吧!）.现在看起来是这个样子: 在项目中安装composer代码操作后根目录会出现vendor文件夹，其内包含了所有的composer代码或composer下载的依赖库.三. 设置自动加载composer支持自动加载代码，可以自动加载类(psr-0,psr-4)或指定ph…

在Yaf中使用Zf2的配置和服务管理器
type: item
date: 2014-04-05T11:23:00+00:00
description: 测试条件: I3 380M + 4G + Windows7 + iis7 + PHP5.4(fastcgi) + Zend2.3网站设置: 使用默认的模块和控制器,配置config和module缓存. 不连接任何服务和数据库.为避免带宽不足清空view测试软件: Jmeter 20并发用户.测试机和被测试机是不同的电脑，它们之间用100M5类线直连在测试结果中,平均响应时间需要0.637秒,每秒处理30个请求.这个数据比zf1低一半. 同一台机zf1可以达到每秒60多个请求我看到这个测试结果后有点想放弃zf2,可是在开发灵活和便捷性上zf2确实要比zf1要好得多. 分析发现,在zf2中路由，派遣和服务注册，模块注册拖累了整个速度. 以前做项目用到过yaf,发现yaf性能挺好的,于是计划用yaf代替zf2的mvc模块.一. 在yaf项目中加载zf2类库首先你得有一个能正常运行的yaf项目.在这个基础上改动以增加zf2支持.可以参考yaf官方教程做一个yaf的基本架构站点. 这里假设你已按照官方教程架设好yaf站点1. 在yaf项目中使用composeryaf官网示范中默认没有zf2的类加载器，考虑到今后还要加载其它的类库代码，这里使用composer加载zf2依赖. 要在yaf项目中引用composer需要对yaf项目的/public/index.php和/conf/application.ini做少量改动.<?php /** * This makes our life easier when dealing with paths. Everything is relative * to the application root now. */ chdir(dirname(__DIR__)); // Decline static file requests back to the PHP built-in webserver if (php_sapi_name() === 'cli-server' && is_file(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH))) { return false; } // Setup autoloading require 'init_autoloader.php'; // Define path to application directory define("APP_PATH", dirname(__DIR__)); // Create application, bootstrap, and run $app = new Yaf_Application(APP_PATH . "/conf/application.ini"); $app->bootstrap() ->run();改动后的文件和yaf默认文件主要的区别:要增加chdir(dirname(__DIR__)). 目的是让zf2能正常读取配置文件require 'init_autoloader.php'; 这个文件是在ZendSkeletonApplication.zip中复制出来的，目的是引用composer, zf2类库就要通过这个文件加载进来.$app->bootstrap() 必须要有引导器，因为后面要在bootstrap里面加载zf2配置和服务因为yaf默认会禁用spl加载器，这会造成无法加载非yaf前缀命名的类.所以我们还需要更改yaf运行配置.在/conf/application.ini中设置 application.system.use_spl_autoload = true[product] application.directory = APP_PATH "/application/" application.dispatcher.catchException = true application.system.use_spl_autoload = true总结一下，你需要更改 index.php,application.ini增加init_autoloader.php文件，哦!别忘记了编辑composer.json在其中增加zf2依赖配置. 我这里用的是zf2.3. 然后更新composer依赖. 等待composer依赖更新完成后测试项目，看看在yaf项目中是否可以用zf2的类库,这里应该可以引用，如果还是不行就请下载本文后面提供的完整代码.<?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/Z…

设置内存GC提高IIS+PHP运行稳定性
type: item
date: 2014-03-03T07:37:00+00:00
description: IIS配置php提供web服务. 短期访问正常,长时间高压力访问容易崩溃.表现为IIS提示500错误，php-cgi.exe崩溃. 此时在php日志中看不到任何异常，但windows事件日志记录下了php-cgi.exe应用程序错误. 其原因和php内存管理有关.有以下改善方法1. 服务器配置足够物理内存.根据任务管理器界面的物理内存数据，保留更多的空闲物理内存给php-cgi.exe使用. 避免总内存占用超过物理内存.2. 给php-cgi.exe配置足够内存.php内存回收机制决定了达到一半的内存占用时就会运行gc. 频繁的gc造成php崩溃(windows版php的bug);根据实际情况可以改大些. 最好超过实际占用值的两倍以上(任务管理器可以查看php-cgi进程得知实际占用值) memory_limit = 128M程序中如下代码，效果和更改php.ini相同.ini_set('memory_limit','128M');3. fastcgi配置请求超过一定数量（例如1000） 就重启进程. MaxInstances=64 #根据内存和CPU情况配置最大php-cgi.exe进程数. 不要服务器压力过大. InstanceMaxRequests=1000 #每处理1000个请求则重启实例. EnvironmentVars=PHP_FCGI_MAX_REQUESTS:1000 #同上如果64/1000还不行，可以配置更少4.减少请求处理内存占用和处理时长.优化PHP代码，提高程序性能和减少内存占用。比如使用php完成采集任务时避免一次采集过多内容（那样会占用大量的内存和单次cpu处理时间）.5. 可以考虑在php处理过程中关闭gc.虽然关闭gc会造成php内存占用增大，但可以避免频繁运行gc造成php-cgi.exe崩溃.gc_collect_cycles(); gc_disable(); ....php业务代码. gc_enable();以上方法可以极大的改善windows版php的运行稳定性. 总结就是以下几点:不要让PHP服务器满负荷运行.尽可能减少PHP引擎的内存回收次数（通过优化代码降低内存占用或关闭gc实现）

zend2数据层代码示例
type: item
date: 2014-02-28T14:32:00+00:00
description: zend2数据层配置和代码示范(带一对多关系)表 admin, log,数据模型代码和工厂类,配置,控制器在模块Admin的调用示范db.sqlCREATE TABLE `admin` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自动编号', `username` varchar(64) NOT NULL COMMENT '用户名', `password` varchar(40) NOT NULL COMMENT '登陆密码', `disabled` tinyint(1) NOT NULL COMMENT '禁用状态', `name` varchar(64) NOT NULL COMMENT '姓名', `title` varchar(64) NOT NULL COMMENT '职位', `phone` varchar(64) NOT NULL COMMENT '联系电话', `email` varchar(320) NOT NULL COMMENT '邮件地址', `address` varchar(255) NOT NULL COMMENT '联系地址', `description` text NOT NULL COMMENT '其他记录', `addtime` bigint(20) NOT NULL COMMENT '增加时间', `uptime` bigint(20) NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `username_UNIQUE` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='管理员数据表'; CREATE TABLE `adminlog` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自动编号', `admin` int(11) NOT NULL COMMENT '管理员', `content` text NOT NULL COMMENT '内容', `time` bigint(20) NOT NULL COMMENT '时间', PRIMARY KEY (`id`), KEY `fk_adminlog_admin_idx` (`admin`), CONSTRAINT `fk_adminlog_admin` FOREIGN KEY (`admin`) REFERENCES `admin` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=220 DEFAULT CHARSET=utf8 COMMENT='管理日志';return array( 'service_manager' => array( 'factories' => array( 'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory', ), ), );编辑 "/config/application.config.php" 注册数据库工厂服务return array( 'db' => array( 'driver' => 'pdo', 'platform' => 'Mysql', 'pdodriver' => 'mysql', 'options' => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8\'') ), );编辑 "/config/autoload/global.php" 配置数据库参数return array( 'db' => array( 'hostname' => '服务器', 'dbname' => '数据库名', 'username' => '账号', 'password' => '密码', ), );编辑 "/config/autoload/local.php" 配置数据库连接信息<?php namespace Admin; use Zend\Db\ResultSet\ResultSet; use Zend\Db\TableGateway\TableGateway; use Zend\ModuleManager\Feature\ServiceProviderInterface; class Module implements ServiceProviderInterface { public func…

PHP实现RGB,HSL,HSV色彩空间转换
type: item
date: 2014-02-24T09:55:00+00:00
description: <?php /** * HSL色彩空间描述 * HSL.php * @author shizhuolin */ class HSL { /** * 色相 0-360 * @var float */ protected $_hue; /** * 饱和度 0-1 * @var float */ protected $_saturation; /** * 亮度 0-1 * @var float */ protected $_lightness; /** * 构造HSL色彩空间描述 * @param float $hue * @param float $saturation * @param float $lightness */ public function __construct($hue=0, $saturation=0, $lightness=0) { $this->_hue = $hue; $this->_saturation = $saturation; $this->_lightness = $lightness; } /** * 获取色相 * @return float */ public function getHue() { return $this->_hue; } /** * 获取饱和度 * @return float */ public function getSaturation() { return $this->_saturation; } /** * 获取亮度 * @return float */ public function getLightness() { return $this->_lightness; } /** * 获取RGB形式色彩空间描述 * @return RGB */ public function toRGB() { $h = $this->getHue(); $s = $this->getSaturation(); $l = $this->getLightness(); if ($s == 0) { require_once 'RGB.php'; return new RGB($l, $l, $l); } $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - ($l * $s); $p = 2 * $l - $q; $hk = $h / 360; $tR = $hk + (1 / 3); $tG = $hk; $tB = $hk - (1 / 3); $tR = $this->getTC($tR); $tG = $this->getTC($tG); $tB = $this->getTC($tB); $tR = $this->getColorC($tR, $p, $q); $tG = $this->getColorC($tG, $p, $q); $tB = $this->getColorC($tB, $p, $q); require_once 'RGB.php'; return new RGB($tR, $tG, $tB); } private function getColorC($tc, $p, $q) { if ($tc < (1 / 6)) { return $p + (($q - $p) * 6 * $tc ); } else if ((1 / 6) <= $tc && $tc < 0.5) { return $q; } else if (0.5 <= $tc && $tc < (2 / 3)) { return $p + (($q - $p) * 6 * (2 / 3 - $tc) ); } else { return $p; } } private function getTC($c) { if ($c < 0) $c++; if ($c > 1) $c--; return $c; } /** * 获取 array形式HSL色彩描述 * @return array */ public function toArray() { return array( 'hue' => $this->getHue(), 'saturation' => $this->getSaturation(), 'lightness' => $this->getLightness() ); } }<?php /** * HSV色彩空间描述 * HSV.php * @author shizhuolin */ class HSV { /** * 色相 0-260 * @var float */ protected $_hue; /** * 饱和度 0-1 * @va…

用PHP+GD扩展实现图像高斯模糊处理
type: item
date: 2014-02-24T09:50:00+00:00
description: 很久以前写的代码了，现在才想起贴上来. 稍微更改并结合人脸识别可以实现自动模糊人物的脸部.<?php require_once 'RGB.php'; //这里请看另一个 "PHP实现色彩空间转换" /** * 图像信息处理 * @author shizhuolin */ class Image { /** * 位图资源 * @var resource */ protected $_image; /** * 使用指定文件构造图像操作实例 * @param string $filename */ public function __construct($filename=null) { if ($filename) $this->open($filename); } /** * 读取指定文件明的图像 * @param string $filename * @return Image */ public function open($filename) { $handle = fopen($filename, "rb"); $contents = stream_get_contents($handle); fclose($handle); $image = imagecreatefromstring($contents); $width = imagesx($image); $height = imagesy($image); $truecolorimage = imagecreatetruecolor($width, $height); imagefilledrectangle($truecolorimage, 0, 0, $width, $height, 0xFFFFFF); imagecopyresampled($truecolorimage, $image, 0, 0, 0, 0, $width, $height, $width, $height); imagedestroy($image); $this->setImage($truecolorimage); return $this; } /** * 读取指定资源的图像 * @param resource $image * @return Image */ public function load($image) { $width = imagesx($image); $height = imagesy($image); $truecolorimage = imagecreatetruecolor($width, $height); imagefilledrectangle($truecolorimage, 0, 0, $width, $height, 0xFFFFFF); imagecopyresampled($truecolorimage, $image, 0, 0, 0, 0, $width, $height, $width, $height); if ($this->getImage()) { imagedestroy($this->getImage()); } $this->setImage($truecolorimage); return $this; } /** * 设置内部图像资源描述符 * @param resource $image */ protected function setImage($image) { $this->_image = $image; } /** * 获取内部操作图像资源 * @return resource */ public function getImage() { return $this->_image; } /** * 获取图像宽度 * @return int */ public function getWidth() { return imagesx($this->getImage()); } /** * 获取图像高度 * @return int */ public function getHeight() { return imagesy($this->getImage()); } /** * 获取指定坐标像素颜色 * @param type $x * @param type $y * @return type */ public function getColorAt($x, $y) { $rgb = imageColorAt($this->getImage(), $x, $y); $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0…