不带Doctrine的Symfony2是什么样?

这是一个奇怪话题,因为Doctrine是Symfony2的几个核心之一(另外几个是DI, Twig, 集成的单元测试).

怎么会突然想到不带Doctrine的Symfony2呢?因为最近用Slim用得很爽,直接是Twig+Slim+PDO,虽然有点阳春白雪,但是用起来果断很爽,比原生写PHP要方便很多,比Symfony2要轻便很多.

仔细对比了一会,最大的区别应该还是Form的处理,换句话说,核心依然是Doctrine,在为没有Doctrine就没有方便的操作Form的接品,这种事情让我突然有一种奇怪的感觉:也许Symfony2走到最后,不只是需要一些代码生成器,更需要一个IDE.

如果使用Symfony2但却不使用Doctrine,会怎么样呢?

相对来说,当再做Symfony2项目时,假如没有Doctrine,那么应该更适合从页面入手,先做一个页面出来,然后考虑需要展示的数据有哪些,再然后呢?做一个简单的数据表,然后在Service中处理一下db操作,写一个单元测试.

这个数据链接要么是写一个pdo的单例,要么是直接从entity manager中获取,用完应该记得关闭.

似乎这样用Symfony2比直接用Doctrine要复杂?

那么是不是说明DI应该配合ORM来用,而不应该直接用?

这个问题在Java时代就开始思考,这么做也许可以,也许不可以,不过Symfony2很适合多人协作,Slim更适合一个人开发.Slim要想多人开发自然也可以,只是分隔性不如Symfony2.

我思考问题太简单了,哪能只考虑这些,可能是因为今天写了一天代码,头有点晕吧.不管了,睡觉,明天再继续.

转载自:http://saharabear.com/weblog/?p=1840

ORM到底是用还是不用?

ORM即Object/Relation Mapping的简写,一般称作“对象关系映射”,在Web开发中最常出没于和关系型数据库交互的地方。接口、中间件、库、包,你都可以这么称呼它。

我们可以结合PHP和MySQL,从ORM的四个核心理念来认识它:

  • 简单:ORM以最基本的形式建模数据。比如ORM会将MySQL的一张表映射成一个PHP类(模型),表的字段就是这个类的成员变量
  • 精确:ORM使所有的MySQL数据表都按照统一的标准精确地映射成PHP类,使系统在代码层面保持准确统一
  • 易懂:ORM使数据库结构文档化。比如MySQL数据库就被ORM转换为了PHP程序员可以读懂的PHP类,PHP程序员可以只把注意力放在他擅长的PHP层面(当然能够熟练掌握MySQL更好)
  • 易用:ORM的避免了不规范、冗余、风格不统一的SQL语句,可以避免很多人为Bug,方便编码风格的统一和后期维护

接下来再通过一个很基本的例子来说明一下ORM的使用,还以PHP和MySQL为例。

user这个数据模型是再普遍不过的了。假设我们有一张user数据表,结构如图:

在OOP中通常我们需要写一个对应的class User来作为user数据表的数据模型:

// 声明class User 
class User{ 
    $id; 
    $name; 
    function create(){/*…*/} 
    function load($id){/*…*/} 
} 
// 使用class User 
$user = new User(); 
$user->name = ‘fancy’; 
$user->create();

但是通过ORM,我们可以不用去声明class User,可以直接继承ORM提供的工厂类,比如:

// 直接使用!对于熟悉MVC的亲知道这个意义之所在! 
$user = new ORM(‘user’); 
// ORM都有自己的规则,这里直接使用了MySQL的表名 
$user->name = ‘fancy’; 
// MySQL的表的字段就是$user对象的成员变量 
$user->save(); 
// 掉用ORM提供的接口函数

ORM一般都针对数据模型提供了一下常见的接口函数,比如:create(), update(), save(), load(), find(), find_all(), where()等,也就是讲sql查询全部封装成了编程语言中的函数,通过函数的链式组合生成最终的SQL语句。

