❶ 如何在Windows下配置搭建php环境
一、安装Apache,配置成功一个普通网站服务器
运行下载好的“apache_2.0.55-win32-x86-no_ssl.msi”,出现如下界面:
❷ 如何安装运行PHP网站
搭建PHP本地环境前言
【本地环境就是你的网站还没有上线,但是想在自己电脑看一下网站搭建后的效果。你在自己电脑做了一个可以看效果的环境。也就是测试环境。】
目前80%以上的网站都是使用xunruicms模版(PHP语言编写的),所以这里只教大家建立PHP本地环境搭建。
新手做网站,还要上线,输入域名可以访问很新奇,但得先看这篇"搭建PHP本地环境并运行xunruicms网站",有了这个基础再看下一篇"网站上线"会容易得多。PHP本地环境搭建就是让你熟悉网站上线的基本功,免得你正式上线手忙脚乱一堆事情,一会儿就放弃了。我也是一步步来的,我尽量写得很细,让大家跟着我操作就可以。
xunruicms建站步骤主要分为三步:①搭建PHP环境,②建立数据库,③安装xunruicms网站
PHP环境搭建
PHP环境搭建使用工具(大学里常用的工具):
WAMPserver
XAMPP
这两个工具任选一个就可以了。这两个工具都是Windows系统下的安装包,linux环境无法使用,里面集成了APACH, MYSQL, PHPADMIN不需要自己一个个安装然后配置。安装包都是exe文件,基本都是一键安装,很简单。我使用的是WAMPserver.
在官网下载 我下载的是3.1.4版本的,这一版本很好,里面很多配置都不需要自己重新配。
下载安装
下载好后直接双击打开
80端口被Apache正常使用,没有被占用。
配置数据库
点击"W"标志,点击"PHPMYADMIN
❸ PHP项目案例分析的前言
学习语言的目的是为了开发项目,很多初学者对于学习技术没有问题,但要真正开发项目,就会感到迷茫和手足无措。而对于即将毕业的学生来说,提交的毕业设计又会让他们感到焦头烂额。
为了帮助读者解决这些问题,引导读者学有所用,特编写了本书,内容涉及PHP开发的主流开发技术,并以最简单通俗的方式向读者介绍如何开发Web项目。相信通过本书的学习,读者会在PHP项目开发的道路上积累更多的实战经验,掌握项目开发的方法。同时,也为正在忙于毕业设计的同学提供了一条捷径。
如果读者在学习的过程中遇到问题,可以通过QQ、论坛等方式与我们联系,我们会力争排除读者在PHP学习过程中遇到的各种障碍。
本书内容
本书分为8章,其中包括6个实用项目和2个毕业设计。实用项目包括图书信息管理系统、俊羽会议管理系统、梦幻网络日记、企业网站系统、明日网上书店和问鼎办公自动化系统的设计;毕业设计包括图书馆管理系统和电子商务网站的设计。
本书特色
* 技术丰富:本书从实际应用的角度出发,运用最简洁、最实用的技术开发最流行的项目。如PHP操作MySQL数据库、Smarty模板、PDO和ADODB数据库抽象层等技术。
* 横向扩展:本书属于PHP系列图书的一部分,在经过了基础、范例和典型模块等内容的学习后,以此来检验读者的学习成果,体会Web项目开发的过程,积累实战经验。
* 讲解到位:本书对每个项目中最有价值的部分进行了剖析,以达到画龙点睛的目的。
* 赠送项目源代码和毕业设计论文:书中所有项目均提供有源代码,用户在开发中可以快速借鉴或应用,并且提供了两篇毕业设计论文,以供参考。
* 提供多节视频录像:本书提供了多节的项目开发视频录像,读者可以边看边学,快速提高。
本书配套资源
本书提供了内容丰富的配套资源,包括自学视频、源程序、素材,以及模块库、案例库、题库、素材库等多项辅助内容,读者朋友可以通过如下方式获取。
第1种方式:
(1)登录清华大学出版社的网站,在网页右上角的搜索文本框中输入本书书名(注意区分大小写和留出空格),或者输入本书关键字,或者输入本书ISBN号(注意去掉ISBN号间隔线“-”),单击“搜索”按钮。
(2)找到本书后单击超链接,在该书的网页下侧单击“网络资源”超链接,即可下载。
第2种方式:
访问本书的新浪微博PHPbook,找到配套资源的链接地址进行下载。
本书约定
* 项目使用方法
用户在学习本书过程中,可以从配套资源中复制程序,去掉其只读属性。有些项目需要使用相应的数据库或第三方资源,此类程序在使用前需要进行相应配置,详细使用方式可参考本书的配套资源使用说明书。此外,如果用户直接将本书内容用于商业用途,由此产生的不良后果由用户自己承担。
* 部分项目只给出关键代码
由于篇幅限制,书中有些模块只给出了关键代码,完整代码可参见配套资源项目程序。
读者人群
本书非常适合以下人员阅读:
* 从事PHP编程行业的开发人员
* 有一定语言基础,想进一步提高技能的人员
* 大中专院校的老师和学生
* 即将走上工作岗位的大学毕业生
* 相关培训机构的老师和学员
* PHP编程爱好者
❹ 基于php的在线考试系统 引言怎么写
管理系统
明确的,我知道设计的
❺ PhpStorm软件求提供一款中文免费版,谢谢!
《PhpStorm 2020.1中文破解版》网络网盘资源免费下载:
链接: https://pan..com/s/1GTg54RahK6cGscMTr0fudg
PhpStorm 2020.1是由JetBrains公司研发的一款功能丰富的PHP集成开发环境,是PhpStorm编程软件系列的最新版本,深厚世界各地PHP程序员的喜欢,很多工程师都用它来开发和部署网站。该软件拥有强大的智能编码辅助功能,包含动态错误检查、零配置调试、扩展的HTML、代码重构等等。
❻ php 框架 怎么使用回调函数
前言
最近在开发一个PHP系统,为了提高系统的扩展性,我想在系统中加入类似Javascript的事件处理机制,例如:我想在一篇新闻被添加以后,我想记录一下日志,用类似Javascript的代码,应该是这样写的:
function fnCallBack( $news )
{
//将$news的信息记录到日志中
writeLog( $news->getTitle().' has been added successfully!');
}
$newsEventManager->addEventListener( 'add' , fnCallBack );
其中,fnCallBack函数是回调函数,addEventListener表示监听newsEventManager的add事件。当一篇news被add以后,系统就会调用fnCallBack函数,从而完成writeLog的动作。
但是,PHP中的函数传递方法和Javascript有很大的不同。在Javascript中,函数也是对象,它可以很方便的当作参数传递,但是PHP不行。
$newsEventManager->addEventListener( 'add' , fnCallBack );
上面这行代码中的fnCallBack,看上去好像是那个函数的句柄,但实质上它是一个字符串,并不是我们所要的函数。
为了实现我们的事件模型,有必要研究一下PHP的回调函数的实现方法。
全局函数的回调
这里的全局函数的意思,是直接使用function定义的函数,它不包含在任何对象或类之中。请看下面的例子
示例代码
function fnCallBack( $msg1 , $msg2 )
{
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( $fnName , $params );
代码说明:
这里使用了PHP内置的函数call_user_func_array来进行调用。call_user_func_array有两个参数,第1个参数是一个字符串,表示要调用的函数名,第2个参数是一个数组,表示参数列表,按照顺序依次会传递给要调用的函数。
效果如下:
类的静态方法的回调
如果我们要回调的方法,是一个类的静态方法,那怎么办呢?我们依然可以利用PHP内置的call_user_func_array方法来进行调用,请看示例:
示例代码:
class MyClass
{
public static function fnCallBack( $msg1 , $msg2 )
{
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$className = 'MyClass';
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( array( $className , $fnName ) , $params );
代码说明:
这段代码和第1种方法的代码很相似,我们将类名(MyClass)也作为call_user_func_array的第1个参数传递进去,就可以实现类的静态方法的回调了。注意,这时call_user_func_array的第1个参数是一个数组了,数组的第1个元素是类名,第二个元素是要调用的函数名
运行结果:
(其实和第1种方法的结果是一样的 ^_^ )
继续研究
如果我用这种方法调用一个类的非静态方法(也就是把static去掉),会出现什么结果呢?请看下面代码
class MyClass
{
public function fnCallBack( $msg1 , $msg2 )
{
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$className = 'MyClass';
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( array( $className , $fnName ) , $params );
运行结果
和前面的结果还是一样的。。。
现在我为这个类添加一点属性,并在方法中引用
class MyClass
{
private $name = 'abc';
public function fnCallBack( $msg1 , $msg2 )
{
echo 'object name:'.$this->name;
echo "<br />\n";
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$className = 'MyClass';
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( array( $className , $fnName ) , $params );
运行结果
出现解析错误,提示$this没有在对象环境下出现,说明这个方法不能用类来调用,而是要用对象来调用。那我们就修改一下代码,创建一个对象:
class MyClass
{
public function fnCallBack( $msg1 , $msg2 )
{
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$myobj = new MyClass();
$className = 'myobj';
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
call_user_func_array( array( $className , $fnName ) , $params );
运行结果:
提示call_user_func_array的第1个参数非法,也就是说,调用失败。看来我们不能用call_user_func_array方法来回调一个对象的方法了,那么如何实现对象方法的回调的?
对象的方法的回调
我先用最原始的字符串形式的调用方法尝试了一下,如下所示:
class MyClass
{
private $name = 'abc';
public function fnCallBack( $msg1 = 'default msg1' , $msg2 = 'default msg2' )
{
echo 'object name:'.$this->name;
echo "<br />\n";
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$myobj = new MyClass();
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
$myobj->$fnName();
成功了,输出结果
调用是成功了,不过如何把参数params传给这个方法呢,如果把params直接传进去,那么它会作为1个参数,怎么把params拆开来传进去呢?
查了下PHP手册,找到了create_function函数,这个方法可以用字符串来创建一个匿名函数,好,有思路了,可以创建一个匿名的函数,在这个匿名函数中,调用我们的回调函数,并把参数传进去。
我先手动创建一个匿名函数anonymous,在这个函数中,用前面试出来的方法调用回调函数,如下所示:
class MyClass
{
private $name = 'abc';
public function fnCallBack( $msg1 = 'default msg1' , $msg2 = 'default msg2' )
{
echo 'object name:'.$this->name;
echo "<br />\n";
echo 'msg1:'.$msg1;
echo "<br />\n";
echo 'msg2:'.$msg2;
}
}
$myobj = new MyClass();
$fnName = "fnCallBack";
$params = array( 'hello' , 'world' );
function anonymous()
{
global $myobj;
global $fnName;
global $params;
$myobj->$fnName( $params[0] , $params[1] );
}
anonymous();
成功了,可以看到,对象的属性name也输出来了
然后,我用create_function来创建这个匿名函数,同时,代码中的params[0],params[1]应该是动态生成的,代码如下:
$strParams = '';
$strCode = 'global $myobj;global $fnName;global $params;$myobj->$fnName(';
for ( $i = 0 ; $i < count( $params ) ; $i ++ )
{
$strParams .= ( '$params['.$i.']' );
if ( $i != count( $params )-1 )
{
$strParams .= ',';
}
}
$strCode = $strCode.$strParams.");";
$anonymous = create_function( '' , $strCode);
$anonymous();
这段代码可以定义一个匿名函数,并保存在$anonymous变量中,最后调用这个$anonymous,实现了方法的回调,如图
PHP事件模型(观察者模式)的实现思路
至此,PHP中的3种常见的函数类型(全局函数,类静态函数,对象的方法)都可以回调了,可以实现文章一开始说的事件模型了 :)
事件模型模仿Firefox的Javascript实现,有3个方法,分别是
addEventListener:注册一个事件上的响应回调函数
removeEventListener:删除一个事件上的响应回调函数
fire:触发一个事件,也就是循环调用所有响应这个事件的回调函数
不过,由于第2、第3种方法需要传递上下文(也就是类名和对象名),所以addEventListener和removeEventListener应该有3个参数,我是这样设计的:
function addEventListener( $evtName , $handler , $scope = null )
第1个参数表示事件名,字符串类型
第2个参数表示回调函数名,字符串类型
第3个参数$scope是上下文环境,一共有3种类型,null表示传入的handler函数是一个全局函数,字符串类型表示传入的handler函数是scope类的静态函数,对象类型表示传入的scope是一个对象,handler函数是对象的一个方法。
function fire( $evtName , $params = null )
这个方法内,会读取出所有响应evtName的handler,然后判断它对应的scope,如果是null,则用本文第1种方法回调,如果是字符串,则用本文第2种方法回调,如果是对象,则用本文第3种方法回调。这样,一个PHP的事件模型就可以实现了,而且可以将回调函数放在某个对象中。
❼ Android和PHP开发最佳实践的图书目录
前言第一篇 准备篇第1章学前必读 11.1移动互联网时代的来临 11.2为何选择Android和PHP 21.3如何学习Android和PHP 31.3.1如何学习Android 31.3.2如何学习PHP 41.3.3同时学好Android和PHP 41.4小结 5第2章Android开发准备 62.1Android背景知识 62.2Android系统框架 82.3Android应用框架 112.3.1活动(Activity) 122.3.2消息(Intent) 142.3.3视图(View) 162.3.4任务(Task) 172.4Android系统四大组件 192.4.1活动(Activity) 202.4.2服务(Service) 212.4.3广播接收器(Broadcast Receiver) 232.4.4内容提供者(Content Provider) 242.5Android上下文 252.5.1界面上下文(Activity Context) 252.5.2应用上下文(Application Context) 272.6Android数据存储 282.6.1应用配置(Shared Preferences) 282.6.2 本地文件(Files) 292.6.3数据库(SQLite) 302.7Android应用界面 312.7.1控件属性 312.7.2布局(Layout) 332.7.3事件(Event) 372.7.4菜单(Menu) 392.7.5主题(Theme) 412.7.6对话框(Dialog) 422.8Android图形界面 432.8.1画笔(Paint) 432.8.2画布(Canvas) 442.8.3 基础几何图形 462.8.4常见图形变换 472.9Android动画效果 502.9.1逐帧动画(Frame Animation) 502.9.2补间动画(Tween Animation) 512.10Android开发环境 522.10.1开发环境的搭建 532.10.2首个Android项目 582.10.3使用DDMS调试工具 632.11小结 64第3章PHP开发准备 653.1PHP开发基础 653.1.1PHP语言简介 653.1.2PHP语法简介 663.1.3PHP开发起步 683.1.4PHP面向对象编程 753.1.5PHP的会话 783.2PHP开发环境 803.2.1开发环境的搭建 803.2.2安装配置Xampp 813.2.3管理Apache 833.2.4管理MySQL 843.3使用JSON通信 873.4常用PHP开发框架 883.5认识Smarty模板引擎 903.6开发框架简介 933.6.1框架的特点和优势 943.6.2框架的基础目录结构 943.6.3框架MVC思路讲解 973.6.4框架MVC实例分析 993.7小结 108第二篇实战篇第4章实例产品设计 1094.1为何选择微博 1094.2开发前的准备 1104.2.1选择开发模式 1104.2.2了解项目策划 1114.2.3了解原型设计 1124.3功能模块设计 1124.4应用界面设计 1144.5应用架构设计 1154.6通信协议定义 1164.7数据库结构设计 1184.8小结 120第5章程序架构设计 1215.1服务端程序架构设计 1215.1.1基础框架设计 1225.1.2调试框架设计 1275.1.3核心类库设计 1305.1.4服务端的MVC与SOA 1365.2客户端程序架构设计 1365.2.1基础框架设计 1375.2.2核心类包设计 1385.2.3Android应用的MVC 1425.3客户端界面架构设计 1425.3.1界面框架设计 1435.3.2主要界面设计 1445.4小结 146第6章服务端开发 1476.1开发入门 1476.1.1接口程序开发 1476.1.2调试框架开发 1516.1.3生成接口文档 1556.2验证接口 1566.2.1用户登录接口 1566.2.2用户登出接口 1606.3用户接口 1626.3.1新建用户接口 1626.3.2更新用户信息接口 1646.3.3查看用户信息接口 1656.3.4添加粉丝接口 1676.3.5删除粉丝接口 1716.4微博接口 1726.4.1发表微博接口 1726.4.2查看微博接口 1746.4.3微博列表接口 1766.5评论接口 1806.5.1发表评论接口 1806.5.2评论列表接口 1826.6图片接口 1846.6.1用户头像接口 1856.6.2头像列表接口 1886.7通知接口 1896.8Web版接口 1926.8.1Web版UI界面(jQuery Mobile) 1936.8.2Web版地图接口 1956.9小结 196第7章客户端开发 1987.1开发入门 1987.1.1开发思路梳理 1987.1.2掌握应用配置文件 2007.1.3常规程序开发与调试 2117.2界面布局和行为控制 2217.2.1使用Layout布局 2217.2.2使用Merge整合界面 2247.2.3使用Event控制用户行为 2267.2.4使用Intent控制界面切换 2287.3网络通信模块 2317.3.1使用HttpClient进行网络通信 2317.3.2支持CMWAP网络接入方式 2377.3.3使用JSON库为消息解码 2407.3.4使用Toast消息提示 2457.4异步任务模块 2477.4.1进程和线程 2477.4.2任务创建Thread 2497.4.3任务处理Handler 2557.4.4使用异步任务AsyncTask 2577.5全局功能模块 2597.5.1全局UI基类 2597.5.2全局Menu菜单 2647.5.3全局Dialog窗口 2657.5.4使用Service获取通知 2667.5.5使用Notification显示通知 2707.6用户登录界面 2737.6.1界面程序逻辑 2737.6.2使用TextView 2737.6.3使用EditText 2747.6.4使用Button 2767.6.5使用Shape和Selector 2777.6.6使用CheckBox 2797.6.7使用SharedPreference 2807.7微博列表界面 2817.7.1界面程序逻辑 2817.7.2使用ListView 2867.7.3使用ImageView 2907.7.4使用draw9patch 2927.7.5异步获取远程图片 2947.7.6使用SdCard缓存图片 2977.7.7使用SQLite缓存数据 3007.8我的微博列表 3037.8.1界面程序逻辑 3037.8.2使用ScrollView 3097.8.3使用自定义微博列表 3107.9微博文章界面 3137.9.1界面程序逻辑 3137.9.2界面布局进阶(综合使用UI控件) 3197.9.3发表评论功能实现 3227.9.4发表微博功能实现 3267.10用户配置界面 3287.10.1界面程序逻辑 3287.10.2使用自定义选项列表 3337.10.3修改签名功能实现 3347.10.4更换头像功能实现 3347.11网页界面开发 3407.11.1界面程序逻辑 3407.11.2使用WebView 3417.11.3使用ProgressDialog 3437.11.4使用WebView的重写和回调 3467.11.5网页地图实例分析 3487.12小结 349第三篇优化篇第8章性能分析 3518.1关于性能测试 3518.1.1服务端压力测试 3528.1.2客户端性能测试 3598.2瓶颈 3648.2.1服务端瓶颈分析 3658.2.2客户端瓶颈分析 3668.3优化的思路 3668.4小结 367第9章 服务端优化 3689.1优化PHP程序 3689.1.1优化PHP代码 3689.1.2优化Session机制 3719.1.3使用缓存中间件 3739.1.4使用APC加速 3769.2优化数据传输 3779.2.1优化JSON协议 3779.2.2使用gzip压缩 3799.3其他优化 3809.3.1服务器优化 3809.3.2数据库优化 3839.3.3网络优化 3869.4小结 386第10章客户端优化 38710.1优化Android程序 38710.1.1优化Java代码 38710.1.2异步获取数据 39110.1.3文件资源缓存 39110.1.4数据库缓存 39210.2避免内存泄露 39210.2.1Android内存管理 39210.2.2如何判断内存泄露 39310.2.3常见内存泄露的处理 39510.3优化Android UI 39610.3.1模板代码优化 39610.3.2关于布局优化 39710.3.3使用Hierarchy Viewer工具 40210.4其他优化 40310.4.1优化图片 40310.4.2优化APK包 40310.4.3使用keytool和jarsigner签名 40410.4.4使用zipalign优化 40710.5小结 408第四篇进阶篇第11章Android特色功能开发 40911.1使用Google Map API 40911.2使用LBS功能 41411.3使用传感器 41911.4使用摄像头 42211.5多媒体开发 43111.6语音识别 43911.7小结 441第12章Android NDK开发 44212.1NDK开发基础 44212.1.1使用NDK的原因 44212.1.2使用NDK调用C或C++ 44312.1.3Android . mk 和 Application . mk 44512.2NDK开发入门 44812.2.1开发环境搭建 44812.2.2首个NDK项目 44912.3小结 456第13章Android游戏开发 45713.1手游开发基础 45713.1.1手游开发思路解析 45713.1.2贪食蛇和飞船游戏实例 46213.1.3认识Android游戏引擎 46413.1.4使用OpenGL和OpenGL ES 46613.1.5使用RenderScript 47213.2手游开发进阶 47413.2.1认识Cocos2d-x 47513.2.2架设Cocos2d-x开发环境 47513.2.3首个Cocos2d-x项目 47513.2.4认识Unity 3D 48713.3小结 489附录AHush Framework框架实例源码部署 490附录B微博应用实例源码部署 495
❽ php和go语言哪个好
前言
最近工作中遇到的一个场景,php项目中需要使用一个第三方的功能,而恰好有一个用Golang写好的类库。那么问题就来了,要如何实现不同语言之间的通信呢?下面就来一起看看吧。
常规的方案
1、 用Golang写一个http/TCP服务,php通过http/TCP与Golang通信
2、将Golang经过较多封装,做为php扩展。
3、PHP通过系统命令,调取Golang的可执行文件
存在的问题
1、http请求,网络I/O将会消耗大量时间
2、需要封装大量代码
3、PHP每调取一次Golang程序,就需要一次初始化,时间消耗很多
优化目标
1、Golang程序只初始化一次(因为初始化很耗时)
2、所有请求不需要走网络
3、尽量不大量修改代码
解决方案
1、简单的Golang封装,将第三方类库编译生成为一个可执行文件
2、PHP与Golang通过双向管道通信
使用双向管道通信优势
1:只需要对原有Golang类库进行很少的封装
2:性能最佳 (IPC通信是进程间通信的最佳途径)
3:不需要走网络请求,节约大量时间
4:程序只需初始化一次,并一直保持在内存中
具体实现步骤
1:类库中的原始调取demo
package main
import (
"fmt"
"github.com/yanyiwu/gojieba"
"strings"
)
func main() {
x := gojieba.NewJieba()
defer x.Free()
s := "小明硕士毕业于中国科学院计算所,后在日本京都大学深造"
words := x.CutForSearch(s, true)
fmt.Println(strings.Join(words, "/"))
}
保存文件为main.go,就可以运行
2:调整后代码为:
package main
import (
"bufio"
"fmt"
"github.com/yanyiwu/gojieba"
"io"
"os"
"strings"
)
func main() {
x := gojieba.NewJieba(
"/data/tmp/jiebaDict/jieba.dict.utf8",
"/data/tmp/jiebaDict/hmm_model.utf8",
"/data/tmp/jiebaDict/user.dict.utf8"
)
defer x.Free()
inputReader := bufio.NewReader(os.Stdin)
for {
s, err := inputReader.ReadString('\n')
if err != nil && err == io.EOF {
break
}
s = strings.TrimSpace(s)
if s != "" {
words := x.CutForSearch(s, true)
fmt.Println(strings.Join(words, " "))
} else {
fmt.Println("get empty \n")
}
}
}
只需要简单的几行调整,即可实现:从标准输入接收字符串,经过分词再输出
测试:
# go build test
# ./test
# //等待用户输入,输入”这是一个测试“
# 这是 一个 测试 //程序
3:使用cat与Golang通信做简单测试
//准备一个title.txt,每行是一句文本
# cat title.txt | ./test
正常输出,表示cat已经可以和Golang正常交互了
4:PHP与Golang通信
以上所示的cat与Golang通信,使用的是单向管道。即:只能从cat向Golang传入数据,Golang输出的数据并没有传回给cat,而是直接输出到屏幕。但文中的需求是:php与Golang通信。即php要传数据给Golang,同时Golang也必须把执行结果返回给php。因此,需要引入双向管道。
在PHP中管道的使用:popen("/path/test") ,具体就不展开说了,因为此方法解决不了文中的问题。
双向管道:
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w")
);
$handle = proc_open(
'/webroot/go/src/test/test',
$descriptorspec,
$pipes
);
fwrite($pipes['0'], "这是一个测试文本\n");
echo fgets($pipes[1]);
解释:使用proc_open打开一个进程,调用Golang程序。同时返回一个双向管道pipes数组,php向$pipe['0']中写数据,从$pipe['1']中读数据。
好吧,也许你已经发现,我是标题档,这里重点要讲的并不只是PHP与Golang如何通信。而是在介绍一种方法: 通过双向管道让任意语言通信。(所有语言都会实现管道相关内容)
测试:
通过对比测试,计算出各个流程占用的时间。下面提到的title.txt文件,包含100万行文本,每行文本是从b2b平台取的商品标题
1: 整体流程耗时
time cat title.txt | ./test > /dev/null
耗时:14.819秒,消耗时间包含:
进程cat读出文本
通过管道将数据传入Golang
Golang处理数据,将结果返回到屏幕
2:计算分词函数耗时。方案:去除分词函数的调取,即:注释掉Golang源代码中的调取分词那行的代码
time cat title.txt | ./test > /dev/null
耗时:1.817秒时间,消耗时间包含:
进程cat读出文本
通过管道将数据传入Golang
Golang处理数据,将结果返回到屏幕
分词耗时 = (第一步耗时) - (以上命令所耗时)
分词耗时 : 14.819 - 1.817 = 13.002秒
3:测试cat进程与Golang进程之间通信所占时间
time cat title.txt > /dev/null
耗时:0.015秒,消耗时间包含:
进程cat读出文本
通过管道将数据传入Golang
go处理数据,将结果返回到屏幕
管道通信耗时:(第二步耗时) - (第三步耗时)
管道通信耗时: 1.817 - 0.015 = 1.802秒
4:PHP与Golang通信的时间消耗
编写简单的php文件:
<?php
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w")
);
$handle = proc_open(
'/webroot/go/src/test/test',
$descriptorspec,
$pipes
);
$fp = fopen("title.txt", "rb");
while (!feof($fp)) {
fwrite($pipes['0'], trim(fgets($fp))."\n");
echo fgets($pipes[1]);
}
fclose($pipes['0']);
fclose($pipes['1']);
proc_close($handle);
流程与上面基本一致,读出title.txt内容,通过双向管道传入Golang进程分词后,再返回给php (比上面的测试多一步:数据再通过管道返回)
time php popen.php > /dev/null
耗时:24.037秒,消耗时间包含:
进程PHP读出文本
通过管道将数据传入Golang
Golang处理数据
Golang将返回结果再写入管道,PHP通过管道接收数据
将结果返回到屏幕
结论:
1 :整个分词过程中的耗时分布
使用cat控制逻辑耗时: 14.819 秒
使用PHP控制逻辑耗时: 24.037 秒(比cat多一次管道通信)
单向管道通信耗时: 1.8 秒
Golang中的分词函数耗时: 13.002 秒
2:分词函数的性能: 单进程,100万商品标题分词,耗时13秒
以上时间只包括分词时间,不包括词典载入时间。但在本方案中,词典只载入一次,所以载入词典时间可以忽略(1秒左右)
3:PHP比cat慢 (这结论有点多余了,呵呵)
语言层面慢: (24.037 - 1.8 - 14.819) / 14.819 = 50%
单进程对比测试的话,应该不会有哪个语言比cat更快。
相关问题:
1:以上Golang源码中写的是一个循环,也就是会一直从管道中读数据。那么存在一个问题:是不是php进程结束后,Golang的进程还会一直存在?
管道机制自身可解决此问题。管道提供两个接口:读、写。当写进程结束或者意外挂掉时,读进程也会报错,以上Golang源代码中的err逻辑就会执行,Golang进程结束。
但如果PHP进程没有结束,只是暂时没有数据传入,此时Golang进程会一直等待。直到php结束后,Golang进程才会自动结束。
2:能否多个php进程并行读写同一个管道,Golang进程同时为其服务?
不可以。管道是单向的,如果多个进程同时向管道中写,那Golang的返回值就会错乱。
可以多开几个Golang进程实现,每个php进程对应一个Golang进程。
最后,上面都是瞎扯的。如果你了解管道、双向管道,上面的解释对你基本没啥用。但如果你不了解管道,调试上面的代码没问题,但稍有修改就有可能掉坑里。
❾ php网站中英文切换
多语言网站解决方案 php
前言:
多语言网站开发,重点的还是在解决语言之间的问题。
那如何解决这个问题呢?大概就分三步走:
1.页面多语言
2.数据库多语言
3.用户访问语言统一
1.页面多语言
需要考虑的问题:
A.用户登陆时候,自动识别字符,调用不同的语言包?
B.用户切换不同语言时候,调用不同的语言包?
C.增加多语言后的目录结构?
页面多语言也就是外观的多语言化,这里可以采用静态的语言包的方式。
设计时候就应该包括language的目录,针对不同语言有独立的子目录。
如英文language/en ,简体中文language/gb,繁体中文language/b5 (可以扩展其他语言)
每个目录下就包含了对每个页面的语言版本。选择语言版本时候就可以调用相应版本的语言包。
具体做法:
0.利用js语言,识别浏览器语言,在调用不同的语言包.
1.language/en/global.ln是针对英文版的全局语言包。
2.global.ln 内容为:
$title = "English webstie";
$charset = "UTF-8";
3.index.php调用:
<?php
require_once()
?>;
<html>;
<head>;
<title>;$title<title>;
<meta http-equiv="content-type" content="text/html;charset=$charset">;
</head>;
<body>;</body>;
</html>;
这样通过扩展就可以实现页面的多语言化.
2.数据库多语言
这个考虑的问题:
A.后台录入数据的多语言化?
B.用户在不同版本下,提交的内容,如何保存?
C.提供三种语言包,还是提供英文和简体,简体通过转化提供繁体?
数据库多语言就是达到多语言在数据库里面的统一。就需要采用utf-8统一编码。
无论什么语言的文字,都统一使用utf-8来存放到数据库里面。采用表字段来表识
属于什么语言版本的文字。
具体:
A.对于后台添加的问题:
1.后台添加时候,就需要多语言化的录入。先建立一个以utf-8编码的数据库,录入英文/简体,简体在通过转化为繁体,
再以utf-8编码方式存于数据库中。
2.建立以utf-8为编码的表结构,importlanguage标识属于什么语言版本
但在某个版本下,就搜索属于这个版本的文字来显示。其他文字不显示。
DROP TABLE IF EXISTS `zz_importer`;
CREATE TABLE IF NOT EXISTS `zz_importer` (
`importID` int(11) NOT NULL auto_increment,
`importTime` date NOT NULL default '0000-00-00',
`improtfile` varchar(100) NOT NULL default '',
`importlanguage` varchar(100) NOT NULL default ''
PRIMARY KEY (`importID`)
) ENGINE=MyISAM DEFAULT CHARSET=uft-8;
3.简体转化的繁体。
利用php的iconv.此过程对于linux/unix有效,对于windows无效。
iconv("GB2312","BIG5",$text);
4.因为,charset = "utf-8",数据就都是以utf-8编码方式存在,
添加数据时候,要分别用en/gb/big5来标识语言版本.
INSERT INTO `zz_importer` VALUES (,'', '', 'en');
INSERT INTO `zz_importer` VALUES (,'', '', 'gb');
INSERT INTO `zz_importer` VALUES (,'', '', 'big5');
B.对于用户添加的问题:
1.假设下简体中文下.用户因为页面头为UTF-8.则用户浏览器会以utf-8编码
方式浏览页面。
2.添加的数据库本身以utf-8方式存在。
3.添加数据时候,要分别用gb来标识语言版本
INSERT INTO `zz_importer` VALUES (,'', '', 'gb');
C.对于简体和繁体是单独提供还是转化问题
单独提供 - 比较符合多语言的标准,灵活性大,对ISP没有特别的要求。
转化提供 - 提交速度会受影响,同时要ISP提供iconv的函数支持。
3.用户访问语言统一
A.假设用户简体中文版时候:
<meta http-equiv="content-type" content="text/html;charset=UTF-8">;
所有语言版本都是这样。
B.调用language/gb的语言包。
C.搜索数据库有语言字段为gb的数据,并显示
D.当用户提交信息,参照上面数据库多语言的B问题。
❿ 如何将php里面的数组内容进行分页显示出来
1、前言
分页显示是一种非常常见的浏览和显示大量数据的方法,属于web编程中最常处理的事件之一。对于web编程的老手来说,编写这种代码实在是和呼吸一样自然,但是对于初学者来说,常常对这个问题摸不着头绪,因此特地撰写此文对这个问题进行详细的讲解,力求让看完这篇文章的朋友在看完以后对于分页显示的原理和实现方法有所了解。本文适合初学者阅读,所有示例代码均使用php编写。
2、原理
所谓分页显示,也就是将数据库中的结果集人为的分成一段一段的来显示,这里需要两个初始的参数:
每页多少条记录($PageSize)?
当前是第几页($CurrentPageID)?
现在只要再给我一个结果集,我就可以显示某段特定的结果出来。
至于其他的参数,比如:上一页($PreviousPageID)、下一页($NextPageID)、总页数($numPages)等等,都可以根据前边这几个东西得到。
以mysql数据库为例,如果要从表内截取某段内容,sql语句可以用:select * from table limit offset, rows。看看下面一组sql语句,尝试一下发现其中的规率。
前10条记录:select * from table limit 0,10
第11至20条记录:select * from table limit 10,10
第21至30条记录:select * from table limit 20,10
……
这一组sql语句其实就是当$PageSize=10的时候取表内每一页数据的sql语句,我们可以总结出这样一个模板:
select * from table limit ($CurrentPageID - 1) * $PageSize, $PageSize
拿这个模板代入对应的值和上边那一组sql语句对照一下看看是不是那么回事。搞定了最重要的如何获取数据的问题以后,剩下的就仅仅是传递参数,构造合适的sql语句然后使用php从数据库内获取数据并显示了。以下我将用具体代码加以说明。
3、简单代码
请详细阅读以下代码,自己调试运行一次,最好把它修改一次,加上自己的功能,比如搜索等等。
<?php
// 建立数据库连接
$link = mysql_connect("localhost", "mysql_user", "mysql_password")
or die("Could not connect: " . mysql_error());
// 获取当前页数
if( isset($_GET['page']) ){
$page = intval( $_GET['page'] );
}
else{
$page = 1;
}
// 每页数量
$PageSize = 10;
// 获取总数据量
$sql = "select count(*) as amount from table";
$result = mysql_query($sql);
$row = mysql_fetch_row($result);
$amount = $row['amount'];
// 记算总共有多少页
if( $amount ){
if( $amount < $page_size ) //如果总数据量小于$PageSize,那么只有一页
if( $amount % $page_size ){ //取总数据量除以每页数的余数
$page_count = (int)($amount / $page_size) + 1; //如果有余数,则页数等于总数据量除以每页数的结果取整再加一
}else{
$page_count = $amount / $page_size; //如果没有余数,则页数等于总数据量除以每页数的结果
}
}
else{
$page_count = 0;
}
// 翻页链接
$page_string = '';
if( $page == 1 ){
$page_string .= '第一页|上一页|';
}
else{
$page_string .= '<a href="/?page=1>";第一页</a>|<a href="/?page='."($page-1).'>上一页</a>|';
}
if( ($page == $page_count) || ($page_count == 0) ){
$page_string .= '下一页|尾页';
}
else{
$page_string .= '<a href="/?page='."($page+1).'>下一页</a>|<a href="/?page='."$page_count.'>尾页</a>';
}
// 获取数据,以二维数组格式返回结果
if( $amount ){
$sql = "select * from table order by id desc limit ". ($page-1)*$page_size .", $page_size";
$result = mysql_query($sql);
while ( $row = mysql_fetch_row($result) ){
$rowset[] = $row;
}
}else{
$rowset = array();
}
// 没有包含显示结果的代码,那不在讨论范围,只要用foreach就可以很简单的用得到的二维数组来显示结果
?>
4、OO风格代码
以下代码中的数据库连接是使用的pear db类进行处理
<?php
// FileName: Pager.class.php
// 分页类,这个类仅仅用于处理数据结构,不负责处理显示的工作
Class Pager
{
var $PageSize; //每页的数量
var $CurrentPageID; //当前的页数
var $NextPageID; //下一页
var $PreviousPageID; //上一页
var $numPages; //总页数
var $numItems; //总记录数
var $isFirstPage; //是否第一页
var $isLastPage; //是否最后一页
var $sql; //sql查询语句
function Pager($option)
{
global $db;
$this->_setOptions($option);
// 总条数
if ( !isset($this->numItems) )
{
$res = $db->query($this->sql);
$this->numItems = $res->numRows();
}
// 总页数
if ( $this->numItems > 0 )
{
if ( $this->numItems < $this->PageSize )
if ( $this->numItems % $this->PageSize )
{
$this->numPages= (int)($this->numItems / $this->PageSize) + 1;
}
else
{
$this->numPages = $this->numItems / $this->PageSize;
}
}
else
{
$this->numPages = 0;
}
switch ( $this->CurrentPageID )
{
case $this->numPages == 1:
$this->isFirstPage = true;
$this->isLastPage = true;
break;
case 1:
$this->isFirstPage = true;
$this->isLastPage = false;
break;
case $this->numPages:
$this->isFirstPage = false;
$this->isLastPage = true;
break;
default:
$this->isFirstPage = false;
$this->isLastPage = false;
}
if ( $this->numPages > 1 )
{
if ( !$this->isLastPage )
if ( !$this->isFirstPage )
}
return true;
}
/***
*
* 返回结果集的数据库连接
* 在结果集比较大的时候可以直接使用这个方法获得数据库连接,然后在类之外遍历,这样开销较小
* 如果结果集不是很大,可以直接使用getPageData的方式获取二维数组格式的结果
* getPageData方法也是调用本方法来获取结果的
*
***/
function getDataLink()
{
if ( $this->numItems )
{
global $db;
$PageID = $this->CurrentPageID;
$from = ($PageID - 1)*$this->PageSize;
$count = $this->PageSize;
$link = $db->limitQuery($this->sql, $from, $count); //使用Pear DB::limitQuery方法保证数据库兼容性
return $link;
}
else
{
return false;
}
}
/***
*
* 以二维数组的格式返回结果集
*
***/
function getPageData()
{
if ( $this->numItems )
{
if ( $res = $this->getDataLink() )
{
if ( $res->numRows() )
{
while ( $row = $res->fetchRow() )
{
$result[] = $row;
}
}
else
{
$result = array();
}
return $result;
}
else
{
return false;
}
}
else
{
return false;
}
}
function _setOptions($option)
{
$allow_options = array(
'PageSize',
'CurrentPageID',
'sql',
'numItems'
);
foreach ( $option as $key => $value )
{
if ( in_array($key, $allow_options) && ($value != null) )
{
$this->$key = $value;
}
}
return true;
}
}
?>
<?php
// FileName: test_pager.php
// 这是一段简单的示例代码,前边省略了使用pear db类建立数据库连接的代码
require "Pager.class.php";
if ( isset($_GET['page']) )
{
$page = (int)$_GET['page'];
}
else
{
$page = 1;
}
$sql = "select * from table order by id";
$pager_option = array(
"sql" => $sql,
"PageSize" => 10,
"CurrentPageID" => $page
);
if ( isset($_GET['numItems']) )
{
$pager_option['numItems'] = (int)$_GET['numItems'];
}
$pager = @new Pager($pager_option);
$data = $pager->getPageData();
if ( $pager->isFirstPage )
{
$turnover = "首页|上一页|";
}
else
{
$turnover = "<a href='?page=1&numItems=".$pager->numItems."'>首页</a>|<a href="/?page=".$pager->PreviousPageID."&numItems=".$pager->numItems."'>上一页</a>|";
}
if ( $pager->isLastPage )
{
$turnover .= "下一页|尾页";
}
else
{
$turnover .= "<a href="/?page=".$pager->NextPageID."&numItems=".$pager->numItems."'>下一页</a>|<a href="/?page=".$pager->numPages."&numItems=".$pager->numItems."'>尾页</a>";
}
?>
需要说明的地方有两个:
这个类仅仅处理数据,并不负责处理显示,因为我觉得将数据的处理和结果的显示都放到一个类里边实在是有些勉强。显示的时候情况和要求多变,不如自己根据类给出的结果处理,更好的方法是根据这个Pager类继承一个自己的子类来显示不同的分页,比如显示用户分页列表可以:
<?php
Class MemberPager extends Pager
{
function showMemberList()
{
global $db;
$data = $this->getPageData();
// 显示结果的代码
// ......
}
}
/// 调用
if ( isset($_GET['page']) )
{
$page = (int)$_GET['page'];
}
else
{
$page = 1;
}
$sql = "select * from members order by id";
$pager_option = array(
"sql" => $sql,
"PageSize" => 10,
"CurrentPageID" => $page
);
if ( isset($_GET['numItems']) )
{
$pager_option['numItems'] = (int)$_GET['numItems'];
}
$pager = @new MemberPager($pager_option);
$pager->showMemberList();
?>
第二个需要说明的地方就是不同数据库的兼容性,在不同的数据库里截获一段结果的写法是不一样的。
mysql: select * from table limit offset, rows
pgsql: select * from table limit m offset n
......
所以要在类里边获取结果的时候需要使用pear db类的limitQuery方法。
ok,写完收功,希望花时间看完这些文字的你不觉得是浪费了时间。
回答者
另外,虚机团上产品团购,超级便宜