Smarty 在表格(table)里输出多列多行数据的方法

Smarty 是一个非常流行的 PHP 模板引擎,她支持缓存,能在实现 MVC 构架的同时,提高程序执行效率,深受众多 PHPer 的喜爱。Smarty 提供功能全面的模板语法,如果使用得当,你能很方便的实现你想要的显示方式。

本文讨论的是一个对初学者来说非常头痛的问题:将数据分成多列显示在表格中。单条数据循环对大多数模板引擎来说,实现都非常简单,但是要每行显示多条记录就需要一些额外的设置了。本文详细说明了解决这一问题的方法,相信对初学者非常有用。

模板文件:

 
<table border="1">
	<tr>
 
<?section name=site loop=$siteList?>
 
	<td><?$siteList[site].url?></td>
 
	<?if $siteListColumn > 1 ?>
 
	<?if $smarty.section.site.index != 0 && ($smarty.section.site.index + 1) % $siteListColumn == 0 ?>
	</tr>
	<tr>
	<?/if?>
 
	<?else?>
	</tr>
	<tr>
	<?/if?>
 
<?/section?>
 
	</tr>
</table>

注:示例中的模板定界符为 <??>

PHP 代码:

 
<?php
 
// 说明:Smarty 在表格(table)里输出多列多行数据的方法
// 站点:http://www.codebit.cn
 
// 设置列表内容
$siteList = array(
	array('url'=>'http://www.codebit.cn'),
	array('url'=>'http://YITU.org'),
	array('url'=>'http://www.google.com'),
	array('url'=>'http://www.baidu.com'),
	array('url'=>'http://www.yahoo.com.cn'),
	array('url'=>'http://www.163.com'),
	array('url'=>'http://www.sohu.com'),
	array('url'=>'http://www.sina.com.cn'),
);
 
// 列表数据统计
$siteListCount = count($siteList);
 
// 显示列数
$siteListColumn = 3;
 
// 如果列表数据不能将最后一行填满,
// 如:共 8 条记录,每列 3 条记录,最后一行还差 1 条
if($siteListColumn > 1 && $siteListCount % $siteListColumn != 0)
{
	// 计算最后一行还差几列
	$emptyColumn = $siteListColumn - ($siteListCount % $siteListColumn);
 
	for($i=0; $i<$emptyColumn; $i++)
	{
		// 用空值填充,保证最后一行正确显示
		$siteList[$siteListCount + $i] = array('url'=>'&nbsp;');
	}
}
 
// 将显示列数赋值到模板
$smarty->assign('siteListColumn', $siteListColumn);
 
// 将显示数据赋值到模板
$smarty->assign('siteList', $siteList);
 
?>

此代码可以将指定数据显示在一个任意列(通过 $siteListColumn 设置)的表格中。

除了将数据显示在表格中,我们还有另外一个选择,那就是将数据显示在一个 UL 列表中,然后通过 CSS 控制 LI 的宽度,同样也能实现多列数据显示。这种方法在前台页面中也实现了数据和结构的分离,页面上只有数据,具体显示由 CSS 控制,这样,就实现了前台页面的 MVC 构架,好处多多。

MSSQL 如何实现 MySQL 的 limit 查询方式

不知为何,MSSQL 中没有 limit 这个极为重要的查询方式,熟悉 MySQL 的朋友都知道,MySQL 的 limit 对于实现分页和一些限制结果集的应用中非常方便。没有不要紧,我们可以用其他方法达到同样的目的,自己动手,丰衣足食!

语法:

 
SELECT * FROM 
(
	SELECT TOP [每页记录] * FROM 
	(
		SELECT TOP [每页记录*当前页数] [字段1, 字段2, ...] 
		FROM [数据表]	
		ORDER BY [排序字段] DESC
	)
	[表别名1] 
	ORDER BY [排序字段] 
)
[表别名2] 
ORDER BY [排序字段] DESC

示例:

 
SELECT * FROM 
(
	SELECT TOP 5 * FROM 
	(
		SELECT TOP 10 * 
		FROM table 
		ORDER BY id DESC
	) t1 
	ORDER BY id
) t2 
ORDER BY id DESC

上面的代码表示从 table 表中获取记录,每页5条记录,当前是第二页5*2=10,结果按照 id 倒序排列。

PHP 中控制浏览器缓存的方法