所以由这些来看,ORM对于敏捷开发和团队合作开发来说,好处是非常非常大的。这里就罗列一下我想到的ORM显著的优点:

  • 大大缩短了程序员的编码时间,减少甚至免除了对Model的编码
  • 良好的数据库操作接口,使编码难度降低,使团队成员的代码变得简洁易读、风格统一
  • 动态的数据表映射,在数据表结构甚至数据库发生改变时,减少了相应的代码修改
  • 减少了程序员对数据库的学习成本
  • 可以很方便地引入数据缓存之类的附加功能

但是ORM并不是一个完美的东西,它同时也有其自身不可避免的缺点:

  • 自动化进行关系数据库的映射需要消耗系统性能。其实这里的性能消耗还好啦,一般来说都可以忽略之,特别是有cacha存在的时候
  • 在处理多表联查、where条件复杂之类的查询时,ORM的语法会变得复杂且猥琐
  • 越是功能强大的ORM越是消耗内存,因为一个ORM Object会带有很多成员变量和成员函数。有一次修复bug时就遇见,使用ORM查询的时候会占用12MB的内存,而使用SQL的查询时只占用了1.7MB……

ORM就是这么一个让人又爱又恨的东西。回到我们开始的问题:“ORM到底是用还是不用?”。

Fancy个人的观点是:ORM要用!但关键部位不能用!

因为对于一般的Web应用开发来说,使用ORM确实能带来上述的诸多好处,而且在大部分情况下涉及不到ORM的不好的地方。但是在系统里面有大数据量、大运算量、复杂查询的地方,就不要用ORM。ORM的性能问题将给你带来灾难。在这些地方就可以使用纯SQL或者其他简单轻量的DB Helper库了。在详细了解ORM之后,你就可以扬长避短让ORM发挥其最大效用了。

原文链接: http://www.fancycedar.info/2013/01/orm/

PHP文件头部空白影响CSS布局

在编写PHP文件过程中,发现在浏览器预览PHP文件时,顶部会出现一行空白,影响了页面的布局。

关于BOM header的解释如下:

通常情况下,使用Windows系统自带的记事本程序编写网页程序,但在编写或修改php博客系统代码后,进行调试时总是会出现如同以下几点问题:

–不能登入或者不能登出; –页顶出现一条空白; –页顶出现错误警告; –其它不正常的情况。

分析原因: 由于使用UTF-8编码,在编写或修改代码后都保存为utf-8编码格式。虽然现在几乎所有的文本编辑软件都可以显示并编辑UTF-8编码的文件,但是很遗憾的是其中很多软件的表现并不理想。

类 似WINDOWS自带的记事本等软件,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(_0xEF _0xBB _0xBF,即BOM——Byte Order Mark)。它是一串隐藏的字符,用于让记事本等编辑器识别这个文件是否以UTF-8编码。对于一般的文件,这样并不会产生什么麻烦。但对于 PHP来说,PHP在设计时就没有考虑BOM的问题,不会忽略UTF-8编码的文件开头BOM的那三个字符,会把BOM作为该文件开头正文的一部分。由于必须在<?或者<?php后面的代码才会作为PHP代码执行,所以将会造成在页面上输出这三个字符,显示效果就要看浏览器了,一般是一个空行或是一个乱码。由于在html一开头有这3个字符的存在,即使页面的 top padding 设置为0,也无法让整个网页紧贴浏览器顶部。由于受COOKIE送出机制的限制,在这些文件开头已经有BOM的文件中,COOKIE无法送出(因为在 COOKIE送出前PHP已经送出了文件头),所以登入和登出功能失效。一切依赖COOKIE、SESSION实现的功能全部无效。

解决办法:

在编辑、更改任何文本文件时,请务必使用不会乱加BOM的编辑器。Linux下的编辑器应该都没有这个问题。WINDOWS下,请勿使用记事本等编辑器。推荐的编辑器是: Editplus 2.12版本以上; EmEditor; UltraEdit(需要取消‘添加BOM’的相关选项); Dreamweaver(需要取消‘添加BOM’的相关选项); Notepad(需要进行“转换为不带BOM的UTF-8”)等。

