Symfony Helper select_tag

我们做数据库设计时,会用数字标记某条记录的状态。最简单的例子,一个 gender 字段,是 tinyint 类型,用 1 代表男性,2 代表女性。

在设计 html 页面编辑这条记录时,我们总要写好多 html 代码,很麻烦。

用 Symfony 的 select_tag 可以非常方便地帮我们完成这些复杂的工作。

下面介绍一个实例。

有一个项目,需要提交问题处理记录,表单有一项“优先级”,分为 6 种级别,希望可以用下拉列表进行选择。

select_tag.png

详情请见:

http://wiki.leakon.com/SymfonyHelper-select_tag

Symfony 文档 电子书 PHP Quebec 2007

最近在看 Symfony 的源码,从中体会到很多这个框架背后实现的原理和过程。

其实,我们在讨论框架的时候,不是要把他直接拿来用,而是要研究他优秀的部分,吸取他的经验。

我真是不明白为什么很多搞开发的人那么讨厌框架,那么鄙视框架的性能。

也许,就像我的一个朋友说的那样,有些人在技术上比较保守,不思进取,当别人学新东西的时候,他总是极力反对,原因就是怕别人抢饭碗……

不说那么多了,今天在一个比较牛的下载站,下了很多 Symfony 的文档和一些相关参考资料。

其中有一个 pdf ,是 Symfnoy 创始人 Fabien Potencier 在 Quebec 2007 PHP 大会上演示的文档,制作相当精美,而且用图形整体描述了 Symfony  的主体框架,很赞……

Development-with-Symfony.ppt
doctrine-manual.pdf
symfony-api.chm
symfony-book.pdf
symfony-guide.chm
symfony-PHPQuebec-2007-en.pdf
SymfonyBook.zip

给大家一个压缩包下载,里面包括了上述的几个文件。

希望大家多交流。

http://wiki.leakon.com/ 是我最近刚建立的 Wiki,我会把平时积累的一些经验,尤其是代码部分放在上面。

接触 Symfony 也有将近一年的时间了,我也会把自己总结的 Symfony 的一些开发经验,在 Wiki 上与大家分享。

好啦,现在给大家压缩包的地址:

http://down.leakon.com/SymfonyBook/SymfonyBook.zip

宣传一下 Symfony 的官方网站地址:

http://www.symfony-project.org/

Symfony 温故而知新

使用Symfony的同学,连接数据库时,如果想指定编码,需要在得到数据库Connection的时候发送一条SET NAMES UTF-8语句,以保证统一。

针对这个问题,我以前写过2篇Blog,地址:

里面是通过修改Creole的源码,symfony/vendor/creole/Creole.php,加入一个setUTF8方法。

这个方式管用,但不是最好。

这两天看了Symfony的 Code snippets ,发现很多Symfony的运行机制,看到一个FilterChains,可以由用户添加一个Filter到调用链中,可以在系统初始化时自动运行。

利用这个特点,把设置连接编码的语句,添加到一个filter中,每次自动运行:

<?php
// 首次执行时,设置数据库连接编码为 GBK
class FilterGBK extends sfFilter {
    
public function execute($filterChain) {
        
// execute this filter only once
        
// 这里确保了这几行代码只执行一次
        
if ($this->isFirstCall()) {
            
$connection = Propel::getConnection();
            
$query = 'SET NAMES gbk';
            
$statement = $connection->prepareStatement($query);
            
$statement->executeQuery();
        
}
        
// execute next filter
        
$filterChain->execute();
    
}
}

再编辑 apps/front/config/filters.yml 文件,在开头加入:

FilterGBK:
  class: FilterGBK

这样就可以达到目的,而以前的实现方式需要修改插件源码,无法在一个系统中运行多个Symfony项目。

随着逐渐深入Symfony,并反复查看文档和代码,可以学到很多Web开发的经验和技巧。

这回,深刻体会到了“温故而知新”的内涵。

Symfony Apache Url Rewrite

今天在服务器上新装了apache,把用Symfony开发的后台程序部署到服务器上,发现生产版本的环境无法使用,居然报404 Not Found。

刚开始没想到是什么原因,反复翻文档,检查虚拟主机的配置,和目录权限,以及.htaccess文件,都正确无误。

