找到
289
篇与
易航
相关的结果
- 第 28 页
-
PHP使用PDO连接数据库 一、什么是PDO? PDO是PHP Date Object(PHP数据对象)的简称,它是与PHP 5.1版本一起发行的。 目前支持的数据库包括Firebird、FreeTDS、Interbase、MySQL、MS SQL Server、ODBC、Oracle、Postgre SQL、SQLite和Sybase。 PHP开发图片 有了PDO,您不必再使用mysql_函数、oci_函数或者mssql_*函数,也不必再为它们封装数据库操作类,只需要使用PDO接口中的方法就可以对数据库进行操作。在选择不同的数据库时,只需修改PDO的DSN(数据源名称)。 在PHP 6中将默认使用PDO连接数据库,所有非PDO扩展将会在PHP 6中被移除。该扩展提供PHP内置类PDO来对数据库进行访问,不同数据库使用相同的方法名,以解决数据库连接不统一的问题。 二、PDO的作用与特点 统一各种数据库的访问接口 PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和mssql函数库相比,PDO让跨数据库的使用更具有亲和力;与ADODB和MDB2相比,PDO更高效。 图片 三、PDO的启用 PDO是与PHP 5.1一起发行的,默认包含在PHP 5.1中。 由于PDO需要PHP 5.0核心面向对象特性的支持,因此其无法在PHP 5.0之前的版本中使用。 默认情况下,PDO在PHP 5.2中为开启状态,但是要启用对某个数据库驱动程序的支持,仍需要进行相应的配置操作。 在Windows环境下,PDO在php.ini文件中进行配置,如果想支持某个特定数据库,只需要把php.ini 文件里边所对应的 ;号 去掉即可。 我们先找到php.ini 配置文件,然后进入 搜索 pdo_ 可以看到我们这里只打开了 mysql和sqlite。注意:开启过后需要重启Apache 图片 我们可以使用输出 phpinfo() 函数来查看是否开启。 四、通过PDO连接数据库 PDO的构造函数 在PDO中,要建立与数据库的连接需要实例化PDO的构造函数,PDO构造函数的语法如下: __construct(string $dsn[,string $username[,string $password[,array $driver_options]]]) dsn:数据源名,包括主机名、端口号和数据库名称。 username:连接数据库的用户名。 password:连接数据库的密码。 driver_options:连接数据库的其他选项。 格式:mysql,db_databvase17,127.0.0.1,root,123456 实例: $dbms='mysql';//数据库类型 $host='127.0.0.1';//数据库主机名 也可以是127.0.0.1 $dbName='db_database17';//使用的数据库名称 $user='root';//用户名 $pass='123456';//对应的密码 $dsn="$dbms:dbname=$dbName;host=$host"; $conn= new PDO($dsn,$user,$pass); //初始化一个PDO对象,就是创建了连接数据库的对象 $conn构造函数用于构造PDO对象,有了这个对象,我们我就可以使用里边的方法来访问数据库。 1. exec() 方法 exec() 方法返回执行后受影响的行数,: 通常用于 INSERT 、 DELETE 和 UPDATE 语句中。 实例: <?php try { $conn = new PDO($dsn, $user, $pass); //初始化一个PDO对象,就是创建了连接数据库的对象 $conn $query = "insert into tb_pdo_mysql(pdo_type,database_name,dates)values('" . $_POST['pdo'] . "','" . $_POST['databases'] . "','" . $_POST['dates'] . "')"; $result = $conn->exec($query); echo "数据添加成功,受影响的行数为:" . $result; } catch (PDOException $e) { die("Error!:" . $e->getMessage() . '<br/>'); } ?>2. query() 方法 用于返回执行查询后的结果集 query() 方法用于返回执行查询后的结果集: 实例: <?php try { $pdo = new PDO($dsn, $user, $pass); $sql = 'select * from tb_pdo_mysql'; $result = $pdo->query($sql); foreach ($result as $row) { echo "<tr align='center'>" . "<td>" . $row['id'] . "</td>"; echo "<td>" . $row['pdo_type'] . "</td>"; echo "<td>" . $row['database_name'] . "</td>"; echo "<td>" . $row['dates'] . "</td>" . "</tr>"; } } catch (PDOException $e) { die("Error!:" . $e->getMessage() . '<br/>'); } ?>
-
Typecho开发主题常用函数及调用方法 1、站点名称 <?php $this->options->title() ?>2、站点网址 <?php $this->options ->siteUrl(); ?>3、完整路径标题如分享几个 Typecho 中常用的调用函数 <?php $this->archiveTitle(' » ', < span class="string">'', ' | '); ?><?php $this ->options->title(); ?>4、站点说明 <?php $this->options->description() ?>5、模板文件夹地址 <?php $this->options->themeUrl(); ?>6、导入模板文件夹内的 php 文件 <?php $this->need('.php'); ?>7、文章或者页面的作者 <?php $this->author(); ?>8、作者头像 < ?php $this->author->gravatar('40') ?> //此处输出的完整的img标签,40是头像的宽和高9、该文作者全部文章列表链接 <?php $this->author->permalink (); ?>10、该文作者个人主页链接 <?php $this->author->url(); ?>11 、该文作者的邮箱地址 <?php $this->author->mail(); ?>12、上一篇与下一篇调用代码 <?php $this->thePrev(); ?> <?php $this->theNext(); ?>13、判断是否为首页,输出相关内容 <?php if ($this->is('index')): ?> //首页输出内容 <?php else: ?> //不是首页输出内容 <?php endif; ?>14、文章或页面,评论数目 <?php $this->commentsNum('No Comments', '1 Comment' , '%d Comments'); ?>15、截取部份文章(首页每篇文章显示摘要),350 是字数 <?php $this->excerpt(350, '...'); ?>16、调用自定义字段 <?php $this->fields->fieldName ?>17、RSS 地址 <?php $this->options->feedUrl(); ?>18、获取最新 post <?php $this->widget('Widget_Contents_Post_Recent', 'pageSize=8&type=category')->parse('<li><a href="{permalink}">{title}</a></li>'); ?>19、纯文字分类名称,不带链接 <?php $this->category(',', false); ?>20、获取当前文章所属分类(包含链接) <?php if ($this->is('post')): ?> <span><?php $this->category(' '); ?></span> <?php endif; ?>21、获取文章分类列表 <ul> <?php $this->widget('Widget_Metas_Category_List') ->parse('<li><a href="{permalink}">{name}</a> ({count})</li>'); ?> </ul>22、获取某分类 post <ul> <?php $this->widget('Widget_Archive@indexyc', 'pageSize=8&type=category', 'mid=1') ->parse('<li><a href="{permalink}" title="{title}">{title}</a></li>'); ?> </ul>23、获取最新评论列表 <ul> <?php $this->widget('Widget_Comments_Recent')->to($comments); ?> <?php while($comments->next()): ?> <li><a href="<?php $comments->permalink(); ?>"><?php $comments->author(false); ?></a>: <?php $comments->excerpt(50, '...'); ?></li> <?php endwhile; ?> </ul>24、首页获取 最新文章 代码限制条数 <?php while ($this->next()): ?> <?php if ($this->sequence <= 3): ?> html <?php endif; ?> <?php endwhile; ?>25、获取最新评论列表第二个版本,只显示访客评论不显示博主也就是作者或者说自己发的评论 <?php $this->widget('Widget_Comments_Recent','ignoreAuthor=true')->to($comments); ?> <?php while($comments->next()): ?> <li><a href="<?php $comments->permalink(); ?>"><?php $comments->author(false); ?></a>: <?php $comments->excerpt(50, '...'); ?></li> <?php endwhile; ?>26、获取文章时间归档 <ul> <?php $this->widget('Widget_Contents_Post_Date', 'type=month&format=F Y') ->parse('<li><a href="{permalink}">{date}</a></li>'); ?> </ul>27、获取标签集合,也就是标签云 <?php $this->widget('Widget_Metas_Tag_Cloud', 'ignoreZeroCount=1&limit=28')->to($tags); ?> <?php while($tags->next()): ?> <a href="<?php $tags->permalink(); ?>" class="size-<?php $tags->split(5, 10, 20, 30); ?>"><?php $tags->name(); ?></a> <?php endwhile; ?>28、调用该文相关文章列表 <?php $this->related(5)->to($relatedPosts); ?> <?php if ($relatedPosts->have()): ?> //这句也可以写成 if (count($relatedPosts->stack)) <ul><?php while ($relatedPosts->next()): ?> <li><a href="<?php $relatedPosts->permalink(); ?>" title="<?php $relatedPosts->title(); ?>"><?php $relatedPosts->title(); ?></a></li> <?php endwhile; ?></ul> <?php else : ?> <li>无相关文章</li> <?php endif; ?>29、隐藏 head 区域的程序版本和模版名称 <?php $this->header("generator=&template="); ?>30、获取读者墙 <?php $period = time() - 999592000; // 時段: 30 天, 單位: 秒 $counts = Typecho_Db::get()->fetchAll(Typecho_Db::get() ->select('COUNT(author) AS cnt','author', 'url', 'mail') ->from('table.comments') ->where('created > ?', $period ) ->where('status = ?', 'approved') ->where('type = ?', 'comment') ->where('authorId = ?', '0') ->group('author') ->order('cnt', Typecho_Db::SORT_DESC) ->limit(25) ); $mostactive = ''; $avatar_path = 'http://www.gravatar.com/avatar/'; foreach ($counts as $count) { $avatar = $avatar_path . md5(strtolower($count['mail'])) . '.jpg'; $c_url = $count['url']; if ( !$c_url ) $c_url = Helper::options()->siteUrl; $mostactive .= "<a href='" . $c_url . "' title='" . $count['author'] . " (参与" . $count['cnt'] . "次互动)' target='_blank'><img src='" . $avatar . "' alt='" . $count['author'] . "的头像' class='avatar' width='32' height='32' /></a>\n"; } echo $mostactive; ?>31、登陆与未登录用户展示不同内容 <?php if($this->user->hasLogin()): ?> // 登陆可见 <?php else: ?> // 未登录和登陆均可见 <?php endif; ?>32、导航页面列表调用隐藏特定的页面 这个演示隐藏了 album 和 search 两个页面 <ul> <li<?php if($this->is('index')): ?> class="current"<?php endif; ?>><a href="<?php $this->options->siteUrl(); ?>">主页</a></li> <?php $this->widget('Widget_Contents_Page_List')->to($pages); ?> <?php while($pages->next()): ?> <?php if (($pages->slug != 'album') && ($pages->slug != 'search')): ?> <li<?php if($this->is('page', $pages->slug)): ?> class="current"<?php endif; ?>><a href="<?php $pages->permalink(); ?>" title="<?php $pages->title(); ?>"><?php $pages->title(); ?></a></li> <?php endif; ?> <?php endwhile; ?> </ul> //参数说明:9.0 版 typecho 支出在后台管理页面编辑时选择隐藏页面。33、Typecho 归档页面 (牧风提供) <?php $this->widget('Widget_Contents_Post_Recent', 'pageSize=10000')->to($archives); $year=0; $mon=0; $i=0; $j=0; $output = '<div id="archives">'; while($archives->next()): $year_tmp = date('Y',$archives->created); $mon_tmp = date('m',$archives->created); $y=$year; $m=$mon; if ($mon != $mon_tmp && $mon > 0) $output .= '</ul></li>'; if ($year != $year_tmp && $year > 0) $output .= '</ul>'; if ($year != $year_tmp) { $year = $year_tmp; $output .= '<h3 class="al_year">'. $year .' 年</h3><ul class="al_mon_list">'; //输出年份 } if ($mon != $mon_tmp) { $mon = $mon_tmp; $output .= '<li><span class="al_mon">'. $mon .' 月</span><ul class="al_post_list">'; //输出月份 } $output .= '<li>'.date('d日: ',$archives->created).'<a href="'.$archives->permalink .'">'. $archives->title .'</a> <em>('. $archives->commentsNum.')</em></li>'; //输出文章日期和标题 endwhile; $output .= '</ul></li></ul></div>'; echo $output; ?>34、获取当前文章页缩略图 <?php $this->attachments(1)->attachment->url(); ?> //进行熊掌号改造的朋友请务必注意,这里所谓缩略图指的是当前文章页第一个附件地址,请确保第一个附件类型为图片。35、根据页面类型显示内容 //判断是文章页则显示内容 <?php if ($this->is('post')): ?> 想要显示的内容1 <?php endif; ?> //判断是页面则显示内容 <?php if ($this->is('page', 'about')): ?> 想要显示的内容2 <?php endif; ?>图片
-
PHP微信公众号回调授权系统源码 源码简介 php微信公众号回调授权系统源码,可以突破微信公众号后台默认只能授权两个网页域名的限制,对接无限个网站域名授权。 准备工具:微信公众号授权无限回调工具 认证过的公众号,记着加白名单IP,这个网上教程很多就是在微信公众号设置里面加IP白名单 域名一枚,也需要微信公众号加进去受访信任,服务器一台。 Linux服务器安装宝塔,添加一个站点,站点内不需要什么页面,宝塔默认的就可以 这个文件不需要设置什么,再上传放入公众号验证的文件验证一下域名归属权。 图片 安装教程 测试运行环境 Nginx+PHP7.2+MySQL5.6 安装PHP扩展 sg11 修改数据库配置文件 /config.php 后台地址:http://你的域名/admin/login.php 账户密码:admin 源码下载 隐藏内容,请前往内页查看详情
-
PHP操作文件详解 本文主要讲解php文件操作的方法和实例。希望对大家有帮助,操作方法仅供参考。 1、判断是否是一个文件 is_file('./test.txt'); //如果文件是常规的文件,该函数返回 true。 //该函数的结果会被缓存。请使用 clearstatcache() 来清除缓存。2、判断文件是否存在 file_exists('./test.txt');3、打开文件 $fp = fopen('./test.txt', 'r'); /** 只读, r 读写,文件覆盖:r+ 清空写入:w 可创建清空写入:w+ 追加写入:a 创建追加写入:a+ **/4、写入内容到文件 fwrite($fp, 'str字符串');5、指定读取多少字节的文件 fread($fp, 1024);6、一次性读取文件大小 filesize($path); fread($fp, filesize($path));7、关闭文件 fclose($fp);8、给文件重命名 rename(oldname, newname, context);9、删除文件 unlink($path);
-
在线生成网站Favicon.ico图标源码 源码介绍 在线制作生成Favicon.ico图标站长工具源码,支持多种图片格式转换成ICO图标,php源码无后台,上传即可使用,上传图片格式和体积都可以直接在文件内修改。 源码截图 图片 源码说明 上传至网站目录即可使用,无后台版本。 图片默认支持: .jpg .jpeg .gif .png格式,需要添加可修改config.php内: $valid_exts = array("jpg","jpeg","gif","png");默认上传文件大小限制在小于175k,需要修改可修改config.php内: $max_file_size = 179200; // 175kb源码下载 隐藏内容,请前往内页查看详情
-
PHP对API接口请求进行限流的几种算法 接口限流的意义 那么什么是限流呢?顾名思义,限流就是限制流量,包括一定时间内的并发流量和总流量。 就像你有一个 GB 流量的宽带包,用完就没了,所以控制好自己的使用频率和单次使用的总消费。 通过限流,我们可以很好地控制系统的 qps,从而达到保护系统或者接口服务器稳定的目的。 图片 接口限流的常用算法 1、计数器法 计数器法是限流算法里最简单也是最容易实现的一种算法。 比如我们规定,对于 A 接口来说,我们 1 分钟的访问次数不能超过 100 个。那么我们可以这么做:在一开始的时候,我们可以设置一个计数器 counter,每当一个请求过来的时候,counter 就加 1,如果 counter 的值大于 100 并且该请求与第一个请求的间隔时间还在 1 分钟之内,那么说明请求数过多; 如果该请求与第一个请求的间隔时间大于 1 分钟,且 counter 的值还在限流范围内,那么就重置 counter。 代码如下: class CounterDemo { private $first_request_time; private $request_count = 0; //已请求的次数 public $limit = 100; //时间窗口内的最大请求数 public $interval = 60; //时间窗口 s public function __construct() { $this->first_request_time = time(); } public function grant() { $now = time(); if ($now < $this->first_request_time + $this->interval) { //时间窗口内 if ($this->request_count < $this->limit) { $this->request_count++; return true; } else { return false; } } else { //超出前一个时间窗口后, 重置第一次请求时间和请求总次数 $this->first_request_time = $now; $this->request_count = 1; return true; } } } $m = new CounterDemo(); $n_success = 0; for ($i = 0; $i < 200; $i++) { $rt = $m->grant(); if ($rt) { $n_success++; } } echo '成功请求 ' . $n_success . ' 次';计数器算法很简单,但是有个严重的 bug: 一个恶意用户在 0:59 时瞬间发送了 100 个请求,然后再 1:00 时又瞬间发送了 100 个请求,那么这个用户在 2 秒内发送了 200 个请求。 上面我们规定 1 分钟最多处理 100 个请求, 也就是每秒 1.7 个请求。用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过系统的承载能力,导致系统挂起或宕机。 上面的问题,其实是因为我们统计的精度太低造成的。那么如何很好地处理这个问题呢?或者说,如何将临界问题的影响降低呢?我们可以看下面的滑动窗口算法。 图片 上图中,我们把一个时间窗口(一分钟)分成 6 份,每份(小格)代表 10 秒。每过 10 秒钟我们就把时间窗口往右滑动一格, 每一个格子都有自己独立的计数器。 比如一个请求在 0:35 秒到达的时候,就会落在 0:30-0:39 这个区间,并将此区间的计数器加 1。 从上图可以看出, 0:59 到达的 100 个请求会落在 0:50-0:59 这个灰色的格子中, 而 1:00 到达的 100 个请求会落在黄色的格子中。 而在 1:00 时间统计时, 窗口会往右移动一格,那么此时的时间窗口内的请求数量一共是 200 个,超出了限制的 100 个,触发了限流,后面的 100 个请求被抛弃或者等待。 如果我们把窗口时间划分越多, 比如 60 格,每格 1s, 那么限流统计会更精确。 2、漏桶算法 (Leaky Bucket) 漏桶算法(Leaky Bucket): 平滑网络上的突发流量。使其整流为一个稳定的流量。 图片 有一个固定容量的桶,有水流进来,也有水流出 去。对于流进来的水来说,我们无法预计一共有多少水会流进来,也无法预计水流的速度。但是对于流出去的水来说,这个桶可以固定水流出的速率。当桶满了之后,多余的水将会溢出(多余的请求会被丢弃)。 简单的算法实现代码: class LeakyBucketDemo { private $last_req_time; //上一次请求的时间 public $capacity; //桶的容量 public $rate; //水漏出的速度(个/秒) public $water; //当前水量(当前累积请求数) public function __construct() { $this->last_req_time = time(); $this->capacity = 100; $this->rate = 20; $this->water = 0; } public function grant() { $now = time(); $water = max(0, $this->water - ($now - $this->last_req_time) * $this->rate); // 先执行漏水,计算剩余水量 $this->water = $water; $this->last_req_time = $now; if ($water < $this->capacity) { // 尝试加水,并且水还未满 $this->water += 1; return true; } else { // 水满,拒绝加水 return false; } } } $m = new LeakyBucketDemo(); $n_success = 0; for ($i = 0; $i < 500; $i++) { $rt = $m->grant(); if ($rt) { $n_success++; } if ($i > 0 && $i % 100 == 0) { //每发起100次后暂停1s echo '已发送', $i, ', 成功 ', $n_success, ', sleep' . PHP_EOL; sleep(1); } } echo '成功请求 ' . $n_success . ' 次';3、令牌桶算法 (Token Bucket) 令牌桶算法比漏桶算法稍显复杂。首先,我们有一个固定容量的桶,桶里存放着令牌(token)。桶一开始是空的(可用 token 数为 0),token 以一个固定的速率 r 往桶里填充,直到达到桶的容量,多余的令牌将会被丢弃。每当一个请求过来时,就会尝试从桶里移除一个令牌,如果没有令牌的话,请求无法通过。 实现代码如下: class TokenBucketDemo { private $last_req_time; //上次请求时间 public $capacity; //桶的容量 public $rate; //令牌放入的速度(个/秒) public $tokens; //当前可用令牌的数量 public function __construct() { $this->last_req_time = time(); $this->capacity = 100; $this->rate = 20; $this->tokens = 100; //开始给100个令牌 } public function grant() { $now = time(); $tokens = min($this->capacity, $this->tokens + ($now - $this->last_req_time) * $this->rate); // 计算桶里可用的令牌数 $this->tokens = $tokens; $this->last_req_time = $now; if ($this->tokens < 1) { // 若剩余不到1个令牌,则拒绝 return false; } else { // 还有令牌,领取1个令牌 $this->tokens -= 1; return true; } } } $m = new TokenBucketDemo(); $n_success = 0; for ($i = 0; $i < 500; $i++) { $rt = $m->grant(); if ($rt) { $n_success++; } if ($i > 0 && $i % 100 == 0) { //每发起100次后暂停1s echo '已发送', $i, ', 成功 ', $n_success, ', sleep' . PHP_EOL; sleep(1); } } echo '成功请求 ' . $n_success . ' 次';我们可以使用 redis 的队列作为令牌桶容器使用,使用 lPush(入队),rPop(出队),实现令牌加入与消耗的操作。 TokenBucket.php <?php /** * PHP基于Redis使用令牌桶算法实现接口限流,使用redis的队列作为令牌桶容器,入队(lPush)出队(rPop)作为令牌的加入与消耗操作。 * public add 加入令牌 * public get 获取令牌 * public reset 重设令牌桶 * private connect 创建redis连接 */ class TokenBucket { // class start private $_config; // redis设定 private $_redis; // redis对象 private $_queue; // 令牌桶 private $_max; // 最大令牌数 /** * 初始化 * @param Array $config redis连接设定 */ public function __construct($config, $queue, $max) { $this->_config = $config; $this->_queue = $queue; $this->_max = $max; $this->_redis = $this->connect(); } /** * 加入令牌 * @param Int $num 加入的令牌数量 * @return Int 加入的数量 */ public function add($num = 0) { // 当前剩余令牌数 $curnum = intval($this->_redis->lSize($this->_queue)); // 最大令牌数 $maxnum = intval($this->_max); // 计算最大可加入的令牌数量,不能超过最大令牌数 $num = $maxnum >= $curnum + $num ? $num : $maxnum - $curnum; // 加入令牌 if ($num > 0) { $token = array_fill(0, $num, 1); $this->_redis->lPush($this->_queue, ...$token); return $num; } return 0; } /** * 获取令牌 * @return Boolean */ public function get() { return $this->_redis->rPop($this->_queue) ? true : false; } /** * 重设令牌桶,填满令牌 */ public function reset() { $this->_redis->delete($this->_queue); $this->add($this->_max); } /** * 创建redis连接 * @return Link */ private function connect() { try { $redis = new Redis(); $redis->connect($this->_config['host'], $this->_config['port'], $this->_config['timeout'], $this->_config['reserved'], $this->_config['retry_interval']); if (empty($this->_config['auth'])) { $redis->auth($this->_config['auth']); } $redis->select($this->_config['index']); } catch (RedisException $e) { throw new Exception($e->getMessage()); return false; } return $redis; } } ?>令牌的假如与消耗: <?php /** * 演示令牌加入与消耗 */ require 'TokenBucket.php'; // redis连接设定 $config = array( 'host' => 'localhost', 'port' => 6379, 'index' => 0, 'auth' => '', 'timeout' => 1, 'reserved' => NULL, 'retry_interval' => 100, ); // 令牌桶容器 $queue = 'mycontainer'; // 最大令牌数 $max = 5; // 创建TrafficShaper对象 $tokenBucket = new TokenBucket($config, $queue, $max); // 重设令牌桶,填满令牌 $tokenBucket->reset(); // 循环获取令牌,令牌桶内只有5个令牌,因此最后3次获取失败 for ($i = 0; $i < 8; $i++) { var_dump($tokenBucket->get()); } // 加入10个令牌,最大令牌为5,因此只能加入5个 $add_num = $tokenBucket->add(10); var_dump($add_num); // 循环获取令牌,令牌桶内只有5个令牌,因此最后1次获取失败 for ($i = 0; $i < 6; $i++) { var_dump($tokenBucket->get()); } ?>