对于已经添加了BOM的文件,要取消的话,可以用以上编辑器另存一次。(Editplus需要先另存为gb,再另存为UTF-8。Dreamweaver在”页面属性“的 “包含Unicode 签名(BOM)”取消即可)

转载自:http://www.cnblogs.com/newsouls/archive/2013/01/11/2856518.html

Symfony2之不能承受之重

本来想写成PHP之不能承受之轻,但PHP本身问题并不大,易学易用,大多数需要的东西都有,友好的C扩展接品,虽然有一些不好的语法等问题存在,但不能说PHP之不能承受之轻.

那还是说说Symfony2这个自带DI的Web开发框架吧,最起码说一说Symfony2之不能承受之重.

首先,组件.Symfony2在PHP的世界里带来了组件的概念,这个概念非常好,特别是以完全面向对象的风格,引入各种bundle作为组件.虽然21世纪的技术早就普及的组件的概念,但是Symfony2实现得非常好,比如安全组件,再比如权限等等.但没有完美的东西,Form组件与验证组件用起来就太重了,不方便单元测试,使用复杂,到今天我还是记不住所有语法,问过其他人,也大多记不下语法.

然后, 自然要提到I18N组件,简直就是能让人疯狂的组件,没有文档说明如何配置是正确的,有人用yml,有人用xml还有人用更奇怪的办法.所以,每当碰上这种I18N的情况,我宁可多加一个部分,在Web层配置两套twig.

再然后,单元测试.不少人说Symfony2的单元测试挺好啊,又用不着自己处理垃圾数据,直接放在内存里面跑,但又有几个人真正了解如何以bootstrap的模式启动Symfony2的内核?真正的单元测试又怎么能够不以这种方式做单元测试和数据层?别提Mock,我知道什么是Mock,但你只测试QueryBuilder生成的query语句还不够,一定要跑起来再看实体定义,Symfony2应该增加这部分的默认配置.

再再然后,就是Bundle的继承关系,没有一个真正优秀的设计,这部分继承关系,如同鸡肋,食之无味,弃之可惜(比如用FOS的组件就需要用到这个特性)

最后,再折腾一句:cache设计得不合理,很多人都需要花很久才能真正用好,应该再自动化一点,智能一点,多封装几种算法.

又写废话了,Symfony2还是最好的PHP框架之一,只是有一些地方,总是有着开发人员无法承受之重.

转载自:http://saharabear.com/weblog/?p=1799

为什么很多人讨厌PHP

幾年前我有回覆類似的問題,核心理念是,當我們只從一個或少數角度來觀看一件事時,往往會忘了另一片風景。

重點是,我們打算用程式語言(PHP)做什麼?這會決定我們看的角度,甚至影響了我們的心態。我曾在公開演講中表示,程式語言對我來說,是個「選擇(Option)」,是用來「解決某個問題」。如同我們不會拿榔頭敲掉螺絲,而是使用螺絲起子。一旦我們受限於只比較「工具」的局部特性時,我們很容易只看到一個工具的缺點,而忘了它的優點。

今天我在網路上看到 Phil Sturgeon 在 Quora 針對此問題的回答,同時也同步在他的網誌,分享給大家。

Phil 認為很多人有各種不同的理由「討厭」PHP,或至少看衰它。其中有一些是有根據的,有些則否。

1. Inconsistent haystack / needle

Phil 舉的第一個例子是「不一致的 haystack / needle」。

舉個 PHP 中的兩個內建函式:

  • in_array($needle, $haystack)
  • strpos($haystack, $needle)

很多人批評函式參數的 haystack 及 needle 在不同的情況下的順序不一致,這導致開發者很可能要「硬背」這些 API。