用 PHP 控制浏览器缓存是非常容易的,手册上也相关的说明,由于很多初学者没有把手册看完,所以还是会有很多关于这个问题的疑问,故在此专门发一篇文章,同时对相关的语法做了详细的说明,方便新手查阅。

要解决这一问题,可以通过 PHP 中的 header() 函数,发送特定的缓存控制原始 HTTP 标头,具体代码如下:

 
<?php
 
//下面的语句设置此页面的过期时间(用格林威治时间表示),只要是已经过去的日期即可。
header("Expires: Mon, 26 Jul 1970 05:00:00 GMT");
 
//下面的语句设置此页面的最后更新日期(用格林威治时间表示)为当天,可以强迫浏览器获取最新资料
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
 
//告诉客户端浏览器不使用缓存,HTTP 1.1 协议
header("Cache-Control: no-cache, must-revalidate");
 
//告诉客户端浏览器不使用缓存,兼容HTTP 1.0 协议
header("Pragma: no-cache"); 
 
?>

注意:header() 必须在任何实际输出之前调用,不论是来自普通的 HTML 标记,空行或者 PHP。在中文环境下,一个全角的空格也会导致难以查找的错误!

FreeBSD 安装 Zend Optimizer 成功却不工作的原因

由于 FreeBSD 系统的安全性和稳定性以及该系统下 PHP 运行的良好口碑,越来越多的人开始选择他做为自己的服务器系统平台。

Zend Optimizer (下简称 ZO) 是 PHP 官方推荐的 PHP 代码优化工具,在 FreeBSD 下安装 ZO 时,一个常见的问题是明明提示安装成功,但是在查看 phpinfo 时,却发现 ZO 并没有正常加载,或者加载了也不工作,本文介绍的就是这一问题的解决办法。

Zend Optimizer 安装文档中的说明:

The Zend Optimizer will not run if the following PHP settings are enabled:

Debug Mode – Check that your PHP was compiled in non-debug mode –
This can be checked by looking at the top part of the phpinfo() function
output and checking "Debug Build" row (ZEND_DEBUG in older PHP
versions) – it should say "no".

意思是如果你的 PHP 运行在 debug 模式, Zend Optimizer 将不会正常运行。解决这一问题,您需要:

(1)如果你是编译安装 PHP ,那需要在编译选项里面加上 “–disable-debug”

(2)如果你是 ports 安装,在安装选项中去掉 DEBUG 项。

PHP 中检查是否关联数组(多维数组)的方法 (UPDATE!)

摘自 xoad 的检查是否关联数组(多维数组)的方法

数组在PHP中是最常用的一种数据类型,PHP 支持一维和多维数组,在操作数组元素时,对一维数组和多维数组的处理方法有许多不同之处,因此,许多时候,我们需要在操作前先检测一下数组类型,本文介绍的就是解决这一问题的方法。

 
<?php
// 说明:摘自 xoad 的检查是否关联数组(多维数组)的方法
// 整理:http://www.CodeBit.cn

function isAssocArray($var)
{
	if ( ! is_array($var))
	{
		return false;
	}

	$arrayKeys = array_keys($var);

	$sequentialKeys = range(0, sizeof($var));

	if (function_exists('array_diff_assoc'))
	{
		if (array_diff_assoc($arrayKeys, $sequentialKeys)) 
		{
			return true;
		}
	}
	else
	{
		if ((array_diff($arrayKeys, $sequentialKeys)) && 
			(array_diff($sequentialKeys, $arrayKeys)))
		{
			return true;
		}
	}
	return false;
}

$array_1 = array(
	'http://www.CodeBit.cn', 
	'http://YITU.org'
);

$array_2 = array(
	'CodeBit.cn'=>'http://www.CodeBit.cn', 
	'YITU.org'=>'http://YITU.org'
);

echo (isAssocArray($array_1))?'是':'否'; // 否

echo "<br />";

echo (isAssocArray($array_2))?'是':'否'; // 是
?>

网友 etng 发布的检查是否关联数组(多维数组)的方法

数组在PHP中是最常用的一种数据类型,PHP 支持一维和多维数组,在操作数组元素时,对一维数组和多维数组的处理方法有许多不同之处,因此,许多时候,我们需要在操作前先检测一下数组类型,本文介绍的就是解决这一问题的方法。

 
<?php

// 说明:检查是否关联数组(多维数组)的方法
// 整理:http://www.CodeBit.cn

