用php实现简单的内容采集器

 

发表在 BS架构后台语言 | 标签为 , | 留下评论

undefined reference to `libiconv_open 无法编译PHP libiconv

make时提示:

解决方法:

再检查php,指定 iconv的位置  –with-iconv=/usr/local/libiconv

另一种解决方法为去除iconv模块也能正常编译php,如下:

編輯 Makefile 大約 77 行左右的地方:

在最後加上 -liconv,例如:

再运行make就可以了。

最后一种方法:由tonyty163提供:

 

发表在 操作系统相关 | 标签为 , | 留下评论

Linux环境PHP7.0.2安装过程

去年年底PHP环境出了7.0版本,紧接着各程布署php7,单位的一些平台也基于PHP7开发,今天在布署时发现以前的环境是php5.3,百度了一下成功升级到7.0.2。

以下为分享升级步骤:

下载

建议安装之前先看看安装帮助文件INSTALL

解压安装

01

如果配置错误,需要安装需要的模块,直接yum一并安装依赖库

编译安装

02

配置文件

需要注意的是php7中www.conf这个配置文件配置phpfpm的端口号等信息,如果你修改默认的9000端口号需在这里改,再改nginx的配置

附:服务脚本

在init.d下创建php-fpm服务脚本

然后

保存退出

赋权后通过

03配置opcache

官网地址:http://php.net/opcache

使用下列推荐设置来获得较好的 性能:

你也可以禁用 opcache.save_comments 并且启用 opcache.enable_file_override。 需要提醒的是,在生产环境中使用上述配置之前,必须经过严格测试。 因为上述配置存在一个已知问题,它会引发一些框架和应用的异常, 尤其是在存在文档使用了备注注解的时候。

发表在 应用工具软件 | 标签为 , | 留下评论

基于Redis的轻量级消息队列php-resque

最近的做一个邮件群发的项目,需要用到消息队列。因此开始了我对消息队列选型的漫长路.

为什么选型会纠结呢,直接使用ActiveMQ,RabittMQ,Gearman等流行的消息队列不就可以了吗? 在这个项目中,只有单台服务器,而且我采用了redis来做系统缓存,同时开启了php apc来缓存phalcon model Metadata.如果再开启其他进程,需要很合理的分配各个应用的资源,如果分配不好,极有可能产生浪费,同时还有可能造成应用性能低下.

因此,为了实现项目结构的简单化,同时简化维护,我就打算用Redis来实现,但短信群发过程中,必须要有优先级别的,直接使用Redis的 List显然不是太合适,本着这一打算,我还专门google了一下,发现有人使用zset来模拟FIFO,实现LIST中的lpush,rpop操作。

通过Google发现有一个基于Redis的比较不错的消息队列 Resque https://github.com/resque/resque 而此消息队列则是使用ruby语言实现的.我更不想一个项目中使用多种语言了,幸好,马上又发现了基于resque的PHP实现, php-resque https://github.com/chrisboulton/php-resque

Resque还包括很多其他插件以及其他语言的实现,详细列表请看官方列表 https://github.com/resque/resque/wiki/Alternate-Implementations

php-resque本身并没有包括查看消息队列status的用户界面,但我们可以通过命令行查看,同时由于php-resque的消息队列实现和resque中命名一致,可以安装ruby的web界面来进行查看.

我一直使用的是phpredis扩展. php-resque使用Redis Client是 Credis, https://github.com/colinmollenhour/credis ,而Credis的API完全是基于phpredis来封装的,即API一样,前者是C扩展,后者是PHP实现.

促使我最终决定使用Redis及PHP-Resque的一个最要原因是PHP-Resque内置可同时开启多个进程,对于海量数据下发来说非常必要,同时不需要自己再写代码实现多进程或多线程了.

下面具体介绍一下PHP-Resque的安装与使用.

PHP-Resque安装

1.环境需求

  • PHP 5.3+
  • Redis 2.2+
  • Optional but Recommended: Composer

2.安装Composer

3.安装PHP-Resque

php-resque的队列实现

所有的消息队列都差不多,有生产者,消费者,还有Task Server.只不过名称不同而已.

生产者:接受用户提交信息,组成消息队列中的一个任务,并将其加入消息队列服务中.

消费者:一般为一个守护进程,从消息队列服务器中取出任务,对任务做出相应的处理.PHP-Resque中的消息者为守护进程+Job Class .即由守护进程从消息队列中取出任务,具体的任务中在任务的生产过程中已经指定了由哪个Job Class来做具体的处理.

Task Server: 消息队列服务器,本处指redis服务.

具体实现

下载安装PHP-Resque后,在php-resque/demo目录中,有类似如下几个文件(我修改测试过,和原有目录不太一样了):

生成任务(创建一个Job)

其中第一行为连接redis服务

第二行的数组是任务的内容,可随意编写.通过Resque::enqueue 序列化后加入到消息队列中.

最后一行的第一个参数表示 消息队列的名称(可随意标记,比如 email,log等),第二个参数表示取出任务后,由My_Job这个类来处理此条任务.

同时需要说明的是: 在PHP-Resque中也没有数字标识的优化级,但可以通过消息队列名称来实现优化级,具体下面会讲到.

定义Job Class

从上面的代码中可以看出,这是一个非常简单的PHP类文件, 方法perform是必须的,主要用来处理任务.其他两个方法可有可无,根据你自己的应用环境看是否需要.

Demo目录中的job.php (修改过)

从上面的例子可以看出,如果想在Job Class中读取任务的具体内容,可直接使用 $this->args[‘name’]来进行读取.按上面的例子来说,它将输出 Chris

测试消息队列

(1)创建任务

queue.php代码如下:

此时查看Redis,会发现多了三条数据

注意: “,”逗号前是键名,后面是键值

在开启守护进程以前,请确保PHP_Job存在,PHP_Job为PHP类名,而非PHP文件名. 如果PHP_Job不存在,则此条任务会处理失败.(因为根本不存在处理它的文件)

(2)处理任务

在demo目录中,守护进程是由目录下的resque.php来进行,代码如下:

Job Class需要放到此文件头部引入,当然也可以使用其他方式引入. 上面代码中job.php即是类PHP_Job文件

开启守护进程参数说明:

在上面的代码中,最后一行引入的../bin/resque 其实也是一个php cli程序,代码如下:

从上面的代码可以看出,在命令行启动守护进程时,可以传递一些环境变量.而 ../bin/resque通过getenv函数来获取环境变量.

支持的环境变量有:

========================================================================================================

QUEUE – 這个是必要的,会決定 worker 要執行什麼任務,重要的在前,例如 QUEUE=default,notify,mail,log 。也可以設定為 QUEUE=* 表示執行所有任務。

APP_INCLUDE – 这也可以说是必要的,因為 Resque 的 Job 都是写成PHP类,那 worker 執行的時候當然要把物件的檔案引入進來。可以設成 APP_INCLUDE=require.php 再在 require.php 中引入所有 Job 的 Class 文件即可。

COUNT – 設定 worker 數量,預設是1 COUNT=5 。

REDIS_BACKEND – 設定 Redis 的 ip, port。如果沒設定,預設是連 localhost:6379 。

LOGGING, VERBOSE – 設定 log, VERBOSE=1 即可。

VVERBOSE – 比較詳細的 log, VVERBOSE=1 debug 的時候可以開出來看。

INTERVAL – worker 檢查 queue 的間隔,預設是五秒 INTERVAL=5 。

PIDFILE – 如果你是開單 worker,可以指定 PIDFILE 把 pid 寫入,例如 PIDFILE=/var/run/resque.pid 。

=============================================================================

启动守护进程:

QUEUE=* 表明处理所有的消息队列,此时则没有优化级别.如果需要优化级别,可以按先后顺序列出,如 QUEUE=mail1,mail2,mail3

APP_INCLUDE=require.php 文件中,可以引入其他的一些Job Class或其他辅助类,当然也可以直接在 demo/resque.php中引入

启动守护进程后:

可以看出,已经成功取出任务,并使用PHP_Job处理.然后守护进程一直在运行,等待处理新的任务

此时看一下进程文件:

查看任务的状态

在生成任务的时候,使用$token = Resque::enqueue(‘default’, ‘My_Job’, $args, true); 生成一个任务,第四个参数设置为true,会返回任务的JobID,通过JobID可以查看任务的状态.

在类文件Resque_Job_Status中定义了所有类型任务状态

事件触发接口 暂时没用到,可查看官方文档

本来想把选型,使用,以及整合Phalcon写到一篇文章中,看来太长,还是分开吧.抽空把集成到Phalcon以及消息队列实际应用写一下.

 

参考文档:

http://avnpc.com/pages/run-background-task-by-php-resque

http://blog.hsatac.net/2012/01/php-resque-introduction/

http://kamisama.me/2012/10/12/background-jobs-with-php-and-resque-part-4-managing-worker/

https://github.com/kamisama/Fresque

http://stackoverflow.com/questions/11814445/what-is-the-proper-way-to-setup-and-use-php-resque

发表在 BS架构后台语言, 应用工具软件 | 标签为 , | 2条评论

Meta标签技巧:拦截搜索引擎,阻止网页被收录

今天在整理一个项目时,遇到关于单个网页阻止搜索引擎收录的问题,在网上搜索一翻,现在分享出来,希望对大家有所帮助。

使用<meta>标签拦截或删除网页:在网页的 <head> 部分添加适当的 <meta> 标签。

拦截所有搜索引擎把网页收录:

<meta name=”robots” content=”noindex, nofollow”>

只是拦截百度蜘蛛爬取网页,而允许其他搜索引擎收录:

<meta name=”baiduspider” content=”noindex, nofollow”>

允许搜索引擎收录你的网页,但禁止其追踪外部链接(如:zh.wikipedia.org 为了防止链接泛滥采用了此例):

<meta name=”robots” content=”nofollow”>

允许搜索引擎收录你的网页,但禁止其收录网页上的图片:

<meta name=”robots” content=”noimageindex”>

注:哪一个网页需要拦截或删除,则在那个网页添加<META> 标签,其他页面不会受影响。

<meta> 标签针对的是具体的某个网页,而不是整个网站。

发表在 Web前台开发技术 | 标签为 , | 留下评论

jquery on()方法绑定多个选择器,多个事件

on(events,[selector],[data],fn)

•events:一个或多个用空格分隔的事件类型和可选的命名空间,如”click”或”keydown.myPlugin” 。
•selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代。如果选择器为null或省略,当它到达选定的元素,事件总是触发。
•data:当一个事件被触发时要传递event.data给事件处理函数。
•fn:该事件被触发时执行的函数。 false 值也可以做一个函数的简写,返回false。

这样一个需求,如果用live()方法实现的话 非常简单,容易理解。

jquery在1.7版本后,建议大家用on方法代替之前的bind、live、delegate方法。
那上面一句如果用on的话,怎么写呢?

其实查看live源码就知道,live实际是委托doucment进行事件委派的。

按照这个思路,可以将on方法绑定到document即可。

还有一种情况,on()方法绑定多个事件,可以这样写:

最后,用on()方法绑定多个选择器,多个事件则可以这样写:

 

发表在 Web前台开发技术 | 标签为 , | 留下评论

PhpStorm-2016.1 汉化注册版

JetBrains PhpStorm(智能PHP编辑器) 注册版是一个轻量级且便捷的PHP IDE,其旨在提供用户效率,可深刻理解用户的编码,提供智能代码补全,快速导航以及即时错误检查。尤其是该软件提供智能代码补全,快速导航以及即时错误检查等功能,是众多开发者选择它的主要原因。JetBrains 的所有产品都是非常棒的,如果你是程序员,果断需要用一用!


PhpStorm 的首次出现填补了 PHP 开发智能 IDE 的长期空白,它提供了必不可少的工具,如自动化重构、深层代码分析、联机错误检查和快速修复。基于众多尝试这款突破性 IDE 的开发者的反馈,PhpStorm 关注于更多的智能性、更好的代码质量保证,并支持最新的 PHP 趋势。JetBrains 团队负责人 Alexey Gopachenko 表示:“我们增加了对今天 PHP 开发中经常使用的 PHP 命名空间和封包的支持,大大提高了代码分析能力。此外,此次重要版本发布使得 PHP 调试成为‘轻而易举的工作’,无需任何配置。”

智能PHP编辑器:

-PHP代码补全。
-智能的重复编码检测器。
-PHP重构。
-支持Smarty和PHPDoc。
-支持多语言混合。Java Script 编辑器:
-基于DOM/指定浏览器完成。
-代码导航和用法查找。
-JavaScript 重构。
-JavaScript调试器。

HTML/CSS编辑器:

-支持HTML5。
-支持Zen编码。
-检验和快速修正。
-显示应用的外观。
-提取嵌入样式。

轻量级IDE:

-易于安装。
-可在Windows, Mac OS X, Linux上运行。
-项目配置简单-可在任意地方打开代码开始工作。
-性能优先。

智能的环境:

-可视化PhP单元测试运行期。
-VCS支持SVN, Git, Mercurial等。
-支持FTP和远程文件同步。
-可记录本地修改。
-可视化调试 。
-无需任何配置的调试器。
-支持在PHP,JS,HTML中设置断点。
-观察变量,窗口。
-批量代码分析。
-集成分析器。

PhpStorm-2016.1 汉化注册版 下载地址:

https://pan.baidu.com/s/1c0QBVLu

发表在 应用工具软件 | 标签为 , | 留下评论

PHP7.0 Redis扩展dll下载

PHP7.0.0正式版发布有一段时间了,但是与之对应的扩展组件非常之少,特别是windows上用PHP7搭建开发平台,组件太少肯定是影响开发的。

目前PHP官网的PECL上日常用到的大部分PHP扩展组件都没有适配PHP7的,这源于PHP7的一些新特性与依赖关系和PHP5有很多不同之处,所以很多组件都需要开发者们经过一段时间的开发以适配PHP7。

以下是现在php pcel上的redis组件,目前只有php5.3-php5.6的:

4_1_c7b89caab2474b1

今天特别为大家补充一款PHP7 Redis扩展组件:

php7

注:php7目录下有php7.dll的选择nts版本;有php7ts.dll的选择ts版本。

使用教程:
选择对应版本redis组件解压得到php_redis.dll文件,拷贝到php7的ext目录下,打开php.ini配置文件,增加

重启下webserver或者phpfpm生效。

以下是php7 redis组件在php探针上的显示:

redis

已更新至1512.17,基于PHP7.0.1版本重新编译:

zzstudio_php_redis-7.0-ts-vc14-x64

zzstudio_php_redis-7.0-ts-vc14-x86

zzstudio_php_redis-7.0-nts-vc14-x64

zzstudio_php_redis-7.0-nts-vc14-x86

发表在 应用工具软件 | 标签为 , , | 留下评论

php $_SERVER信息分析整理

php $_SERVER信息分析整理类库

 

发表在 BS架构后台语言 | 标签为 , | 一条评论

考虑到 PHP 5.0~5.6 各版本兼容性的 cURL 文件上传

最近做的一个需求,要通过PHP调用cURL,以multipart/form-data格式上传文件。

不同版本PHP之间cURL的区别

PHP的cURL支持通过给CURL_POSTFIELDS传递关联数组(而不是字符串)来生成multipart/form-data的POST请求。

传统上,PHP的cURL支持通过在数组数据中,使用“@+文件全路径”的语法附加文件,供cURL读取上传。这与命令行直接调用cURL程序的语法是一致的:

但PHP从5.5开始引入了新的CURLFile类用来指向文件。CURLFile类也可以详细定义MIME类型、文件名等可能出现在multipart/form-data数据中的附加信息。PHP推荐使用CURLFile替代旧的@语法:

PHP 5.5另外引入了CURL_SAFE_UPLOAD选项,可以强制PHP的cURL模块拒绝旧的@语法,仅接受CURLFile式的文件。5.5的默认值为false,5.6的默认值为true。

但是坑的一点在于:@语法在5.5就已经被打了deprecated,在5.6中就直接被删除了(会产生 ErorException: The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead)。

对于PHP 5.6+而言,手动设置CURL_SAFE_UPLOAD为false是毫无意义的。根本不是字面意义理解的“设置成false,就能开启旧的unsafe的方式”——旧的方式已经作为废弃语法彻底不存在了。PHP 5.6+ == CURLFile only,不要有任何的幻想。

我的部署环境是5.4(仅@语法),但开发环境是5.6(仅CURLFile)。都没有压在5.5这个两者都支持过渡版本上,结果就是必须写出带有环境判断的两套代码。

现在问题来了……

环境判断:小心魔法数字!

我见过这种环境判断的代码:

我对这种代码的评价只有一个字:

这个判断掉入了典型的魔法数字陷阱。版本号莫名其妙的出现在代码之中,不查半天PHP手册和更新历史,很难明白作者被卡在了哪个功能的变更上。

代码应该回归本源。我们的实际需求其实是:有CURLFile就优先采用,没有再退化到传统@语法。那么代码就来了:

建议明确指定的退化选项

从可靠的角度,推荐指定CURL_SAFE_UPLOAD的值,明确告知php是容忍还是禁止旧的@语法。注意在低版本PHP中CURLOPT_SAFE_UPLOAD常量本身可能不存在,需要判断:

cURL选项设置的顺序

不管是curl_setopt()单发还是curl_setopt_array()批量,cURL的选项总是设置一个生效一个,而设置好的选项立刻就会影响cURL在设置后续选项时的行为。

例如CURLOPT_SAFE_UPLOAD就和CURLOPT_POSTFIELDS的行为有关。如果先设置CURLOPT_POSTFIELDS再设置CURLOPT_SAFE_UPLOAD,那么后者的约束作用就不会生效。因为设置前者时cURL就已经把数据实际的识读处理完毕了!

cURL有那么几个选项存在这种坑,务必小心。还好这种存在“依赖关系”的选项不多,机制也不复杂,简单处理即可。我的方法是先批量设置所有的选项,然后直到curl_exec()的前一刻才用curl_setopt()单发设置CURLOPT_POSTFIELDS

实际上在curl_setopt_array()用的数组中,保证CURLOPT_POSTFIELDS的位置在后边也是可靠的。PHP的关联数组是有顺序保障的,我们也可以假设curl_setopt_array()内部的执行顺序一定是从头到尾按顺序[注A],所以尽可放心。

我的做法只是在代码表现上加个多余的保险,突出强调顺序的重要性防以后手贱。

命名空间

PHP 5.2或以下的版本没有命名空间。代码中用到了空间分隔符\就会引发解析器错误。要照顾PHP 5.2其实容易想,放弃命名空间即可。

要注意的反倒是有命名空间的PHP 5.3+。无论是调用CURLFile还是用class_exists()判断CURLFile的存在性,都推荐写成\CURLFile明确指定顶层空间,防止代码包裹在命名空间内的时候崩掉。

发表在 BS架构后台语言 | 标签为 | 留下评论