Phil 指出,其實 PHP 的函式設計是有規則的。如果 haystack 處理的是 array,則順序是 needle, haystack;反之若是 string,則順序是 haystack, needle。

2. PHP is a HTML file, with logic

很多人認為 PHP 與 HTML 的混用規則是很奇怪的設計。

Phil 指出,PHP 在起初設計上就是預設檔案是個 HTML,只是中間可以嵌入一些 PHP 的邏輯處理。我們也不能否認的是,在當時的那個時代,這個設計使得 PHP 使用率得以快速成長。

但也不能否認的是,這個現象在現代看來有些不合味口,所以在未來的 PHP 6 將會引入新特性來讓開發者得以解決這個問題。

3. No standards

在 PHP 的世界中有太多的 Web framework,每個都有著自己的標準,例如很多人會爭論使用 snake_case 還是 camelCase。最近這個現象也開始舒解了,因為有 PHP-FIG 組織制定了相關的遵循標準。

4. Lack of Quality Packages

另外很多人批評 PHP 沒有夠好的套件管理工具。例如我們知道,

  • Node.js 有 NPM
  • Ruby 有 Bundler/Gems
  • Python 有 PIP
  • Perl 有 CPAN

而過去的 PHP 只有難用的 PEAR。相對好用的 PHP 套件管理工具也不是沒有,只是過於分散不集中。例如,

  • CodeIgniter 的 Sparks
  • FuelPHP 的 Cells
  • Laravel 的 Bundles
  • CakePHP 的 Bakery
  • ZF2 的 Modules

Phil 認為這個現象將會也會得到舒解。因為除了 PHP-FIG 組織制定的 PSR-0 標準外,也有 Composer 團隊推出標準的套件管理計畫。

5. Misconception

Phil 指出(編者註: Phil 同時也是 Ruby 使用者),很多 Ruby 開發者對 PHP 的批評認知還停留在 PHP 4 的時代。其實 PHP 5 已改進非常多,甚至 PHP 5.3 是一個大躍進。他認為很多人的評論還停留在 7 年前的 PHP。

Phil 同時也說,有些人說 PHP 沒有內建 Web server 是個很糟糕的事,但好消息是從 PHP 5.4 開始就內建 built-in web server 功能了。

6. You were doing it wrong

Phil 指出,很多人會說「You can mix MySQL, HTML and PHP in the same files. PHP is disgusting!」(編者譯: 「你可以把 MySQL, HTML 及 PHP 同時放在一個檔案裡面,可見 PHP 多麼噁心」)。

但 Phil 認為這個缺點可以由 PHP Web framework 獲得解決,同時他也認為如果 Ruby 開發者在不使用 Sinatra 或 Rails 時是怎麼解決這個問題的?或者 Node.js 開發者不使用 Express 或 CanJS 時又是怎麼解決的?(編者譯:Phil 指的應該是「不要拿程式語言(PHP)來和 Web framework (Rails 或 Express) 來比較」)

7. Elitism

Phil 感慨的指出,現在很多人認為「不使用 PHP 的人才酷」(編者註:Phil 言下之意不知是否也指「不要以為使用 Rails 或 Node.JS 就覺得很潮」?)

除了批評之外,我們該想想,「為什麼現在還有那麼多人使用 PHP ?」。Phil 認為「沒意外的話,就是氣勢(Momentum)」,他說根據統計,證明就是很多人使用 PHP,也不否認他仍然使用 PHP 的原因就是,相較於 Ruby、Python 及 Node.JS 而言,PHP 仍然擁有最大的市場。

最後 Phil 認為,很多開發者都在追求「完美的語言」,但答案是「世界上沒有完美的工具」,因此沒有任何人應該「討厭」任何程式語言。

转载自:http://blog.gcos.me/2012-12-04_phil-sturgeon-anwser-why-some-people-hate-php.html

PHP中的二进制位运算和权限存储

在很多系统的权限/选项设置中 很多都用到了位运算的方法来存储多种标志位。这样可以节省字段。一个字段只需要一个数字 就可以标识很多种设置和信息。