//作者:etng
//网址:http://www.etng.net/blog

function isAA($input)
{
    return is_array($input) 
            && !(array_keys($input) === range(0, sizeof($input)-1));
}

$array_1 = array(
	'http://www.CodeBit.cn',
	'http://YITU.org'
);

$array_2 = array(
	'CodeBit.cn'=>'http://www.CodeBit.cn',
	'YITU.org'=>'http://YITU.org'
);

echo isAA($array_1)?'是':'否'; // 否
echo "<br />";
echo isAA($array_2)?'是':'否'; // 是 

?>

实现思路:
(1) is_array($input) 检查是否是数组。
(2) array_keys($input) 获取数组的 key(如果是一维数组,其返回一个元素是0到数组大小的数组),然后通过 range(0, sizeof($input)-1) 生成一个0 到 数组大小的一维数组,比较两个数组是否一致(===),如果一致,说明是一维数组,否则(!),便是多维数组。

网友 etng 发布的这段代码结构清晰,代码简洁,非常感谢网友 etng 对本站的支持,

验证邮件地址并格式化成防垃圾邮件的字符串

验证邮件地址是否合法可以说是程序员最最经常用到的功能,正则表达式的写法也有很多种,本文介绍的函数是从 xoops 摘录而来,该函数除了能够验证邮件地址,还能将地址格式化为防垃圾邮件的字符串。

 
<?php
// 说明:验证邮件地址并格式化成防垃圾邮件的字符串
// 整理:http://www.CodeBit.cn

function checkEmail($email,$antispam = false)
{
	if (!$email || !preg_match("/^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+([.][a-z0-9-]+)+$/i",$email)){
		return false;
	}
	if ($antispam) {
		$email = str_replace("@", " at ", $email);
		$email = str_replace(".", " dot ", $email);
		return $email;
	} else {
		return true;
	}
}

echo checkEmail('username@domain.com');

echo "<br />";

echo checkEmail('username@domain.com', true);
?>

上面的代码将输出:

1
username at domain dot com

PHP 版的 Javascript 压缩混淆工具 [ Dean Edwards Packer ]

Dean Edwards ‘s Packer 是个非常有名的 Javascript 压缩/混淆工具,有 .NET / PERL / WSH / PHP 等几种版本, 而本文介绍的 就是Nicolas Martin 发布的 PHP 版。

本说明文档译自:
http://dean.edwards.name/packer/usage/

使用说明:

所有声明,包括 function 函数定义,必须以分号结尾,示例代码:

 
// sample code
 
var $input, $output;
 
// notice the semi-colon at the END of function declarations
 
onload = function() {
    $input = document.getElementById("input");
    $output = document.getElementById("output");
    _clearAll(true);
};
 
function _packScript() {
    $output.value = pack($input.value);
};
 
function _clearAll($focus) {
    $output.value = $input.value = "";
    // the "if" statement is NOT terminated with a semi-colon
    if ($focus) {
        $input.focus();
    }
};

参数:

Encoding

设置压缩/混淆的级别:

None

简单压缩,移除空格和注释,编码特殊字符,

Numeric (Base 10)

所有字符将转换成数字。

Normal (Base 62)

所有字符将转换成数字字母,这个是推荐设置。

High ASCII (Base 95)

将获得更高的压缩比率。(文件更小)

如果你使用这个选项,那么压缩后的代码必须使用 ISO-8859-1 编码,这是由于一个 IE 的 BUG 所致,内容页也需要同样的编码,如果你不能确定,那就使用 "Normal" 。

快速还原 (Fast Decode)

选中此选项,将插入一小段代码(120 bytes),以使代码能够更快的还原(decode)。

特殊字符 (Special Characters)

为了让压缩能区分全局变量和局部变量,压缩工具会将变量转换成下面的格式,由于 Javascript 并不存在确切意义上的全局变量和局部变量,我用下面的方式定义:

局部变量 Local ($)
变量只在当前范围内有效,参数和函数内部的变量就是一个典型例子,将局部变量用 $ 标识,压缩时会截取他们的第一个字符,附加的 $ 将使截取的字符加长,数字将会被保留。

 
// unpacked:
function test($left, $top1, $top2, $$length) {
    // do something
};
// packed:
function test(l,t1,t2,le){};

注意不要让命名冲突,美元标记截取只针对局部变量。

