存档

文章标签 ‘php’

shopex中集成的站长统计功能简单分析

2011年8月2日 没有评论

shopex中集成了一键开启站长统计功能,而无需去CNZZ注册,在phpcms,phpwind等中也都有类似的功能,下面是对这个功能的简单分析,以后也可以偷偷用在自己的网站中,呵呵。

<?php
//我们的域名,这里可以不唯一的
$domain = 'localhost';
//这个应该是CNZZ授权给shopex的加密密钥,如果错了就不能快捷申请账号
$encodestr = 'A34dfwfF';
//这个就是CNZZ授权给shopex的快捷申请账号的URL地址
$url = 'http://wss.cnzz.com/user/companion/shopex.php?domain='.$domain.'&key='.md5($domain.$encodestr);
//获取网页内容得到这样的一个字符串 80772914@3780692425
$res = file_get_contents($url);
//左边是CNZZ统计的站点id,右边是密码
$res = explode('@',$res);
//登录到CNZZ统计的URL,把下面的地址复制到地址栏就可以看到效果了
//http://wss.cnzz.com/user/companion/shopex_login.php?site_id=80772914&password=3780692425
//会自动跳转到 http://wss.cnzz.com/v1/main.php?siteid=80772914&s=main_stat
$login = 'http://wss.cnzz.com/user/companion/shopex_login.php?site_id='.$res[0].'&password='.$res[1];
header("Location:$login");

php pdo中bindParam() 和 bindValue()方法的区别

2011年7月27日 没有评论

方法 bindParam() 和 bindValue() 非常相似。
唯一的区别就是前者使用一个PHP变量绑定参数,而后者使用一个值。

所以使用bindParam是第二个参数只能用变量名,而不能用变量值,而bindValue至可以使用具体值。

$stm = $pdo->prepare("select * from users where user = :user");
$user = "jack";
//正确
$stm->bindParam(":user",$user);
//错误
//$stm->bindParam(":user","jack");
//正确
$stm->bindValue(":user",$user);
//正确
$stm->bindValue(":user","jack");

另外在存储过程中,bindParam可以绑定为input/output变量,如下面:

$stm = $pdo->prepare("call func(:param1)");
$param1 = "abcd";
$stm->bindParam(":param1",$param1); //正确
$stm->execute();

存储过程执行过后的结果可以直接反应到变量上。

对于那些内存中的大数据块参数,处于性能的考虑,应优先使用前者。

php截取html字符串,并自动补全html代码

2011年6月18日 没有评论

实际开发中会经常碰到,很多人直接先strip_tags过滤掉html标签,但是就只剩下纯文本了,可读性非常差,下面是一个函数

/**
 * 截取HTML,并自动补全闭合
 * @param $html
 * @param $length
 * @param $end
 */
function subHtml($html,$length) {
 $result = '';
 $tagStack = array();
 $len = 0;

 $contents = preg_split("~(<[^>]+?>)~si",$html, -1,PREG_SPLIT_NO_EMPTY| PREG_SPLIT_DELIM_CAPTURE);
 foreach($contents as $tag)
 {
 if (trim($tag)=="")  continue;
 if(preg_match("~<([a-z0-9]+)[^/>]*?/>~si",$tag)){
 $result .= $tag;
 }else if(preg_match("~</([a-z0-9]+)[^/>]*?>~si",$tag,$match)){
 if($tagStack[count($tagStack)-1] == $match[1]){
 array_pop($tagStack);
 $result .= $tag;
 }
 }else if(preg_match("~<([a-z0-9]+)[^/>]*?>~si",$tag,$match)){
 array_push($tagStack,$match[1]);
 $result .= $tag;
 }else if(preg_match("~<!--.*?-->~si",$tag)){
 $result .= $tag;
 }else{
 if($len + mstrlen($tag) < $length){
 $result .= $tag;
 $len += mstrlen($tag);
 }else {
 $str = msubstr($tag,0,$length-$len+1);
 $result .= $str;
 break;
 }

 }
 }
 while(!empty($tagStack)){
 $result .= '</'.array_pop($tagStack).'>';
 }
 return  $result;
}

/**
 * 截取中文字符串
 * @param $string 字符串
 * @param $start 起始位
 * @param $length 长度
 * @param $charset  编码
 * @param $dot 附加字串
 */
function msubstr($string, $start, $length,$dot='',$charset = 'UTF-8') {
 $string = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;','&nbsp;'), array('&', '"', '<', '>',' '), $string);
 if(strlen($string) <= $length) {
 return $string;
 }

 if(strtolower($charset) == 'utf-8') {
 $n = $tn = $noc = 0;
 while($n < strlen($string)) {
 $t = ord($string[$n]);
 if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
 $tn = 1; $n++;
 } elseif(194 <= $t && $t <= 223) {
 $tn = 2; $n += 2;
 } elseif(224 <= $t && $t <= 239) {
 $tn = 3; $n += 3;
 } elseif(240 <= $t && $t <= 247) {
 $tn = 4; $n += 4;
 } elseif(248 <= $t && $t <= 251) {
 $tn = 5; $n += 5;
 } elseif($t == 252 || $t == 253) {
 $tn = 6; $n += 6;
 } else {
 $n++;
 }
 $noc++;
 if($noc >= $length) {
 break;
 }
 }
 if($noc > $length) {
 $n -= $tn;
 }
 $strcut = substr($string, 0, $n);
 } else {
 for($i = 0; $i < $length; $i++) {
 $strcut .= ord($string[$i]) > 127 ? $string[$i].$string[++$i] : $string[$i];
 }
 }

 return $strcut.$dot;
}

/**
 * 取得字符串的长度,包括中英文。
 */
function mstrlen($str,$charset = 'UTF-8'){
 if (function_exists('mb_substr')) {
 $length=mb_strlen($str,$charset);
 } elseif (function_exists('iconv_substr')) {
 $length=iconv_strlen($str,$charset);
 } else {
 preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/", $text, $ar); 
 $length=count($ar[0]);
 }
 return $length;
}

php压缩/解压zip的利器-PclZip

