首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
183 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
31
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
786
篇与
的结果
2023-08-07
PHP扩展开发(写一个加法的例子)
PHP扩展开发(写一个加法的例子)5.1 您的第一个扩展配置文件才开始,我们先用最快的(不是最标准的)的方式来建立一个代码最少的扩展。在php源码文件夹的ext目录下创建一个新的文件夹,这里我取的名字叫做walu,它往往就是我们扩展的名字。其实这个文件夹可以放在任何一个位置,但是为了我们在后面介绍win32的编译与静态编译,我们还是把它放在php源码的ext目录下。 现在,我们在这个目录下创建一个config.m4文件,并输入以下内容:PHP_ARG_ENABLE(walu,[Whether to enable the "walu" extension], [ enable-walu Enable "walu" extension support]) if test $PHP_WALU != "no"; thenPHP_SUBST(WALU_SHARED_LIBADD) PHP_NEW_EXTENSION(walu, walu.c, $ext_shared)fi上面PHP_ARG_ENABLE函数有三个参数,第一个参数是我们的扩展名(注意不用加引号),第二个参数是当我们运行./configure脚本时显示的内容,最后一个参数则是我们在调用./configure --help时显示的帮助信息。也许有人会问,为什么有的扩展的开启方式是 --enable-extname的形式,有的则是 --with-extname的形式呢?其实两者并没有什么本质的不同,只不过enable多代表不依赖外部库便可以直接编译,而with大多需要依赖于第三方的lib。 现在,我们的扩展并不需要依赖其它的库文件,所以我们直接使用--enable-walu便可以了。在第17章的时候我们将接触通过CFLAGS和LDFLAGS来配置自己的扩展,使其依赖第三方库文件才能被编译成php扩展。如果我们显示运行./configure --enable-walu,那么终端环境便会自动将$PHP_WALU变量设置为yes,而PHP_SUBST函数只不过是php官方对autoconf里的AC_SUBST函数的一层封装。 最后重要的一点是,PHP_NEW_EXTENSION函数声明了这个扩展的名称、需要的源文件名、此扩展的编译形式。如果我们的扩展使用了多个文件,便可以将这多个文件名罗列在函数的参数里,如:PHP_NEW_EXTENSION(sample, sample.c sample2.c sample3.c, $ext_shared)最后的$ext_shared参数用来声明这个扩展不是一个静态模块,而是在php运行时动态加载的。下面,我们来编写实现扩展主逻辑的源文件walu.c://加载config.h,如果配置了的话ifdef HAVE_CONFIG_Hinclude "config.h"endif//加载php头文件include "php.h"define phpext_walu_ptr &walu_module_entry//module entryzend_module_entry walu_module_entry = {if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER,endif"walu", //这个地方是扩展名称,往往我们会在这个地方使用一个宏。 NULL, /* Functions */ NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */if ZEND_MODULE_API_NO >= 20010901"2.1", //这个地方是我们扩展的版本endifSTANDARD_MODULE_PROPERTIES};ifdef COMPILE_DL_WALUZEND_GET_MODULE(walu)endif这就是所有的代码了,不过鉴于我们平时的开发习惯,往往会把这一份代码分成两份,一个.h文件,一个.c文件。上面的代码只是生成了一基本的框架,而没有任何实际的用处。 紧接着,创建一个zend_module_entry结构体,你肯定已经发现了,依据ZEND_MODULE_API_NO 是否大于等于 20010901,这个结构体需要不同的定义格式。20010901大约代表PHP4.2.0版本,所以我们现在的扩展几乎都要包含STANDARD_MODULE_HEADER这个元素了。 其余六个成员我们可以先赋值为NULL,其实看看它们各自后面的注释你就应该大体上了解它们各自是负责哪一方面的工作了。 最后,最底下的代码用来标志我们的这个扩展是一个共享模块。它是干么的呢?我也说不清楚,反正带上就对了,否则扩展会工作不正常。原文解释:这个简短的条件只是在动态加载扩展时使用 Zend 使用的一个引用。不要担心它做了什么或它是如何做的;只要确保它就在附近,否则下一部分将不起作用。标准一些根据我们平时的开发习惯,应该不会把所有代码都写在这一个文件里的,我们需要把上述代码放在两个文件里,一个头文件,一个c文件。//php_walu.hifndef WALU_Hdefine WALU_H//加载config.h,如果配置了的话ifdef HAVE_CONFIG_Hinclude "config.h"endif//加载php头文件include "php.h"define phpext_walu_ptr &walu_module_entryextern zend_module_entry walu_module_entry;endif下面的是c文件//walu.cinclude "php_walu.h"//module entryzend_module_entry walu_module_entry = {if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER,endif"walu", //这个地方是扩展名称,往往我们会在这个地方使用一个宏。 NULL, /* Functions */ NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */if ZEND_MODULE_API_NO >= 20010901"2.1", //这个地方是我们扩展的版本endifSTANDARD_MODULE_PROPERTIES};ifdef COMPILE_DL_WALUZEND_GET_MODULE(walu)endif链接5 你的第一次延期
2023年08月07日
15 阅读
0 评论
0 点赞
2023-08-07
PHP —-MySQL 数据库
PHP —-MySQL 数据库MySQL数据库操作1.创建数据库.在MySQL中应用 create database 语句创建数据库.格式如下:create database db_name;db_name 为数据库名,必须为合法名称.规定如下:a.不能与其他数据库重名.b.名字可以是任意的字母,阿拉伯数字,下划线或者"$"组成.可以使用以上任意的字符开头,但不能是使用单独的数字,哪样会造成与数字混淆.c.名字最长可由64个字符组成(包括表,列和索引),而别名最多可长达256个字符.d.不能使用MySQL关键字作为数据库名称和表名.ps: 执行过程:在创建数据库时,首先连接MySQL服务器,用户名是root,密码也是root,然后编写"create database db_name;" sql语句,数据库创建成功.2.选择数据库.use 语句用于选择一个数据库,使其成为当前默认数据库.格式如下:use db_name;3.删除数据库.删除数据库使用 drop database 语句.格式如下:drop database db_nameps.对于删除数据库的操作应该谨慎使用.一旦删除数据库中的所有结构和数据都将会被删除,没有恢复的可能,除非数据库中有备份.MySQL 数据库表上面将完数据库的操作,下面讲一下数据库中,对表的操作.MySQL 数据库表的操作包括 创建,查看,修改,重命名和删除.1.创建表.创建表使用 create table 语句.格式如下:create [temporary] table [if not exists] 数据表名 [(create_definition,...)][table_options][select_statement]a. temporary ,如果使用该关键字,表示创建一个临时表.b. if not exists ,该关键字用于避免创建表时,表存在时 MySQL报告的错误.c. create_definition,这是表的列表属性部分.MySQL要求在创建表时,表至少要包含一列.create_deifnition 格式如下:col_name type [not null] [default default_value] [auto_increment] [primary key] [reference_definition]col_name:字段名. type:字段类型. not null|null:指出该列是否允许空值.not null 表示不允许空值.default default_value:表示默认值.auto_increament:表示默认值.primary key:表示是否为主键,一个表中只能有一个primary key.如果没有primary key ,而某些应用要求primary key,服务器将返回第一个没有null 列的unique 键作为primary key.d. table_option, 表的一些特性参数.e. select_statement,select语句描述部分,用它可以快速地创建表.2.查看表.对于创建成功的表,使用 show columns 语句或 describe 语句查看指定数据表的表结构.格式如下:show columns 语句:show [full] columns from 数据表名 [from 数据库名]; 或者 show [full] columns from 数据表名.数据库名;describe 语句,describe 可以简写成DESC.describe 数据表名; 或者 describe 数据表名 列名;3.修改表.修改表结构使用 alter table 语句.其中,修改表结构的操作又包括:增加或者删除字段,修改字段名称或者字段类型,设置/取消主键或者外键,设置/取消索引以及修改表的注释等.格式如下:alter [ignore] TABLE 数据表名 alter_spec[,alter_spec]....如果指定参数 ignore,当出现重复行时,则只执行一行,其他重复行将被删除.其中alter_spec 子句定义要修改的内容,格式如下:alter_specification: add [column] create_definition [FIRST | AFTER column_name],//添加新字段 add index [index_name] (index_col_name,....),//添加索引名称 add primary key (index_col_name,...),//添加主键名称 add unique [index_name] (index_col_name,...),//添加唯一的索引 alter [column] col_name {SET DEFAULT literal | DROP DEFAULT},//修改字段名称 change [column] old_col_name create_definition //修改字段类型 modify [column] create_definition,//修改字句定义的字段 drop [column] col_name ,//删除字段名称 drop primary key,//删除主键名称 drop indEX index_name, //删除索引名称 rename [AS] new_tbl_name,//更改表名 table_optionsalter table 语句允许制定多个动作,其动作使用逗号分隔,每个动作表示对表的一个修改.通过alter 修改表列的前提是必须将表中的数据全部删除.4. 重命名表.重命名表使用rename table 语句.格式如下:rename table 数据表名1 to 数据表名2;//rename table 语句可以同时对多个数据表进行重命名,多个表之间以逗号分隔.5. 删除表删除数据表使用语句 drop table .格式如下:drop table 数据表名; 或者 drop table if exists 数据表名; //防止删除不存在的表,导致的报错.删除数据表,将同样导致没有备份的数据无法恢复.ps:在执行create table,alter table和drop table中的任何操作时,首先必须选择数据库,否则将无法对数据表进行操作.MySQL 数据表中的数据下面总结数据表中的数据.如何更好的操作和使用这些数据才是使用MySQL数据库的根本.1.添加(插入)数据.创建完数据库和数据表后,要向表中添加数据.添加数据主要有三种语法方式:a.列出所有新添加数据的所有的值.insert into table_name values(value1,value2,.....);//语句缺点 当列过多的时候,不易明确知道匹配值.b.给出要赋值的列,然后再给出值.insert into table_name (column_name1,column_name2,...) values ( value1,value2,....);//缺点同上c.用col_name =value 的形式给出列和值.insert into table_name set column_name1 = value1 ,column_name2 = value2 , ....;//弥补以上缺点,但导致语句过长.批量添加数据begin 数据的批量添加使用 load data 和MySQLimport 语句实现.load data 通过大量读取本地文件系统上的文件,可以将大量数据添加到数据库中.格式如下:load data local infile "filename.txt" into table table_name;MySQLimport语句实现程序直接从文件读取批量数据.它相当于load data 语句的一个接口.格式如下:%MySQLimport -local table_name filename.txt;MySQLimport可以自动生成一个load data 语句,该语句把filename.txt 文件中的数据装入table_name 表.MySQLimport 将文件名中第一个圆点前的的字符作为新的表名,并且将文件中的数据导入到新表中.如 文件名 com.youfilename.txt. 那么将会将数据导入到表com 中.2.修改数据.修改数据使用update语句.格式如下:update table_name set column_name1=new_Value1,column_name2 =new_value2,... where condition;condition 为条件语句,如user_name='张三'. 必须保证condition条件的准确性,否则将会导致破坏表中的数据.3.删除数据.删除数据使用 delete 语句.格式如下:delete from table_name where condition;psa.删除某条数据时,一般选择该数据的id 作为条件,以避免产生不必要的错误.b.当到删除整个表的数据,因效率问题,不推荐使用delete操作.可以使用truncate 语句,它可以很快的删除表中的所有内容.4.查询数据.从数据库表中查询数据用与操作以及显示,是对数据进行操作比较重要的一环.下面将会作详细的解释.首先,对MySql数据库表进行数据查询用到select 语句.格式如下:select selection_list //要查询的内容,选择查询的列. from table_list //从何表中查询,从何处选择行. where primaryz_constraint //查询时,需要满足的条件. group by grouping_columns //如何对查询结果进行分组. order by sorting_columns //如何对结果进行排序 having secondary_constraint //查询时满足的第二条件. limit count //限定输出的结果.a. select_list 表示要查询的内容.如果要查询表中所有的列,可以用" * "表示.如果查询多列,可以直接输入列名,并使用" , "分隔.b. table_list 从指定的表中查询.既可以从一个表中查询;也可以从多个表中查询,多表查询使用 " ," 分隔,并且在where 字句中使用连接运算符号来确定表与表之间的关系.当使用多表查询的使用,如果表中有相同的字段,为了告诉服务器要显示的那个表中的字段信息,需要在字段前加上表名.格式如下:table_name.columns_name; //表名.字段名.使用 " = "符号将表连接起来,叫做等同连接.比如.tb_student.name = tb_gradeOne.name ;如果不使用等号连接,那么产生的结果将是两个表的笛卡尔积,叫做全连接.c.where 条件语句用于通过相应条件获取对应信息.格式为 columns_name 比较运算符 value.d. group by 实现对查询得到的数据进行划分并加以分组,从而实现分组查询.在查询时,所查询的列必须包含在分组的列中,目的是使查询到的数据没有矛盾.在与avg() 或则sum()函数一起使用时,group by 语句能够发挥最大的作用.e.使用distinct 在结果中去除重复行.f.order by.使用order by 可以对结果进行升序和降序(DESC),在默认情况下,order by 按照升序输出结果.如果要降序可以使用DESC 来实现.当对含有null值的列进行排序时,升序,null值排在最前,降序,null 排在最后.g.like 模糊查询. like 属于较常用的运算符,通过它可以实现模糊查询,他有两种通配符,即"%"和下划线"_"."%"可以实现匹配一个或多个字符,而"_"只匹配一个字符.h. 使用concat 联合多列.使用concat 函数可以联合多个字段,从而构成一个总的字符串.例如把书名与价格合并,并使用as 为字段起一个别名.select id ,concat(bookname,":",price) as bookInfo form tb_mkbook;i.使用limit 限定结果函数.使用limit字句可以对结果的记录条数进行限定,从而控制它输出的行数. 例如:limit 3 --表示显示3条数据.limit 5,10---表示从编号为5的记录开始,往下读10条数据用于显示.j.函数表达式.常用的统计函数有:avg(columns_name);//获取指定列的平均值.count(columns_name);//统计出制定列的非空记录的条数. 加distinct限定关键字,则统计不同值的条数,相同值的被认为为一条记录.count(*),则统计包含空记录的数目.max(columns_name) 或者 min(columns_name);//获取指定字段的最大/最小值.std(columns_name) 或者 stdtev(columns_name);//指定字段的标准背离值.sum(columns_name);//指定字段所有记录的值的和.ps.常见的数据类型有 数字类型,字符串类型,时间和日期类型.详细情况,请参考php相关知料与文档.MySQL 数据库的操作步骤以上对mysql数据库结构层次总结如下,下面介绍对数据库的操作步骤.1.连接到mysql服务器.使用mysql_connect()函数创建与MySQL服务器连接.方法格式如下:<?php $conn = mysql_connect('hostname' , 'username' , ' password ') or die( "数据库服务器连接失败".mysql_error()); //hostname: mysql服务器的主机名或者ip.如果省略端口号,则默认为3306; //username:登陆mysql数据库服务器的名称 //password: mysql服务器的用户密码. //改函数的返回值表示对这个数据库的连接,如果成功,则返回一个资源. if($conn){ //服务器连接成功 } ?>从上可以知道,可以指定非本机的机器名作为数据库服务器,这样就为数据库的异地存储和数据库的的安全隔离提供了保障.外界用户往往通过www服务器的直接访问权限,如果数据库直接放在www服务器上,就会给MySQL数据库带来安全隐患;如果为数据库系统安装防火墙,那么php可以直接通过局域网访问数据库,而局域网的计算机对外部不可见,这样保证了s数据库不受外来攻击.为了方便查询数据库连接错误,可以加上die()函数进行屏蔽的错误处理机制.mysql_error()用于提取错误文本信息,如果没有出错则返回空字符;如果出错,连兰奇上将会显示错误信息.ps.对于用户而言,建议在mysql_connect()前面添加@符号,用于屏蔽错误信息,这样做是为了让用户看到一堆莫名其妙的错误信息.但是对于开发者而言,在调试的过程中,不使用@能让我们快速定位错误信息.2.选择MySQL数据库.使用mysql_select_db()函数选择MySQL数据库服务器上的数据库,并与数据库创建连接.格式如下:mysql_select_db(string 数据库名 [,resource link_identifier]); //string 数据库名:要选择的MySQL数据库名称 //resource link_identifier: MySQL服务器的连接标识.//例子,同上一步. <?php if($conn){ $selected = sql_select_db("db_webBookStore",$conn); if($selected){ //数据库连接成功; } } ?>3.执行sql语句.使用mysql_query()函数执行sql语句.sql语句操作在前面已经讲过,此处不在阐述.主要介绍mysql_query()函数的用法,格式如下:$result = mysql_query(string sql [,resource link_identifier]); //如果sql语句为查询语句,成功则返回结果集合,否则返回false //如果sql语句为插入,删除或更新,成功则返回true,否则返回false. //ps.改函数也可以用于选择数据库,和设置数据库编码格式. //如:mysql_query('user db_database13',$conn); // mysql_query(' set names utf8');提高: mysql_unbuffered_query() ,顾名思义改函数为不缓存结果查询.它仅向服务器发送一条sql查询语句,但不获取和缓存结果的行.它不像mysql_query哪样自动获取并缓存结果集.优点在于,当处理很大的结果集时,会节省客观的内存;另一方面,可以在获取第一行数据后立即对结果集进行操作,而不用等到整个SQL语句都执行完毕.mysql_fetch_array()函数,用于将结果集合返回到数组中.格式为:$array = mysql_fetch_array(resource result [,int result_type]); //resource result:资源类型的参数,要传入的是由mysql_query()返回的资源数据指针. //int result_type:可选项,要传入的整型参数,可以是:mysql_assoc(关联索引),mysql_num(数字索引),mysql_both(同时包含前两者).默认为mysql_both. //注意,本函数返回的字段名区分大小写. mysql_fetch_row()函数,从结果集中获取一行来作为枚举数组.格式为: $array = mysql_fetch_row(resource result); //根据所获取的行数据,生成数组.如果没有更多的行,则返回false. //数组偏移量下标从0开始. //本函数返回的字段名区分大小写. 本函数只能使用数字索引,而mysql_fetch_array()两者都可使用.如:数字索引:$array[0],关联索引:$array[type]; mysql_num_rows()函数,用于获取查询结果集中的记录数.格式为: int mysql_num_rows(resource result); //返回结果集中行的数目.此命令只对select语句有效.要获取其他sql语句的操作所影响的数据集行数目,需要使用mysql_affected_rows()4.数据执行完后,需要关闭结果集,以释放资源.语法如下:mysql_free_result(resource result);如果在网页中要频繁的对数据库进行访问,可以通过创建与服务器数据库持续连接来提高效率.这样就避免了,每次连接服务器请求多带来的长时间请求和较大的资源开销.持续连接数据库使用mysql_pconnect()函数来替换mysql_connect()函数.创建的持续连接,在程序结束前将不会调用mysql_close()来关闭数据库请求.当再次调用mysql_pconnect()去连接数据库的时,服务器将返回已经创建的持续连接的ID号,而不去重新创建数据库连接.5.关闭MySQL服务器.每次使用mysql_connect()和mysql_query(),都会消耗系统资源.在少量用户访问web网站时候问题还不大,但当大量用户连接超过一定的数量,就会造成系统性能的下降,甚至死机.为了避免这种情况,在完成数据库操作后,应调用改函数来关闭与MySQL服务器的连接,以节省系统的资源.格式如下:mysql_close($conn);ps.php中与数据库的连接是非持久连接,系统会自动回收,一般不用设置关闭.但如果一次性返回的结果集比较大,或者网站访问量比较多,则最好使用改函数手动释放.提高:数据库乱码问题,使用mysql_query()函数设置数据库编码. 编码格式建议使用utf-8 .如果使用gbk2312,如果用户没有安装中文编码(如一些美洲,欧洲用户的机器查看中文网站),则在输出时将会导致乱码.utf-8 的使用返回更广,可移植性更高,也更被国际化支持.
2023年08月07日
14 阅读
0 评论
0 点赞
2023-08-07
php+mysql下,对网站架构方面的一些认识
php+mysql下,对网站架构方面的一些认识三层网站架构目前网站架构一般分成 负载均衡层、WEB层和数据库层负载均衡层-- LVS,WEB层--使用了nginxweb服务器,数据库层--我们使用了db集群方案。网站概况浏览量(PV) 独立访客(UV) 访问次数(VV) 独立IP 发帖量 注册会员数 跳出率 平均在线时长今日 80,973 37,999 42,573 27,979 624 140 72.27% 00:07:56昨日 179,250 74,584 88,986 54,021 1,400 285 77.48% 00:10:00历史平均 154,020 60,927 71,924 47,883 1,936 201 78.24% 00:10:00历史最高 238,993 94,647 110,552 72,692 6,602 468 89.04% 00:11:021 代码提交系统这是在代码进入生产环境前的必须要经历的。在测试服务器上开发OK后,我们提交给SVN服务器,然后进入代码提交服务器。进入代码提交服务器后,有两步要走的,我理解为一个拉,一个推。a 我们使用SVN up 将本地文件更新b 使用rsync推送到生产环境服务器以上两部分 我分别写成一个shell文件运行 bash xxx.sh 即可2 用户访问网站的流程,基本是这样的:网站使用了动态CDN,起到加速的作用,我们先把动态CDN放到一边,说说下面发生的事情。在前端我们使用了LVS,关于LVS我使用百科上的文章,给予解释下:LVS是一个开源的软件,由毕业于国防科技大学的章文嵩博士于1998年5月创立,可以实现LINUX平台下的简单负载均衡。LVS是Linux Virtual Server的缩写,意思是Linux虚拟服务器。LVS集群采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。为此,在设计时需要考虑系统的透明性、可伸缩性、高可用性和易管理性。LVS集群采用三层结构一般来说,LVS集群采用三层结构,其主要组成部分为:A、负载调度器(load balancer),它是整个集群对外面的前端机,负责将客户的请求发送到一组服务器上执行,而客户认为服务是来自一个IP地址(我们可称之为虚拟IP地址)上的。B、服务器池(server pool),是一组真正执行客户请求的服务器,执行的服务有WEB、MAIL、FTP和DNS等。C、共享存储(shared storage),它为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,提供相同的服务。A LVS1 核心是它的负载调度器2 塔负责维护一个路由表3 实时监控真实server健康状况B LVS必须有个热备 hot back,万一LVS坏了,那就完蛋了。这样,当LVS万一坏了,可以备份LVS接管工作。C 源站192.168.1.156/157 对外虚拟一个VIP 115。DNS解析域名的时候就解析到这个VIP上。至于具体用户访问是哪台服务器,对用户而言是透明的,LVS根据 IP负载均衡技术 为用户分配源站地址。D 两台源站服务器,为了可以保证某些地方的数据同步,我做了:1 两台源站服务器之间的缓存通过NFS挂载,保持同步;2 crontab中写入计划任务,同步相关ssi文件;E 后端DB的连接,我们使用了2主2从DB集群两台主库77、78对外虚拟成VIP 110,原理,当任何一台DB挂掉后,另外一台立即接管其。两台db互为主从。通过keepalived监测各自生存状态。F 主从库之间通过binlog保持同步。所有binlog均通过主库发出。其余三台从库(其中一台为主库,角色为从库)接受binlog,维护各自数据成分。G 另外我们是有了一台附件服务器。减轻WEB压力。H 另外,还有图片服务器/小图标服务器,可以放在web自身,通过域名区分。其实图片、附件、css等哪儿并不重要,只要可以通过域名访问到,是完全可以的。我们通过 博瑞系统 ,对网站进行监控。 对于web站点,首屏时间是考核的重点,任何一个用户不想等待3s钟页面还没有加载完,用户体验非常差。这是在加入CDN后,对全国各监测点进行相关的监测和性能的评测。完
2023年08月07日
19 阅读
0 评论
0 点赞
2023-08-07
PHP分页器制作,自动生成分面页码
PHP分页器制作,自动生成分面页码PHP分页器制作,自动生成分面页码,JS调用函数<?php class PageView{ /**页码**/ public $pageNo = 1; /**页大小**/ public $pageSize = 20; /**共多少页**/ public $pageCount = 0; /**总记录数**/ public $totalNum = 0; /**偏移量,当前页起始行**/ public $offSet = 0; /**每页数据**/ public $pageData = array(); /**是否有上一页**/ public $hasPrePage = true; /**是否有下一页**/ public $hasNextPage = true; public $pageNoList = array(); public $jsFunction ='jsFunction'; /** * * @param unknown_type $count 总行数 * @param unknown_type $size 分页大小 * @param unknown_type $string */ public function __construct($count=0, $size=20,$pageNo=1,$pageData =array(),$jsFunction='jsFunction'){ $this->totalNum = $count;//总记录数 $this->pageSize = $size;//每页大小 $this->pageNo = $pageNo; //计算总页数 $this->pageCount = ceil($this->totalNum/$this->pageSize); $this->pageCount = ($this->pageCount<=0)?1:$this->pageCount; //检查pageNo $this->pageNo = $this->pageNo == 0 ? 1 : $this->pageNo; $this->pageNo = $this->pageNo > $this->pageCount? $this->pageCount : $this->pageNo; //计算偏移 $this->offset = ( $this->pageNo - 1 ) * $this->pageSize; //计算是否有上一页下一页 $this->hasPrePage = $this->pageNo == 1 ?false:true; $this->hasNextPage = $this->pageNo >= $this->pageCount ?false:true; $this->pageData = $pageData; $this->jsFunction = $jsFunction; } /** * 分页算法 * @return */ private function generatePageList(){ $pageList = array(); if($this->pageCount <= 9){ for($i=0;$i<$this->pageCount;$i++){ array_push($pageList,$i+1); } }else{ if($this->pageNo <= 4){ for($i=0;$i<5;$i++){ array_push($pageList,$i+1); } array_push($pageList,-1); array_push($pageList,$this->pageCount); }else if($this->pageNo > $this->pageCount - 4){ array_push($pageList,1); array_push($pageList,-1); for($i=5;$i>0;$i--){ array_push($pageList,$this->pageCount - $i+1); } }else if($this->pageNo > 4 && $this->pageNo <= $this->pageCount - 4){ array_push($pageList,1); array_push($pageList,-1); array_push($pageList,$this->pageNo -2); array_push($pageList,$this->pageNo -1); array_push($pageList,$this->pageNo); array_push($pageList,$this->pageNo + 1); array_push($pageList,$this->pageNo + 2); array_push($pageList,-1); array_push($pageList,$this->pageCount); } } return $pageList; } /*** * 创建分页控件 * @param * @return String */ public function echoPageAsDiv(){ $pageList = $this->generatePageList(); $pageString ="<div class='pagination'><div class='page-bottom'>"; if(!empty($pageList)){ if($this->pageCount >1){ if($this->hasPrePage){ $pageString = $pageString ."<a class='page-next' href=\"javascript:" .$this->jsFunction . "(" . ($this->pageNo-1) . ")\">上一页</a>"; } foreach ($pageList as $k=>$p){ if($this->pageNo == $p){ $pageString = $pageString ."<span class='page-cur'>" . $this->pageNo . "</span>"; continue; } if($p == -1){ $pageString = $pageString ."<span class='page-break'>...</span>"; continue; } $pageString = $pageString ."<a href=\"javascript:" .$this->jsFunction . "(" . $p . ")\">" . $p . "</a>"; } if($this->hasNextPage){ $pageString = $pageString ."<a class='page-next' href=\"javascript:" .$this->jsFunction . "(" . ($this->pageNo+1) . ")\">下一页</a>"; } } } $pageString = $pageString .("</div></div>"); return $pageString; } } ?><style type="text/css"> <!-- .pagination {font-family: Tahoma;overflow: hidden; padding-top: 12px; text-align: center;} .pagination-tab { margin-bottom: 20px;} .pagination a, .pagination .page-cur, .pagination .page-prev_g, .pagination .page-prev, .pagination .page-next, .pagination .page-next_g, .pagination .page-break, .pagination .page-skip { display: inline-block;font-family: Tahoma,SimSun,Arial; height: 22px;line-height:22px; margin: 0; min-width: 16px;padding: 0 5px; text-align: center; vertical-align: top; white-space: nowrap;} .pagination a, .pagination .page-prev_g, .pagination .page-prev, .pagination .page-next, .pagination .page-next_g, .pagination .page-cur, .pagination .page-break { border: 1px solid #ed3d83; color:#e9357d; font-weight:bold;} .pagination a:hover { border: 1px solid #ed3d83;text-decoration: none; background-color:#f95f9d; color:#fff;} .pagination .page-prev_g, .pagination .page-prev, .pagination .page-next, .pagination .page-next_g { width: 36px; background-image: url(../static/img/page.gif);} .pagination .page-prev { background-position: -0px -38px; padding-left: 16px;} .pagination .page-prev_g { background-position:0px -59px; padding-left: 16px; color:#cbcbcb; font-weight:normal;} .pagination .page-next { background-position: 0px 0px; padding-right: 16px; font-weight:normal;} .pagination .page-next_g { background-position: -0px -19px; padding-right: 16px; color:#cbcbcb;} .pagination .page-cur {background-color: #f95f9d; border: 1px solid #ed3d83;color: #fff;font-weight: bold;} .pagination .page-break {border: medium none; background:none transparent; color:#333;} --> </style>PHP调用 $pageNo = $_GET['pageNo']; if(empty($pageNo)){ $pageNo = 1; } //分页数据 $pageData = News::getNewsPage($pageNo,$pageSize); //取得总行数 $count = News::getNewsCount(); //创建分页器 $p = new PageView($count['0']['TOTAL'],$pageSize,$pageNo,$pageData); //生成页码 $pageViewString = $p->echoPageAsDiv();效果图如下:
2023年08月07日
12 阅读
0 评论
0 点赞
2023-08-07
PHP分页显示制作详细讲解
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 ){ $page_count = 1; } //如果总数据量小于$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类进行处理Pager.class.php<?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 ){ $this->numPages = 1; } 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 ) { $this->NextPageID = $this->CurrentPageID + 1; } if ( !$this->isFirstPage ) { $this->PreviousPageID = $this->CurrentPageID - 1; } } 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; } } ?>test_pager.php<?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方法。
2023年08月07日
10 阅读
0 评论
0 点赞
1
...
133
134
135
...
158