在自己的Windows环境是好好的,但在服务器上却不行。

后来就拿.htaccess开刀,因为受到一点Apache手册的启发,就是在.htaccess中添加一些错误代码,以检查.htaccess是否正确运行。

其实本来就应该能想到这样做的,只是觉得问题可能出现在其他地方。

果不其然,就是.htaccess中的<IfModule mod_rewrite.c>,在这个分支里面随便写任何东西,都不会起作用。

看来Apache没有正确安装mod_rewrite.so。

一时也不知道如何验证,后来在网上查了半天才查到。

先列一串命令吧:

  • apache/bin/httpd -l
    列出当前环境中安装了哪些module
  • apache2/bin/apxs -c mod_rewrite.c -lgdbm
    在Apache源码路径的modules/mappers/中,可以找到mod_rewrite.c等所有模块的源码,在这个路径执行apache2/bin/apxs(注意,这里的apxs是apache安装的绝对路径),就会自动编译这个模块,生成.so文件到modules/mappers/.libs/,刚才那个mod_rewrite.so就生成在这里
  • apache2/bin/apxs -i -A -n rewrite mod_rewrite.so
    在modules/mappers/.libs/这个目录下执行上面的命令,会在apache2/conf/httpd.conf中加入一行
    #LoadModule rewrite_module     modules/mod_rewrite.so
    注意前面是带#的
  • apache2/bin/apachectl configtest
    检查当前的配置文件语法是否正确,不用等restart不成功再去检查错误了

通过这样几步,检查没问题后,重启apache,mod_rewrite模块就安装完成了。

再打开Symfony的后台,所有页面都可以正确打开。

我通常都在自己的笔记本上开发程序,用xampp套件,很多常用模块都是默认安装好的,使用之前只要把httpd.conf文件中相应模块前面的#去掉就可以了,一下子把程序部署到服务器,很多模块都没装,还真是不适应。

Symfony 限制

发现Symfony的2个限制,其实这个是Propel的限制,Propel是PHP的一个ORM的数据库代码生成器,通过XML或YML文件配置,自动创建针对每个数据库和表的CRUD模型,并有良好的继承关系,真正地以面向对象的方式操纵数据库的每一行每一列。

目前发现2点限制:

  1. 不能适应分表(动态选择表名)
  2. 整型字段不能设置unsigned类型

在设计数据库的时候,采用分表存储,是一个优化性能的好方法, 比如,保存用户的文章,按用户ID,散列到8个表上。这8个表的结构都完全一样,只是表名不一样:tbl_post_0, tbl_post_1, …, tbl_post7。

当前版本的Propel,生成的代码,是和表名紧紧耦合在一起的,也就是说这8个表,会生成8套几乎一摸一样的代码,同样需要写8份schema.xml。

这样很不合理。

应该再抽象出一个机制,考虑结构相同表的统一处理。

Propel的另一个问题就是整数字段不能设置unsigned类型,查了官方的说明,说是PHP的整数类型就是-2的31次方到2的31次方减一。我还没来得及证实,不过这也不是很大的问题。因为,Symfony就是为了从零开始快速开发。一个新项目,数据量从零增加到20多亿条记录,还是需要一些时间的,应该避免项目初期的过度设计。

等你的数据规模达到10亿的时候,考虑找风投给你1000万美元,招人帮你重构吧。

Symfony 如何在项目中使用多个数据库

all:
database1:
class: sfPropelDatabase
param:
dsn: pgsql://foo:bar@hostname/database1

database2:
class: sfPropelDatabase
param:
dsn: mysql://foo:bar@hostname/database2

先建立一个
PROJECT_DIR/config/database1.schema.xml
再建立一个
PROJECT_DIR/config/database2.schema.xml

最后build一下:

$ symfony propel-build-model

$database1_connection_handler = Propel::getConnection(FooPeer::DATABASE_NAME);
$database2_connection_handler = Propel::getConnection(BarPeer::DATABASE_NAME);
Google

Google
LAMP-Linux-redhat LAMP-Apache LAMP-MySQL LAMP-Php Leakon-Wiki Leakon-BBS XueBaoBao Xyoyou