2011年3月31日 没有评论

PclZip简介与使用

PclZip介绍
PclZip library能够压缩与解压缩Zip格式的压缩档(WinZip、PKZIP);且能对此类类档案进行处理,包括产生压缩档、列出压缩档的内容以及解压缩档案等等。由于能够在伺服器端进行压缩与解压缩的动作,所以相当方便使用。
PclZip定义一个PclZip类别,其类别物件可视为一个ZIP档案,亦提供method来进行处理。

如何使用PclZip
1.基础
所有的功能都由pclzip.lib.php这个档案提供,PclZip library可于其首页(www.phpconcept.net/pclzip/index.en.php)下载。所有的PKZIP档案其实就是一个PclZip的类别物件。当产生一个PclZip档案(ie, PclZip类别物件),就会先产生一个压缩档,且档名已经指定,但此压缩档的内容尚未存在:

< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip("archive.zip");
?>

此物件提供了一些public method可用来处理此档案。

2.参数
每一个method有其各自可使用的参数,包括有必须与非必须的参数:

< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');

$v_list = $archive->add('dev/file.txt',
PCLZIP_OPT_REMOVE_PATH, 'dev');
?>

上例中的’dev/file.txt’就是必须参数;’PCLZIP_OPT_REMOVE_PATH’则为非必须参数。当然有些method也可以只包含非必须的参数:

< ?PHP
$list = $archive->extract(PCLZIP_OPT_PATH, "folder",
PCLZIP_OPT_REMOVE_PATH, "data",
PCLZIP_CB_PRE_EXTRACT, "callback_pre_extract",);
?>

上例中原本压缩档内档案存放的路径为/data,不过你可以指定解压缩至/folder中。此外,在解压缩之前,会呼叫callback function(’callback_pre_extract()’),此function可让使用者在解压缩的过程中变更档案存放路径与档名,或是选择某些档案不解压缩。
所有可用的非必要参数可参考网址(www.phpconcept.net/pclzip/man/en/index.php)。

3.回传值
每个method所回传的值可能会不同,将会在每个method中说明。不过大部分的method回传0、error或是阵列。

4.错误处理
从版本1.3之后,错误处理已经整合至PclZip类别中,当一个method回传错误码,可以得知一些额外的讯息以方便错误处理:
* errorName():回传错误名称
* errorCode():回传错误码
* errorInfo():回传错误的描述

接下来会举几个例子来说明如何使用PclZip。

PclZip实例1、产生ZIP压缩档
PclZip($zipname):为PclZip constructor,$zipname为PKZIP压缩档的档名。
主要是产生一个PclZip物件,即一个PKZIP压缩档;但此时,只有压缩档产生出来,并做一些检查(例如是否有开启zlib extension…等),除此之外,并没有做其他动作。
create($filelist, [optional arguments list]):将参数$filelist指定的档案或目录(包含当中所有档案与子目录)加入上述所产生的压缩档中。
而非必要的参数则能够修改压缩档内的档案存放路径。
此method可用的参数可以参考网志(www.phpconcept.net/pclzip/man/en/index.php)。

下面的示例说明如何产生PKZIP压缩档(档名为archive.zip),并将file.txt、data/text.txt以及目录folder(包含当中的档案与子目录)加入刚刚产生的archive.zip中:

< ?PHP
include_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');
$v_list = $archive->create('file.txt,data/text.txt,folder');
if ($v_list == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>

下面的示例说明基本上与上例一样产生archive.zip,但在将file.txt与text.txt压缩于其中时,将路径由data/改为install/ ;因此,在archive.zip中这两个档案的路径会是install/file.txt与install/text.txt

< ?PHP
include_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');
$v_list = $archive->create('data/file.txt,data/text.txt',
PCLZIP_OPT_REMOVE_PATH, 'data',
PCLZIP_OPT_ADD_PATH, 'install');
if ($v_list == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>

PclZip实例2、列出压缩档内容
listContent( ) :列出压缩档中的内容,包括档案的属性与目录:

< ?PHP
include_once('pclzip.lib.php');
$zip = new PclZip("test.zip");

if (($list = $zip->listContent()) == 0) {
die("Error : ".$zip->errorInfo(true));
}

for ($i=0; $i<sizeof ($list); $i++) {
for(reset($list[$i]); $key = key($list[$i]); next($list[$i])) {
echo "File $i / [$key] = ".$list[$i][$key]."<br>";
}
echo "<br />";
}
?></sizeof>

上例将会回传结果:
File 0 / [filename] = data/file1.txt
File 0 / [stored_filename] = data/file1.txt
File 0 / [size] = 53
File 0 / [compressed_size] = 36
File 0 / [mtime] = 1010440428
File 0 / [comment] =
File 0 / [folder] = 0
File 0 / [index] = 0
File 0 / [status] = ok

File 1 / [filename] = data/file2.txt
File 1 / [stored_filename] = data/file2.txt
File 1 / [size] = 54
File 1 / [compressed_size] = 53
File 1 / [mtime] = 1011197724
File 1 / [comment] =
File 1 / [folder] = 0
File 1 / [index] = 1
File 1 / [status] = ok

PclZip实例3、解压缩档案
extract([options list]) :解压缩PKZIP中的档案或目录。
[options list]可用的参数可参考网址(www.phpconcept.net/pclzip/man/en/index.php)。这些参数能让使用者在解压缩的时候有更多的选项,譬如指定变更解压缩档案的路径、指定只解压缩某些档案或不解压缩某些档案或者是将档案解压缩成字串输出(可用于readme档)。

下例是一个简单的解压缩档案示例,将压缩档archive.zip内的档案解压缩至目前的目录:

< ?PHP
require_once('pclzip.lib.php');
$archive = new PclZip('archive.zip');

if ($archive->extract() == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>

下例是进阶的解压缩档案使用,archive.zip中所有档案都解压缩于data/中,而特别指明在install/release中的所有档案也直接丢于data/中,而非data/install/ release:

< ?PHP
include('pclzip.lib.php');
$archive = new PclZip('archive.zip');
if ($archive->extract(PCLZIP_OPT_PATH, 'data',
PCLZIP_OPT_REMOVE_PATH, 'install/release') == 0) {
die("Error : ".$archive->errorInfo(true));
}
?>

本文转自 http://www.ccvita.com/59.html

php 生成日历的简单程序

2011年2月18日 没有评论

<?php

$month = $_GET['m']?$_GET['m']:date(‘n’);
$year = $_GET['y']?$_GET['y']:date(‘Y’);

$start_week = date(‘w’,mktime(0,0,0,$month,1,$year));
$day_num = date(‘t’,mktime(0,0,0,$month,1,$year));
$end = false;
?>
<table>
<tr>
<td>星期日</td><td>星期一</td><td>星期二</td><td>星期三</td><td>星期四</td><td>星期五</td><td>星期六</td>
</tr>
<tr>
<?php
for($i = 0; $i<$start_week; $i++)
{
echo “<td></td>”;
}

$j=1;

while($j<=$day_num)
{
echo “<td>$j</td>”;
$week = ($start_week+$j-1)%7;

if($week ==6){
echo “\n\t</tr>\n”;
if($j != $day_num)
echo “\t<tr>\n\t\t”;
else $end = true;
}
$j++;
}
while($week%7 != 6)
{
echo “<td></td>”;
$week++;
}
if(!$end)
echo “\n</tr>”;
?>

</table>

分类: 全部文章, 学习笔记 标签: ,

smarty 函数插件里使用组合变量(变量连接)

2010年9月14日 没有评论

针对函数传递的变量连接问题:
<?PHP
$var['name'] = ‘shooting’;
?>

我想要在smarty中实现这样的效果:
{fck name = “var[shooting]“}

错误的写法:
{fck name = “var[$var.name]“}
这样$var.name就被解析成了Array.name显然是错误的
正确的写法:
{fck name = “var[`$var.name`]“}
“`”这个符号,是键盘左上角,数字1前面的那个符号

分类: 学习笔记 标签: ,

在php中使用 TCPDF 动态创建 PDF [转载]

2010年9月13日 没有评论

简介

TCPDF 是托管在 Sourceforge.net 上最活跃的项目之一,其完全在 PHP 上实现了强大的 PDF 生成引擎。这使得其更容易安装,即使在您无法访问系统目录或编译自己的代码的站点上。同时,通过让您直接查看 PHP 代码生成的结果,而不使用任何中间步骤,这使迭代开发更加容易。

TCPDF 支持一系列有用的图像格式,包括 SVG 矢量格式和位图格式,如 JPEG 和 PNG。一个简单独立的实用工具让您可以处理 TrueType、OpenType、PostScript Type 1 和 CID-0 字体,使它们可以添加到 TCPDF 创建的文档。您可以使用 TCPDF 来生成无数 1-D 和 2-D 条形码格式,且它支持所有常见的 PDF 功能,如书签、文档链接、压缩、注释、文档加密和数字签名。

用 PHP 编写 TCPDF 并使用其页面,这使其易于创建并部署 PDF 生成的 Web 页面。在您使用任何支持 Web 服务器和您最喜欢的 PHP 开发环境开发并部署 TCPDF 时,我将使用如下工具:

  • Eclipse V3.5.2 — 我最新欢的开源开发环境之一,其支持广泛的编程语言和环境。
  • PHP Development Tools V2.2.0 — 适用于 Eclipse 的 PHP 插件。
  • MAMP Pro V1.9 — 适用于 Mac OS X 的方便的程序包,其通过有用的 GUI 前端在一个隔离的环境中提供 Apache、MySQL 和 PHP。虽然 Mac OS X 附带安装 Apache 和 PHP,但我还是选择使用此工具,因为其提供了一系列稳定且容易分离的 Web 服务器/数据库/PHP。
  • TCPDF V5.0.006 — TCPDF 当前的稳定版本。

您可以在 参考资料 部分找到以上所有工具的下载链接。

如果您已经安装了 PHP,我们就来看看如何在您自己的网站上使用 TCPDF。我们将检查安装过程,然后我们将使用 PHP 生成一个显示可能来自任何电子商务站点的发票式样(invoice-style)文档的网页。此后,我们将使用 TCPDF 来创建一个使用类似格式的可打印的 PDF 版发票。


回页首

安装 TCPDF

当您从 Sourceforge.net 下载 TCPDF 时,它提供一个自包含的 ZIP 存档,也就是说,您可以使用您最喜欢的 ZIP 提取工具来解压存档,您最终将获得一个包含您所需要的所有信息的 TCPDF 目录。

如果您将 TCPDF 目录添加到您的 web 文档目录,则您可以通过加载 doc/index.html 访问 TCPDF 文档并通过加载 examples/index.php 文件查看任何示例,这也可在 TCPDF 网站上找到(请参考 参考资料)。

然而在您可以查看示例以前,您需要配置您的 TCPDF 安装。


回页首

配置 — 类 UNIX 系统

如果您正在类 UNIX® 系统上安装 TCPDF,则您需要更改文件模式,因为它们并没有全部被标记为可执行。在 Microsoft® Windows® 系统上存在一个创建 TCPDF 存档的副作用。幸运的是,很容易在来自 shell 的一个失衡中调整这些(请参考 清单 1)。您还需要确保缓存和图像目录是可写入的,因为 TCPDF 将在那里存储临时文件。

下一步,您需要将文件分配给用户和组 web 服务器;虽然这通常是用户 www 和组 www,但是这将取决于您的系统。如果您正在您的个人网站领域以外运行 TCPDF,(在您的主目录下通常是 public_html),则您可以跳过此步骤。
清单 1. 调整文件模式和所有权

$ cd tcpdf
$ find . -type f | xargs chmod -x
$ chmod +w cache images
$ chown -R www:www .

请注意命令可能使用 . 代替 : 来在一些系统上分离用户和组;如果出现问题,则检查其文档详细资料。


回页首

适用于每个人的配置

使用您最喜欢的文本编辑器,加载 config/tcpdf_config.php 文件。这就是 TCPDF 的配置设置并让您控制库的默认设置,并告诉它如何找到自己的支持文件。

在 tcpdf_config.php 中您想要变更的设置包括:

  • PDF_PAGE_FORMAT — 如果您不使用公制页面格式,则设置其为 letter。除非您手头有一些非常奇特方法,否则 TCPDF 可能比您的打印机支持更大的页面尺寸。
  • PDF_UNIT — 如果您想用点而不是毫米来布置您的 PDF 文档,则设置其为 pt
  • PDF_CREATORPDF_AUTHOR — 一旦您的 PDF 生成代码忘了设置它们,则默认文档创建者和作者。

您可以在您的 PHP 代码中调整这些设置中的任意一个,如果无法确定也无需担心(例如,如果您在此处设置的是像模式文档布局,您仍然可以创建景观文档)。

假设您没有移动文件和目录远离其初始位置,则通过默认配置设置,TCPDF 应该没有呈现任何其附带示例的问题。

在这一点上,您可以加载示例文件以确保您拥有一个正在运行的 TCPDF 安装。让我们使用它来创建一个可打印版的发票。


回页首

创建发票

在您创建了电子商务网站以后,您的客户将订购一些物品,而您将收取他们的货款。虽然这很不错,但是他们将想得到某种发票,以防订单错误或他们的信用卡公司搞混了付款,。

让我们制作一个合理美观的发票网页,这样他们可以看到他们已经订购了什么和您将要向他们收取什么。


回页首

第一个版本 — Web 页面

使用我最喜欢的 PHP 开发环境,我已经创建了一个新的发票文件夹,其包含如下文件:

  • Invoice.php — PHP 生成发票
  • Invoice.css — CSS 式样的发票
  • Azuresol_OnyxTree-S.png — Azuresol 的 “OnyxTree S”,您将其用作您公司的标志(来自 iconfinder.com Web 站点的免费图标(请参考 参考资料))
  • gentleface_print.png — gentleface 的 “Print”,您将使用其触发 PDF 生成(来自 iconfinder.com 的另一个免费图标)

在 Invoice.php 内部,检查看看是否使用 PDF 参数调用页面(请参考 清单 2)。如果不是,用户想要一个正常 web 页面,这样您就可以使用 generateHTML 函数(请参考 清单 3)显示页面。稍后您将看到 generatePDF 函数,但是可以肯定使用它来生成发票数据的 PDF 没任何问题。
Listing 2. 页面生成控制代码

if( array_key_exists( 'PDF', $_REQUEST ) ) {
    generatePDF( $invoiceData );
} else {
    generateHTML( $invoiceData );
}

$invoiceData 阵列拥有所有发票数据;虽然您将直接在 Invoice.php 上创建它,但是您可以设想数据来自于数据库、web 服务或某种网上购物车系统。
清单 3. 生成 HTML

function generateHTML( $data ) {
?>
... HTML code was here ...
<?php
    foreach( $data['items'] as $item ) {
        echo '<tr>' . "\n";
        echo '    <td>' . $item[0] . "</td>\n";
        echo '    <td>' . $item[1] . "</td>\n";
        echo '    <td>' . $item[2] . "</td>\n";
        echo '    <td>' . $item[3]. "</td>\n";
        echo "</tr>\n";
    }
?>
... HTML code was here ...
<?php
    echo '<td>' . $data['total'] . "</td>\n";
?>
... HTML code was here ...
<?php
    echo 'Invoice prepared for ' . $data['user'] . ' on ' . $data['date'] . "\n";
?>
... HTML code was here ...
<?php

}

为了简单明了我已经删掉了此处所有的 HTML 标记代码;您可以在位于 CreatingPDFs-Invoice.zip 存档文件中的 Invoice.php 上看到它, CreatingPDFs-Invoice.zip 存档文件可以在 下载 部分找到。

使用传递给函数的发票信息作为 $data,创建一个包含每个项目一行的表、及其数量、单价和总价的表。在表的末尾,添加一个包含订单的总成本的行。页脚包含用户 ID 和发票生成的日期/时间。

当然,简单明了的事情,以及您在自己站点上实现它的时候所面临的主要挑战,将与您的数据源互动,并获得恰到好处的 CSS 式样。
图 1. 光彩夺目的网页发票
截图显示了一个有吸引力的可打印发票示例;Sumatra Special 的最大数量为 24,而其他的则处于 1 到 5 之间

我完全虚构了一家提供优良咖啡和茶的 South Seas Pacifica 公司,显然我对 Sumatran 品种深深的吸引了。至少他们的价格很吸引人!

右下角的打印机图标是诱人的,您希望能够有单击那里并获得打印发票。这里就是 TCPDF 的用武之地。并不只是打印网页,您将为我们尊贵的客户提供一个时髦的 PDF 版本,这会使他们在轻松的状态下完成打印。


回页首

第二个版本 — PDF

现在,您的网页发票看起来很好,您需要创建可以打印的 PDF 版本。

回忆 清单 2,将 PDF 参数 (http://…/Invoice.php?PDF) 与 Invoice.php 页面一起加载将调用具有相同数据的 generatePDF 函数(请参考清单 4)。
清单 4. 生成 PDF 发票

function generatePDF( $data ) {
    # Create a new PDF document.
    $pdf = new InvoicePdf( $data, 'P', 'pt', 'LETTER' );

    # Generate the invoice.
    $pdf->CreateInvoice();

    # Output the PDF document.
    $pdf->Output( 'Your_Invoice.pdf', 'D' );
}

generatePDF 函数创建了一个 InvoicePdf 对象,调用其 CreateInvoice 方法,然后发送一个名为 Your_Invoice.pdf 的下载 PDF 文档给用户的浏览器。虽然这看起来非常简单,但是隐藏了必须自己创建 InvoicePdf 类的事实,且需要复制原始发票式样。让我们来看看这是如何进行的。

InvoicePdf 类扩展了 TCPDF 的 TCPDF 类,这是主 PDF 生成引擎。在构造函数(请参考 清单 5)中,使用传入的 $orientation(页面方向)、$unit(计量单位)和 $format(页 面大小)初始化父类。TCPDF 构造函数的最后三个参数表明输入的是 Unicode(默认为 Ture),已生成 PDF 的字符编码格式是 UTF-8,且您不应使用磁盘缓存 (False)。虽然在创建 PDF 时,磁盘缓存减少了内存占用,但是速度变得更慢了。因为我们的文件不大也不复杂,所以无需权衡这一点。

在初始化父类以后,将参考存储到发票数据以便今后使用。下一步,使用 SetMargins 方法将页边距设置为宽度 72 点、高度 36 点。SetMargins 最终参数表明您正在用自己的值来重写默认页边距。使用 SetAutoPageBreaks 方法,可在从底部算起有 36 点高时告知 TCPDF 自动创建新页面。
清单 5. InvoicePdf 类构造函数

function __construct( $data, $orientation, $unit, $format ) {
    parent::__construct( $orientation, $unit, $format, true, 'UTF-8', false );

    $this->invoiceData = $data;

    # Set the page margins: 72pt on each side, 36pt on top/bottom.
    $this->SetMargins( 72, 36, 72, true );
    $this->SetAutoPageBreak( true, 36 );

    # Set document meta-information
    $this->SetCreator( PDF_CREATOR );
    $this->SetAuthor( 'Chris Herborth (chrish@pobox.com)' );
    $this->SetTitle( 'Invoice for ' . $this->invoiceData['user'] );
    $this->SetSubject( "A simple invoice example for 'Creating PDFs on
the fly with TCPDF' on IBM's developerWorks" );
    $this->SetKeywords( 'PHP, sample, invoice, PDF, TCPDF' );

    //set image scale factor
    $this->setImageScale(PDF_IMAGE_SCALE_RATIO); 

    //set some language-dependent strings
    global $l;
    $this->setLanguageArray($l);
}

在建立边距以后,设置 PDF 文档元信息。这将显示在您最喜欢的 PDF 查看器中的文档属性窗口。这些仅仅是字符串,因此您可以将它们设置为任何对您的应用程序有意义的信息。

使用 setImageScale 方法,在 TCPDF 的配置文件中使用默认图像缩放比例设置。这是用于将位图图像的大小从像素大小调整为适合的页面。

最后,使用 setLanguageArray 来为 PDF 文件设置一些语言相关的字符串;通过 TCPDF 主配置,这些会在特定语言配置文件中定义。

清单 6 中,您重写了 Header 方法,其被调用以便生成每一个页面的标题内容。首先,定义一些变量。以 14 点的 bigFont 大小开始,您会计算出商标图像的相对大小和相对于 bigFont 大小的正常文本大小。然后您将深入 TCPDF 调用。

ImagePngAlpha 方法插入放置在其左上角宽 72 点、高 32 点的商标图像,其与您以前的边距设置相匹配。因为它是一个正方形的图像,所以您可以指定相同的宽度和高度(已计算的 $imageScale)。您将要说明它是一个 PNG 图像,因为此调用实际可以插入 PNG 和 JPEG 图像(如果在您的 PHP 安装中已安装了 GD 库,则其也可以加载任何由 GD 支持的图像)。下一步,指定一个空值,因为您没有为此图像添加 PDF 链接(通过 AddLink 方法创建)目标。再下一步,使用 T 来说明您想在图像区域的右上角制定下一个 PDF 对象。最后,告知 TCPDF 不要调整图像大小,既保持初始的 72 dpi(一个通用的屏幕分辨率),且图像在页面上应该左对齐。

显然,ImagePngAlpha 方法对如何在 PDF 文档中将图像添加到页面的问题上给予您大量的控制(请参考清单 6)。
清单 6. 页面标题的生成

public function Header() {
    global $webcolor;

    # The image is this much larger than the company name text.
    $bigFont = 14;
    $imageScale = ( 128.0 / 26.0 ) * $bigFont;
    $smallFont = ( 16.0 / 26.0 ) * $bigFont;

    $this->ImagePngAlpha('Azuresol_OnyxTree-S.png', 72, 36, $imageScale,
$imageScale, 'PNG', null, 'T', false, 72, 'L' );
    $this->SetFont('times', 'b', $bigFont );
    $this->Cell( 0, 0, 'South Seas Pacifica', 0, 1 );
    $this->SetFont('times', 'i', $smallFont );
    $this->Cell( $imageScale );
    $this->Cell( 0, 0, '', 0, 1 );
    $this->Cell( $imageScale );
    $this->Cell( 0, 0, '31337 Docks Avenue,', 0, 1 );
    $this->Cell( $imageScale );
    $this->Cell( 0, 0, 'Toronto, Ontario', 0, 1 );

    $this->SetY( 1.5 * 72, true );
    $this->SetLineStyle( array( 'width' => 2, 'color' =>
array( $webcolor['black'] ) ) );
    $this->Line( 72, 36 + $imageScale, $this->getPageWidth() - 72, 36
+ $imageScale );
}

在标题上放置商标图像以后,设置字体(粗体 Times,使用您的 bigFont 大小),然后创建一些单元格来存放公司的名称和地址信息。这些单元格在 HTML 上包含文本,而且有点像表格单元格。Cell 方法采用这些参数(实际上更多;参考 TCPDF 文档获取完整列表):

  • Width — 单元格宽度;如果设置为 0,则单元格一直扩展到右侧边距(或者如果您使用的是从右到左的语言,则扩展到左侧边距)。
  • Height — 单元格高度;如果设置为 0,则单元格高度将扩展,以便能放得下内容。
  • Text — 该文本在单元格内绘制,使用当前的字体和颜色设置。
  • Border — 说明是否边界应该根据单元格制定。在这种情况下,由于您正在使用 0,所以您无需任何边界。您也可以传递 1 来根据单元格制定完整的边界,或字符串以便说明特定的边界。
  • Position — 说明何处创建下一个单元格;1 表明您需要其在下一行的开始出显示,但是您可以使用 0 在此单元格旁边添加下一个单元格,或者 2 以停留在当前的 X 坐标并移到下一行。

最后,我们的 Header 方法在标题的底部绘制了一条两点黑线,一直穿过页面的内容区域。图 2 显示了将如何在页面上查看,如 Mac OS X 的 预览应用程序所呈现的那样。
图 2. 打印标题,就像网页标题
截图对左边的地址显示了带有图形商标的标题,名称使用大的、粗体的字体,且地址使用斜体

现在您已经创建了一个原始标题的合理副本,您也需要重写 Footer 方法,以便于您生成页脚。这非常简单,只包含用户 ID 和发票信息,其通过另外一个两点黑线从剩余的页面中分离出来。

您尚未看到此方法的唯一部分正在使用使用一个负值调用 SetY 方法。在您这样做的时候,相对于页面的底部设置当前的 Y。在这里,您将要为页面页脚留下大量的空间,以确保您的绘制不太接近底部边距(请参考清单 7)。
清单 7. 页面页脚的生成

public function Footer() {
    global $webcolor;

    $this->SetLineStyle( array( 'width' => 2, 'color' =>
array( $webcolor['black'] ) ) );
    $this->Line( 72, $this->getPageHeight() - 1.5 * 72 - 2,
$this->getPageWidth() - 72, $this->getPageHeight() - 1.5 * 72 - 2 );
    $this->SetFont( 'times', '', 8 );
    $this->SetY( -1.5 * 72, true );
    $this->Cell( 72, 0, 'Invoice prepared for ' .
$this->invoiceData['user'] . ' on ' . $this->invoiceData['date'] );
}

在您创建页面时,显示出来的就像发票的网络版,只是减去了打印机的图标。您已经中断了此操作,因为这是打印版本(它是多余的)。图 3 得出了结果。
图 3. 已打印的页脚
截图显示了页脚,其对带有收件人、时间和日期的详细信息用粗体水平线标出

在这一点上,您拥有附带美观的页眉和页脚的空白页。您需要为此添加实际的发票内容,这样做很有用。

在使用 AddPage 方法启动新的页面以后(在这种情况下,这是唯一的页面),将字体设置为 11 点 Helvetica 并将插入点从页面的顶部移动到 144 点处。在表开始以前,这会在页眉以下给我们留出一个小空间。

下一步,要计算您将需要使表居中的缩进量,这基于页面宽度、两个 72 点边距、一个宽列和三个正常列。

在此之后,您将使用以前计算出的值并描绘出每个单元格的完全边界,来创建一系列单元格以呈现列标题。您还要右对齐数字列的标题因为它们通过值进行排列。在标题单元格的最后,您要调用 Ln 方法以便向下移动到下一行的开始。

通过在发票上迭代项目的 foreach 循环,您为每一个内容行进行同类型的布局(请参考清单 8)。
清单 8. 页面内容的生成

public function CreateInvoice() {
    $this->AddPage();
    $this->SetFont( 'helvetica', '', 11 );
    $this->SetY( 144, true );

    # Table parameters
    #
    # Column size, wide (description) column, table indent, row height.
    $col = 72;
    $wideCol = 3 * $col;
    $indent = ( $this->getPageWidth() - 2 * 72 - $wideCol - 3 * $col ) / 2;
    $line = 18;

    # Table header
    $this->SetFont( '', 'b' );
    $this->Cell( $indent );
    $this->Cell( $wideCol, $line, 'Item', 1, 0, 'L' );
    $this->Cell( $col, $line, 'Quantity', 1, 0, 'R' );
    $this->Cell( $col, $line, 'Price', 1, 0, 'R' );
    $this->Cell( $col, $line, 'Cost', 1, 0, 'R' );
    $this->Ln();

    # Table content rows
    $this->SetFont( '', '' );
    foreach( $this->invoiceData['items'] as $item ) {
        $this->Cell( $indent );
        $this->Cell( $wideCol, $line, $item[0], 1, 0, 'L' );
        $this->Cell( $col, $line, $item[1], 1, 0, 'R' );
        $this->Cell( $col, $line, $item[2], 1, 0, 'R' );
        $this->Cell( $col, $line, $item[3], 1, 0, 'R' );
        $this->Ln();
    }

    # Table Total row
    $this->SetFont( '', 'b' );
    $this->Cell( $indent );
    $this->Cell( $wideCol + $col * 2, $line, 'Total:', 1, 0, 'R' );
    $this->SetFont( '', '' );
    $this->Cell( $col, $line, $this->invoiceData['total'], 1, 0, 'R' );
}

代码的最后一位呈现总行数。这演示了您如何可以更容易地在单元格之间变更字体式样(通过调用 SetFont 方法来打开或关闭粗体)。第一个文本单元格的宽度被设置横跨表的前三列,因为您需要发票总数出现在最后一列的底部。

一旦您完成后,发票项目表看起来将非常的棒(请参考图 4)。
图 4. 发票上的项目
附带数量、价格和总数的项目格式化清单的截图

通过逻辑地布局文本单元格,您已经用适合打印的格式重新创建了初始的网页。在无需变更网页本身或任何基础数据的情况下,TCPDF 让您将创建 PDF 的支持添加到您现存的 PHP 网页上。


回页首

结束语

本文向您介绍了 TCPDF,它是一种用于生成 PDF 文档的流行 PHP 库。TCPDF 无需额外的库就能执行此操作,并使其作为您现有 PHP 网站的一部分易于安装。本文向您显示了在类 UNIX 系统中安装并配置 TCPDF 的概述。然后您创建了一个简单的基于 Web 的发票,类似于您可能在一家从事异国热饮的电子商务站点上所看到的诸如此类的事情。

一旦您拥有一个看上去像专业发票的网页,您就可以扩展 TCPDF 类来生产一个 PDF 版本的发票,即客户可以轻松地下载或打印。重写 HeaderFooter 方法让我们用相似的方式建立页面,然后您可以编写一个附加方法来布置发票项目作为一个表。


回页首

下载

描述 名字 大小 下载方法
文章源代码 os-tcpdf-CreatingPDFs-Invoice.zip 21KB HTTP

关于下载方法的信息

本文转载自IBM.COM

http://www.ibm.com/developerworks/cn/opensource/os-tcpdf/index.html?ca=drs-

ajax 返回的innerHTML里面的javascript代码执行问题及Demo [转载]

2010年9月13日 没有评论

解决了一个困扰我许久的问题,用过AJAX的人可能会知道,当把从服务器返回xhr.responseText的数据设定给innerHTML时, 里面的JS代码并不能够执行,查了很多资料,终于找到一个简单而且可行的办法,就是把JS代码封装到一个DIV中通过xhr.responseText打 包给innerHTML,然后把<script></script>标签扒下去,在通过eval()函数执行JS代码(思想转载 自这 里),这里以弹出对话框为例,示例如下:

<!–这是innerHTML的内容–>

<div id=”a”>

<script>

alert(“aa”);

<script>

</div>

<!–这是调用JS的主页内容–>

var pageInfo = xhr.responseText;

document.getElementById(“pageInfo”).innerHTML = pageInfo;

eval(document.getElementById(“aa”).innerHTML.replace(/<script>|<\/script>/,”)); //将<script>标签替换掉,这样才能被eval()函数执行

结果出现了显示”aa”的对话框!

但是问题又出现了,如果执行2句或者两句以上的JS代码就会出现错误了!

这样我们就可以把需要执行的多行JS代码封装成一个方法直接放到需要调用该JS代码的主页面里,然后再被调用的页面里写上这个方法名就可以了,这里 以弹出2个对话框为例,示例如下:

<!–这是innerHTML的内容–>

<div id=”a”>

<script>

doit();

<script>

</div>

<!–这是调用JS的主页内容–>

var pageInfo = xhr.responseText;

document.getElementById(“pageInfo”).innerHTML = pageInfo;

eval(document.getElementById(“aa”).innerHTML.replace(/<script>|<\/script>/,”)); //将<script>标签替换掉,这样才能被eval()

function doit(){

alert(“aa”);

alert(“bb”);

}

结果出现了”aa” “bb”两个对话框!

这样就完美解决了ajax 返回的innerHTML里面的javascript代码执行问题,一些复杂的JS函数都可以,而且一些jQuery的方法也可以哦!

这是在网上找的资料,依据以此,我写了例子来 验证:

Defalut.aspx

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”AjaxJsTestWeb._Default” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>无标题页</title>
<script language=”javascript” type=”text/javascript” >

function getRequest() {
http_request = false;
if (window.XMLHttpRequest) {
//对于Mozilla﹑Netscape﹑Safari等浏览器,创建XMLHttpRequest
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
//如果服务器响应的header不是text/xml,可以调用其它方法修改该header
http_request.overrideMimeType(‘text/xml’);
}
} else if (window.ActiveXObject) {
// 对于Internet Explorer浏览器,创建XMLHttpRequest
try {
http_request = new ActiveXObject(“Msxml2.XMLHTTP”);
} catch (e) {
try {
http_request = new ActiveXObject(“Microsoft.XMLHTTP”);
} catch (e) {}
}
}
return http_request;
}
//获得Url 的responseText

function getResponseText(url)
{
http_request=getRequest();
http_request.open(‘GET’, url, false);
http_request.send(null);

if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseText;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
return requestdoc;
}
//获得Url 的responseXML

//代码片段
function getResponseXml(url)
{
http_request=getRequest();
http_request.open(‘GET’, url, false);
http_request.send(null);

if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseXML;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
return requestdoc;
}

function TestAjaxJs()
{
http_request=getRequest();
http_request.open(‘GET’, “containjsText.aspx”, false);
http_request.send(null);

if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseText;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
// debugger;
document.getElementById(“divJsText”).InnerHTML=requestdoc;
alert( document.getElementById(“divJsText”).InnerHTML);
var str;
str=document.getElementById(“divJsText”).InnerHTML.replace(/<script language=’javascript’>|<\/script>/,”);
str=str.replace(/<\/script>/,”);

alert(str);
eval(str);
// document.write(document.getElementById(“divJsText”).InnerHTML);
return false;
}

</script>
</head>
<body>
<form id=”form1″ runat=”server”>
<div>
<div id=”divJsText” ></div>
<asp:Literal ID=”ltrJsText” runat=”server”></asp:Literal><asp:Label ID=”lblJsText” runat=”server”></asp:Label>
<asp:Button ID=”btnAjax” runat=”server” Text=”Ajax请求返回带有JS脚本的文本 JS脚本执行”  OnClientClick=”return TestAjaxJs();”/>
</div>
</form>
</body>
</html>

ContainJsText.aspx.cs 代码页面

两种情况:

(1)多个JS语句

namespace AjaxJsTestWeb
{
public partial class ContainJsText : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder jsText = new StringBuilder();
jsText.AppendLine(“<script language=’javascript’>function doit(){alert(‘哈哈,我执行了啊!’);alert(‘哈哈,我再次执行了啊!’);} doit();</script>”);
Response.Write(jsText.ToString().Trim());
Response.End();
}
}
}

(2) 就一个js语句

namespace AjaxJsTestWeb
{
public partial class ContainJsText : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder jsText = new StringBuilder();
jsText.AppendLine(“<script language=’javascript’>alert(‘哈哈,我执行了啊!’)</script>”);
Response.Write(jsText.ToString().Trim());
Response.End();
}
}
}

转自 http://www.taotechinfo.com/collect/2010724/n807115732.html

分类: 学习笔记 标签: , , ,

再写关于无限分类

2010年4月6日 1 条评论

数据表里的结构还是非常简单
三个字段id , parentid ,name
算法也很简单递归,以前用递归的时候很傻,应该说极傻,因为在递归中通过查询数据表来获得子类的所有,最近开窍了,想到了一个地球人都能想得到的方法,下面是代码,一个class

<?php
class Tree {

 /**
  * 从数据库查询出的所有分类信息
  * @var array
  */
 var $arr;
/**
 * 如下格式
 *  var $arr = array(
 1 => array(‘id’=>’1′,’parentid’=>0,’name’=>’一级栏目一’),
 2 => array(‘id’=>’2′,’parentid’=>0,’name’=>’一级栏目二’),
 3 => array(‘id’=>’3′,’parentid’=>1,’name’=>’二级栏目一’),
 );*/

 /**
  * 输出结构
  * @var array
  */
 var $tree = array();
 /**
  * 树形递归的深度
  * @var int
  */
 var $deep = 1;

 /**
  * 生成树形的修饰符号
  * @var array
  */
 var $icon = array(‘│’,'├’,'└’);
 /**
  * 生成指定id的下级树形结构
  * @param int $rootid 要获取树形结构的id
  * @param string $add 递归中使用的前缀
  * @param bool $parent_end 标识上级分类是否是最后一个
  */
 function getTree($rootid = 0,$add = ”,$parent_end =true){
  $is_top = 1;
  $child_arr = $this->getChild($rootid);
  if(is_array($child_arr)){
   $cnt = count($child_arr);
   foreach($child_arr as $key => $child){
    $cid = $child['id'];
    $child_child = $this->getChild($cid);
    if($this->deep >1){
     if($is_top == 1 && $this->deep > 1){
      $space = $this->icon[1];
      if(!$parent_end)
      $add .=  $this->icon[0];
      else $add .= ‘&nbsp;&nbsp;’;
     }

     if($is_top == $cnt){
      $space = $this->icon[2];
      $parent_end = true;
     }else {
      $space = $this->icon[1];
      $parent_end = false;
     }
    }
    $this->tree[] = array(‘spacer’=>$add.$k.$space,
           ‘name’=>$child['name'],
           ‘id’=>$cid
    );
    $is_top++;

    $this->deep++;
    if($this->getChild($cid))
    $this->getTree($cid,$add,$parent_end);
    $this->deep–;

   }

  }
  return $this->tree;
 }

 /**
  * 获取下级分类数组
  * @param int $root
  */
 function getChild($root = 0){

  $a = $child = array();
  foreach($this->arr as $id=>$a){
   if($a['parentid'] == $root){
    $child[$a['id']] = $a;
   }
  }
  return $child?$child:false;
   
 }
 /**
  * 设置源数组
  * @param $arr
  */
 function setArr($arr = array()){
  $this->arr = $arr;
 }
}

通过一次查询把结构保存进一个数组,再数组进行递归运算,无疑极大的提高了程序运行效率
使用代码很简单,得到查询结构后setArr,直接调用getTree, 皆可以得到按照程序排序号并带有前缀修饰等信息的数组,到这里通过foreach这个数组就可以得到如下的树状列表了

水果   
  ├香蕉
  ├苹果
  │├红富士
  │└海南苹果
  └桃子

smarty中使用fckeditor

2010年4月6日 没有评论

网上最常用的做法是先在php中调用fckeditor类的createHtml方法生成一段html,直接assign给一个samrty变量即可

这里我通过smarty的插件机制,可以更方便的在smarty中集成fckeditor,在smarty的plugin目录中新建文件function.fck.php

内容如下

<?php
function smarty_function_fck($params, &$smarty)
{
 if(!isset($params['InstanceName']) || empty($params['InstanceName']))
 {
  $smarty->trigger_error(‘fckeditor: required parameter “InstanceName” missing’);
 }

 static $base_arguments = array();
 static $config_arguments = array();

 if(!count($base_arguments))
  $init = TRUE;
 else
  $init = FALSE;

 if(isset($params['BasePath']))
 {
  $base_arguments['BasePath'] = $params['BasePath'];
 }
 else if(empty($base_arguments['BasePath']))
 {

//这里设置默认的fck所在的目录,相对于要使用fck的程序的目录
  $base_arguments['BasePath'] = ‘../plugins/fckeditor/’;
 }

 $base_arguments['InstanceName'] = $params['InstanceName'];

 if(isset($params['Value'])) $base_arguments['Value'] = $params['Value'];
 if(isset($params['Width'])) $base_arguments['Width'] = $params['Width'];
 if(isset($params['Height'])) $base_arguments['Height'] = $params['Height'];
 if(isset($params['ToolbarSet'])) $base_arguments['ToolbarSet'] = $params['ToolbarSet'];
 if(isset($params['CheckBrowser'])) $base_arguments['CheckBrowser'] = $params['CheckBrowser'];
 if(isset($params['DisplayErrors'])) $base_arguments['DisplayErrors'] = $params['DisplayErrors'];

 // Use all other parameters for the config array (replace if needed)
 $other_arguments = array_diff_assoc($params, $base_arguments);
 $config_arguments = array_merge($config_arguments, $other_arguments);

 $out = ”;

 if($init)
 {
  $out .= ‘<script type=”text/javascript” src=”‘ . $base_arguments['BasePath'] . ‘fckeditor.js”></script>’;
 }

 $out .= “\n<script type=\”text/javascript\”>\n”;
 $out .= “var oFCKeditor = new FCKeditor(‘” . $base_arguments['InstanceName'] . “‘);\n”;

 foreach($base_arguments as $key => $value)
 {
  if(!is_bool($value))
  {
   // Fix newlines, javascript cannot handle multiple line strings very well.
   $value = ‘”‘ . preg_replace(“/[\r\n]+/”, ‘” + $0″‘, addslashes($value)) . ‘”‘;
  }
  $out .= “oFCKeditor.$key = $value; “;
 }

 foreach($config_arguments as $key => $value)
 {
  if(!is_bool($value))
  {
   $value = ‘”‘ . preg_replace(“/[\r\n]+/”, ‘” + $0″‘, addslashes($value)) . ‘”‘;
  }
  $out .= “oFCKeditor.Config[\"$key\"] = $value; “;
 }

 $out .= “\noFCKeditor.Create();\n”;
 $out .= “</script>\n”;

 return $out;
}
?>

使用代码

{fck InstanceName=”body”  BasePath=“../plugins/fckeditor/” Value=$news_info.body Width=”100%” Height=”400″}
可以自定义参数 ToolbarSet-使用的工具栏, BasePath-fck相对于当前脚本的目录,InstanceName-要赋予的$_POST变量名, Value-默认值等