存档

文章标签 ‘程序分析’

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中使用 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-

判断一个数是否是2的次方

2010年1月20日 1 条评论

经典的:
int IsPower(unsigned n)
{
if(n==0)
return 1;
while(n)
{
if(n%2==0)
{
n = n/2;
if(n==1)
return 1;
}
else return 0;
}
}
不必解释

超强的:
int IsPower(unsigned n)
{
return (n&&!(n&(n-1)));
}

解释:
如果一个数是2的次方,则转成2进制是首位为1,其余都为0,比如:
2(10) 4(100) 8(1000) 16(10000)……

如果一个数和全1的相与还是等于自己,则这个数就是2的次方

n&(n-1)计算的是全零的情况,故!(n&(n-1))是全1的情况

转自 http://hi.baidu.com/mzyse/blog/item/6b5f5517d5d9d30cc83d6da3.html

php变量类型?内存指针?

2009年10月28日 没有评论

这个问题在C/C++语言中是个常见的问题,然而在php这种弱类型的语言中却并不被关注,个人觉得在php中探讨这个问题有点空中楼阁的感觉,因为php本身就是一种运行在Zend engine解释器基础上的一种语言,如果非要探讨这个问题,需要了解下php在zend引擎上的运行原理。
我们都知道C是强类型的语言,定义了的变量,在它的生命周期类就无法改变的,php这种弱类型的语言怎么能在C中完美运行呢?实际上php中的变量,在C中都是通过一个结构体来表示的,此结构体的定义是:

typedef struct _zval_struct {
zvalue_value value;
zend_uint refcount;
zend_uchar type;
zend_uchar is_ref;
} zval;

其中zvalue_value是真正保存数据的关键部分zvalue_value又是个联合体(union),结构如下

typedef union _zvalue_value {
long lval;
double dval;
struct {
char *val;
int len;
} str;
HashTable *ht;
zend_object_value obj;
} zvalue_value;

这个联合体中保存着一个弱类型的值常用的多种类型
zend engine根据 struct _zval_struct中的type来取union _zvalue_value中相应的单元,这就实现了php的多种类型间的自动转化。

总结,在php中探讨内存指针的问题没有意义,这应该是C/C++爱好者需要深入研究的问题!
深入内容参考 http://www.laruence.com/2008/08/22/412.html

php产生验证码完整案例

2009年8月28日 没有评论

今天继续开发zen cart项目,加上了验证码的功能,考虑到需要较高的安全性,自己手工写了个小程序,功能还算全面,自动检测背景和字体,并随机选取背景图片中的一块范围,随机使用字体,显示验证字符串时随机显示字体大小,字符间距,字符颜色等。以下是程序代码。
validimg.php文件

<?php
/**
* Class for Validate image
* @author  zcs
* @version 1.0-20090828
*/