举例 dicuz的帖子表的status字段,官方预留了16个标志位(0×0000 – 0xFFFF) 即216

目前规划使用了只有8个标志位,如下

0000 0000 0000 0001 是否缓存帖子位置信息
0000 0000 0000 0010 是否回帖只对管理人员和发帖者可见
0000 0000 0000 0100 是否抢楼贴
0000 0000 0000 1000 是否倒序查看回帖
0000 0000 0001 0000 是否存在主题图章标志位
0000 0000 0010 0000 回复是否通知作者
0000 0000 0100 0000 是否推送到QQ空间
0000 0000 1000 0000 是否推送到腾讯微博

这8种状态可以使用一个数字来同时表示,节省了字段

那么这种东西的原理是什么呢

这个我们可以复习一下的位运算单算法

例子 名称 结果
$a & $b And(按位与) 将把 $a 和 $b 中都为 1 的位设为 1
$a | $b Or(按位或) 将把 $a 或者 $b 中为 1 的位设为 1
$a ^ $b Xor(按位异或) 将把 $a 和 $b 中不同的位设为 1
~ $a Not(按位非) 将 $a 中为 0 的位设为 1,反之亦然
$a << $b Shift left(左移) 将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)
$a >> $b Shift right(右移) 将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)

比如

与运算

14 = 0b1110

11 = 0b1011

那么 14 & 11 = 0b1110 & 0b1011 = 0b1010 = 10

或运算

还是上面那个例子

14 | 11 = 0b1110 | 0b1011 = 0b1111 = 15

异或运算

14 ^ 11 = 0b1110 ^ 0b1011 = 0b0101 = 5

非运算

非运算比较特殊 涉及到符号 这里要说一下补码 反码 原码的概念

1.二进制最高是符号位 0是正数 1表示负数

2.正数的 原码 反码 补码 都一样(我上面没有单独算补码的原因 ,正数补码和反码一样)

3.用二进制表示一个数 这个码 就是原码 比如 14的原码就是 1110

4.负数的反码 等于 他符号位不变 其他取反,而负数的补码等于他的反码+1

5.计算机运算的时候 全都是以补码的形式来运算的 不管正负数

那么

1 是正数,那么他的原码 0001 = 反码 = 补码 = 0001 =>取反 后补码1110 <=反码 1101<=原码1010

那么这个符号位是1就是负数 也就是010代表的负数就是-2 也就是 ~1 = -2

左右位移运算

1<< 2 1的补码 00000001 移动2位 00000100 正数的反码 补码 原码 都一样 所以 是个4

负数的计算过程相同 不再赘述 左移也类似 4>>2 就是1

其实可以理解为右移在十进制的表现上就是乘以2 左移 在十进制的表现上就是除以2


那么回到本文正题 如何用一个数字来标识这些权限位呢?

以刚才discuz的帖子表达status字段为例,检查帖子回复是否通知作者 就看二进制上第六位是否是置位为1 那么怎么检查呢?就是用上面我们提到的与运算。

与运算是将把 $a 和 $b 中都为 1 的位设为 1。那么假设

$a=36=0b 0010 0100

$b=0b 0010 0000

$a&$b = 0b 0010 0100 & 0b 0010 0000 = 0b 0010 0000 = 32 = 26-1 = 25

因此 检查,某个数代表的第N个权限标志位有没有置位(是1) 只要选择该数与仅该标志位置位的操作数2N-1进行与运算即可,相反要计算某个标志位被置位的数字 只要选择合适的操作数进行或运算即可。我们可以看discuz对此的实现:

function getstatus($status, $position) {
    $t = $status & pow(2, $position - 1) ? 1 : 0;
    return $t;
}

function setstatus($position, $value, $baseon = null) {
    $t = pow(2, $position - 1);
    if($value) {
        $t = $baseon | $t;
    } elseif ($baseon !== null) {
        $t = $baseon & ~$t;
    } else {
        $t = ~$t;
    }
    return $t & 0xFFFF;
}