全局变量 Private (_)
全局变量可以在整个代码中使用,用 “ _ ” (下划线)来标识,有下划线标识的全局变量将会被转换成下划线加上一个数字:

 
// unpacked:
var _CONSTANT = 42;
function _test($left, $top1, $top2, $$length) {
    return ($top1 / $top2) + _CONSTANT;
};
// packed:
var _0=42;function _1(l,t1,t2,le){return(t1/t2)+_0};

调试代码 Debug Code (;;;)
三个“;” (分号)将被当成一个单行注释,比如:

 
;;; alert("TEST!");

上面的代码在压缩时将被移除。

平台(Platforms)

压缩后的代码能够正常运行在所有支持 JavaScript 的浏览器,只有很少的 javascript 技术被用于还原代码。

有些浏览器不支持压缩,只有支持 DOM 才能正常运行,Legacy 浏览器将显示一个禁用的界面。

在线 Javascript 压缩:
http://dean.edwards.name/packer/

下载地址:
http://joliclic.free.fr/php/javascript-packer/telechargement.php?id=2&action=telecharger

计算 UTF-8 字符串长度(忽略字节的方案)

本文介绍的函数可以统计 UTF-8 字符串的长度,但不同的是,该函数并不考虑字节,这有些类似 Javascript 中字符串的 length 方法,一个字符全部按 1 个长度计算。

 
<?php
// 说明:计算 UTF-8 字符串长度(忽略字节的方案)
// 整理:http://www.CodeBit.cn

function strlen_utf8($str)
{
	$i = 0;
	$count = 0;
	$len = strlen ($str);
	while ($i < $len)
	{
		$chr = ord ($str[$i]);
		$count++;
		$i++;
		if($i >= $len)
			break;

		if($chr & 0x80)
		{
			$chr <<= 1;
			while ($chr & 0x80)
			{
				$i++;
				$chr <<= 1;
			}
		}
	}
	return $count;
} 

$str = "Codebit.cn - 聚合小段精华代码";

echo strlen_utf8($str);

?>

上面的代码将返回 21。

将有单位的文件大小格式还原成数字

在显示文件大小的时候,我们通常需要将数字转换成有单位的格式(如将35840字节转换成35KB),但是在需要计算的地方,还需要将其还原成数字,本文介绍的函数摘自 phpMyAdmin,可以将有单位的文件大小格式还原成数字。

 
<?php
// 说明:将有单位的文件大小格式还原成数字
// 整理:http://www.CodeBit.cn

/**
 * Converts numbers like 10M into bytes
 *
 * @param   string  $size
 * @return  integer $size
 */
function get_real_size($size = 0)
{
    if (!$size) {
        return 0;
    }
    $scan['MB'] = 1048576;
    $scan['Mb'] = 1048576;
    $scan['M']  = 1048576;
    $scan['m']  = 1048576;
    $scan['KB'] =    1024;
    $scan['Kb'] =    1024;
    $scan['K']  =    1024;
    $scan['k']  =    1024;

    while (list($key) = each($scan)) {
        if ((strlen($size) > strlen($key))
          && (substr($size, strlen($size) - strlen($key)) == $key)) {
            $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
            break;
        }
    }
    return $size;
} // end function get_real_size()


echo 173 * 1048576;
echo "<br />";
echo get_real_size('173m');

?>

PHP 中打乱(shuffle)关联数组的排序

PHP 提供了一个 shuffle() 函数,可以打乱给定的数组排序,但是此函数“将删除原有的键名而不仅是重新排序”,如果传入的是关联数组,则关联数组的键名将丢失,本文介绍的函数可以解决这一问题。

 
<?php
// 说明:PHP 中打乱(shuffle)关联数组的排序
// 整理:http://www.CodeBit.cn

$arr = array(
	'Javascript'=>'253',
	'CSS'=>'612',
	'PHP/MySQL'=>'1036',
	'(X)HTML'=>'361',
	'Ajax'=>'492',
);

// 打乱关联数组的排序
function shuffle_assoc($array)
{ 
	$randomized_keys = array_rand($array, count($array)); 
	foreach($randomized_keys as $current_key)
	{ 
		$output[$current_key] = $array[$current_key]; 
	} 
	return $output;
}

echo "<pre>";
print_r($arr);
echo "</pre><hr />";


echo "<pre>";
print_r(shuffle_assoc($arr));
echo "</pre><hr />";

?>