session_start();
class validimg
{
//背景图片目录
var $backgroundpath = ‘validbg’;
//生成验证码宽度
var $width =’80′;
//生成验证码高度
var $height =’25′;
//背景
var $background;
//验证文本
var $text=’abcd’;
//字体目录
var $fontpath = ‘validbg’;
//字体
var $font=’simhei.ttf’;
//字体宽度
var $font_width = ’20′;

function validimg($text)
{
$this->text = $text;
//随机选取一个背景文件
$bgdir =  @dir($this->backgroundpath);
while(false !== ($image = $bgdir ->read()))
{
if($image != ‘.’ && $image != ‘..’ && $this->checktype($image) != false)
{
$backgroundarr[] = $image;

}
}
$bgdir->close();
//随机选取一个字体文件
$fonts =  @dir($this->fontpath);
while(false !== ($font = $fonts ->read()))
{
if($font != ‘.’ && $font != ‘..’ && $this->checktype($font,’FONT’) != false)
{
$fontsarr[] = $font;
}
}
$fonts->close();
$this->font = $fontsarr[array_rand($fontsarr,1)];
$this->background = $backgroundarr[array_rand($backgroundarr,1)];

$this->output();
}

//创建背景图像handdle
function createbackground()
{
switch ($this->checktype($this->background))
{
case ‘jpg’:
$bghanddle = @imagecreatefromjpeg( $this->backgroundpath.’/’.$this->background);
break;
case ‘gif’:
$bghanddle = @imagecreatefromgif( $this->backgroundpath.’/’.$this->background);
break;
case ‘png’:
$bghanddle = @imagecreatefrompng( $this->backgroundpath.’/’.$this->background);
break;
default:
}
return $bghanddle;
}
//检查文件类型
function checktype( $image,$type = ‘IMAGE’)
{
$ext = substr( $image, strrpos($image,’.')+1);
if($type == ‘IMAGE’)
{
if ($ext == ‘jpg’ || $ext ==’gif’ || $ext ==’png’)
return $ext;
else return false;
}else if($type == ‘FONT’)
{
if ($ext == ‘ttf’)
return $ext;
else return false;
}
}
//输出
function output()
{
header(“content-type:image/png;”);
//生成图像
$img = @imagecreatetruecolor( $this->width,$this->height);
$bghanddle = $this->createbackground();
//从背景图像随机位置载入一块作为背景
if($bghanddle)
{
$randx=rand(0,(imagesx($bghanddle) – $this->width));
$randy=rand(0,(imagesy($bghanddle) – $this->height));
}
imagecopy($img,$bghanddle,0,0,$randx,$randy,$this->width,$this->height);
//随机选择角度 字体大小 坐标输出文字
for($i=0;$i<strlen($this->text);$i++)
{
$angle = rand(-30,30);
$fontsize = rand(15,20);
$x = rand($this->font_width*$i,$this->font_width*$i+10);
$color = imagecolorallocate($img, rand(0,255), rand(0,255), rand(0,255));
imagettftext($img,$fontsize,$angle,$x,20,$color,$this->fontpath.’/’.$this->font,substr($this->text,$i,1));
}
imagepng($img);
//释放资源
imagedestroy($img);
imagedestroy($bghanddle);
}
}

new validimg($_SESSION['valid']);
?>

测试文件validtest.php

<?php
/**
* 验证码测试
* @author  zcs
*/
session_start();
$_SESSION['valid']= randstr();
echo $_SESSION['valid'];

//随机生成字符串

function randstr($num=4)
{
$chars = ‘ABDEFGHJKLMNPQRSTVWXYabdefghijkmnpqrstvwxy23456789′;
$randstr=”;
for($i=0;$i<$num;$i++)
{
$randstr.=substr($chars,rand(0,strlen($chars)),1);
}
return $randstr;
}
?>
<img src=”validimg.php” />

Demo http://anfirst.cn/case/validimg/

代码包下载:validimg

zen cart 的sidebox 机制

2009年8月24日 没有评论

zen cart的左右边栏很有特色,由一块一块的sidebox拼合起来的,在模板的sidebox文件夹建立一个sidebox程序,登陆管理后台后,选择外观控制,系统会自动检测到新增加的sidebox程序,并提醒你操作。并把所有的sidebox配置信息存储在layout_boxes的表格中。

程序调用边栏是通过includes/modules 目录下的column_left.php,和column_right.php 控制。分析下源码也非常简单:首页查询layout_boxes数据表,检索出在左栏和或右栏显示的所有sidebox,再直接require 进来 layout_box_name 字段标记的sidebox名称。随便打开一个sidebox的源代码,如系统自带的includes/modules/sideboxes/banner_box.php,banner_box.php只要用来获取sidebox显示所要的数据,再通过require($template->get_template_dir(‘tpl_banner_box.php’,DIR_WS_TEMPLATE, $current_page_base,’sideboxes’),载入显示这个sidebox的模板,其实这个所谓的模板就是生成一个$content的字符串,然后再require($template->get_template_dir($column_box_default, DIR_WS_TEMPLATE, $current_page_base,’common’) . ‘/’ . $column_box_default) 再用一个显示sidebox的公共模板,在$column_box_default中打印出$content的内容,这样一个sidebox就显示完成了!

如何添加一个自己的sidebox?其实很简单,在includes/modules/sideboxes/{模板目录}/  建立一个文件,就是一个sidebox了,可以在后台控制是否显示在默认的左右边栏和排序 。在这个文件中就输出任何内容了,当然可以按照标准的模式,再在includes/templates/{模板目录}/sideboxes 下建立一个模板文件require进来,尽量做到 M/V的分离,这样以后修改也会比较方便!

zen cart的运行过程

2009年8月23日 2 条评论

zencart是典型的单入口程序,所有的程序的url都是index.php?mainpage=XX的形式,通过$_GET['mainpage']载入相应的页面程序。先说首页的输出过程如下:入口index.php->载入初始化文件application_top.php->载入首页默认变量文件mail_template_vars.php->载入公用模板控制文件tpl_main_template.php->载入方框(sidebox)控制文件column_left.php,column_left.php->载入各个sidebox的控制文件和模板->载入首页默认核心部分模板tpl_index_default.php->载入公共页面底部,到这里就完成了首页的显示。其他页面的显示则是在载入include/pages/ $_GET['mainpage']文件下的文件,基本跟首页相同,只是根据不同页面载入不同配置文件和模板。

初次接触zencart,觉得zencart的模板系统异常的复杂,其最大的特点就是覆盖机制,通过其class/template_func.php模板类的get_template_dir方法,按照预先设定的位置按顺序查找模板文件,这种机制极大的提高了模板修改的灵活性,同时避免影响其他的模板和系统程序,也方便了以后的升级,我像扩充下系统默认的模板很简单,拷贝到我自己的模板相应文件夹,想怎么改就怎么改,也不会担心会跟系统不和谐。

以上皆是根据印象所写,文件名也许错误,下次修正。