注意 写这段代码的人显然受到了C的影响 其实 $a & ~$b 和 $a ^ $b 是等效的 只不过 ^是PHP的写法 另外 pow(2, $position – 1)换成 1 << ($position -1) 其实更好理解。

转载自:http://blog.ihipop.info/2013/01/3309.html

PHP语言的精华

我不擅长布道,因为我总是认为人家书上写得东西比我写得好多了.可是我却想把一些简单的道理说一下,因为总有人问我,那我就说几句.

PHP有很多不好的地方,比如说使用$符作为变量的一部分,大量使用->和=>作为分隔符或者引用之类的,并且它的方法并不面向对象,而对象却不能少了过程式方法,它又不像Python那样,方法本身也是对象,同时方法的参考顺序也没有统一的设计,我天天写PHP都要没事就查文档去看substr, strpos, strrpos这些东西.但任何语言都有问题,而PHP却有臫优秀的一面,提提它的精华吧.

第一条精华:简单.

PHP是极其简单的语言,虽然说你可以把PHP复杂化,但是PHP的简单是不需要解释的,也不需要争论的.只要想着PHP在正常情况下会一行一行向下执行,任何人都能够简单地入手.

第二条精华:深入.

不要认为PHP不能做复杂的东西,看看Symfony2框架就明白了,它是一个让PHP完全面向对象的框架,用它能做很多大家伙.

第三条精华:Web+CLI

现在都是PHP5.4的年代了,PHP的GC已经很不错了,你可以在CLI下面写脚本,就像Python和perl做的那样.

第四条精华:扩展

有啥不够用的东西,用C顶上,没有解决不了的问题.

第五条精华:资源

在Web上有大量超乎想像的PHP资源,反正我认为在Web领域要远超其他语言(JavaScript这货不算)

第六条精华:成熟产品

Drupal, WordPress, Joomla, media wiki, tiki, mantis等等,还有crm相关的,国内也有phpwind, discuz, 方维等各家都在使用PHP做产品,大部分都易于修改扩展.

就这六条,应该满足了.别黑我大PHP了.

转载自:http://saharabear.com/weblog/?p=1718

乱谈PHP

新年第二天,从今天以后的一年里都不再数新年第几天。

整体来讲,我不算一个PHP程序员,因为我的入门语言是C和Java,虽然当时一直不明白为什么要用C,因为做网站用Java比用C写CGI要好得多。

再后来学习的是Python,因为这东西在04到05年不大火,却有很多老外希望用这种语言写东西,会的人少,大赚一笔,为此还去读了一部分Python的代码。

再后来就是写商业的Java项目,从Struts+Spring+Hibernate到Struts2再到Wicket+Guice+IBatis还有Wicket+EJB3最后用上Grails和该死的Groovy,我终于烦了。

其间,一直在写PHP。

为什么我很少参与PHP的活动呢?比如我参与的PHP交流不多,看过的PHP代码也不多,到今天还是没学会怎么真正使用Drupal,只能简单做一做模板。其实就是因为PHP这门语言太好了,根本不用多花时间去研究它的实现,只要有一本手册,无论是Web还是Cli都能够很好地运行,不管是直接用过程式,还是大量利用现在的5.4的新特性,都很容易写好代码,虽然有一些时候,需要工具来监控一下执行过程的内存问题,但比起其他语言来讲,PHP的确是极其容易学习的。

就因为这个,我提到PHP的次数不多,因为不太必要提,因为它易学易用。

但是,最近总有人:又黑我大PHP。

所以,我决定宣布我就是PHP程序员,我不打算再当杂牌程序员,不再说自己是Python程序员或者Java程序员了,因为那样,我再次对别人说:又黑我大PHP的时候,他们就不能再说:谁让你一写Python的来掺和,或者说:你一Java端的,你哪头的。

所以,我是PHP程序员。

Over。

转载自:http://saharabear.com/weblog/?p=1703