Gallery: 编码指引:修订间差异

来自站长百科
跳转至: 导航、​ 搜索
无编辑摘要
第1行: 第1行:
This guide describes how to code for the Gallery 2 framework to make sure that it works on all platforms and as reliable as possible as well as that it is compatible with Gallery 2's requirements.
此知道描述为Gallery2框架进行编码的方法,以保证它能够在所有的平台上尽可能地稳定运行,并且能够符合Gallery2的要求。


This document does not cover the the [[Gallery2:Coding_Standards|Gallery 2 Coding Standards]], that is, the coding style is described elsewhere.
该文档不会涉及[[Gallery2:Coding_Standards|Gallery2的编码标准]],即编码风格会另辟话题。


__TOC__
__TOC__


== Database ==
== 数据库 ==


* Do not use DBMS dependent SQL fragments. Some DBMS dependent SQL is abstracted in <tt>$storage->getFunctionSql()</tt>, e.g. <tt>BIT_OR, BIT_AND</tt>, etc.
* 请勿使用依赖DBMS的SQL片断。某些依赖DBMS的SQL 在<tt>$storage->getFunctionSql()</tt>中是抽象化的,如<tt>BIT_OR, BIT_AND</tt>等。


* Do not call database related methods directly (e.g. <tt>mysql_connect</tt>). Instead use the Gallery 2 methods.
* 请勿直接呼叫数据库相关的方法(如<tt>mysql_connect</tt>),而是使用Gallery2的方法。
<pre><nowiki>
<pre><nowiki>
global $gallery;
global $gallery;
第15行: 第15行:
</nowiki></pre>
</nowiki></pre>


* Do not modify Map tables directly. Use <tt>GalleryCoreApi::addMapEntry($mapName, ..), ::removeMapEntry, ..</tt> instead.
* 请勿直接修改Map表格。而是使用<tt>GalleryCoreApi::addMapEntry($mapName, ..), ::removeMapEntry, ..</tt>
:: '''Note:''' In G2.0, this was <tt>MapNameMap::addMapEntry()</tt> etc.
:: '''注:''' 在G2.0中,此为<tt>MapNameMap::addMapEntry()</tt>


* Do not create your own database queries unless it's really necessary. Instead use Gallery 2's API methods.
* 除非必要,不要创建自己的数据库查询,而应使用Gallery2的API方法。


* Do not use {{H:title|Data Definition Language|DDL}} (the <tt>CREATE TABLE, ALTER TABLE, ...</tt> subset of the SQL language). Instead, use the Entity classes and Maps.xml including the XML descriptions to create new or modify existing tables if necessary. Gallery 2 will then generate SQL code for all supported DBMS once you run <tt>make</tt> in the <tt>classes/</tt> directory.
* 不要使用{{H:title|Data Definition Language|DDL}}(SQL 语言的<tt>CREATE TABLE, ALTER TABLE, ...</tt>子集)。而是使用Entity类别以及包含有XML描述的Maps.xml来新建或修改现有的表格。接下来,一旦你在<tt>classes/</tt>目录中运行<tt>make</tt>,Gallery2就会为所有支持的DBMS生成SQL代码。


* '''Locking:''' Use Read and write locks when you need to update persistent data (data that is stored in database). Do not forget to release the locks once you're finished.
* '''Locking:''' 当你需要更新永续性数据(存储于数据库中的数据)时,使用读/写lock。记得在完成更新后,释放这些lock。
:: '''Hint:''' lockIds are not the same as itemIds.
:: '''提示:''' lockIds与itemIds不同。


=== Large Datasets ===
=== 大型数据集 ===


* When dealing with large datasets, think about using a progress bar and <tt>$storage->checkPoint</tt> to minimize the effect of a possible fatal timeout / error.
* 当处理大型数据集时,可以考虑使用进度条和<tt>$storage->checkPoint</tt>来最大限度地限制可能出现的致命超时/错误的作用。


* Do not query with <tt>WHERE / UPDATE</tt> clauses that scale in query string size by the number of arguments since the query size is limited. Instead, do it in smaller batches.<nowiki>
* 不要使用<tt>WHERE / UPDATE</tt>字句进行查询,而按较小的批次进行会比较好。<nowiki>
</nowiki>As an example of a bad <tt>WHERE / UPDATE</tt> clause, assume $allItemIds is a list of 1000+ ids:
</nowiki>举一个<tt>WHERE / UPDATE</tt>字句较差情况的例子,假设$allItemIds为一个含有1000+id的列表:
<pre><nowiki>
<pre><nowiki>
$gallery->search("SELECT * FROM [GalleryItem] WHERE [GalleryItem::id] IN ($markers)", $allItemIds);
$gallery->search("SELECT * FROM [GalleryItem] WHERE [GalleryItem::id] IN ($markers)", $allItemIds);
</nowiki></pre>
</nowiki></pre>
:: '''Note:''' GalleryCoreApi::loadEntitiesById() and GalleryCoreApi::acquire*Lock() are both not yet fixed. This means that you should call these methods with smaller batches too. Even once they are fixed to do the work in batches, you will still have the problem of webserver (not php) timeouts. We can't use a progress bar deep down in the API since we don't know if the current view supports a progress bar.
:: '''注:''' GalleryCoreApi::loadEntitiesById()和GalleryCoreApi::acquire*Lock()均尚未修复。这就意味着你需要按较小的批次来呼叫这些方法了。就算它们被修整为可以进行批量操作,你还是要面对服务器(不是php)的超时问题。我们无法在API深层使用进度条,因为我们不确定当前视图是否支持进度条。


== PHP ==
== PHP ==


* Do not call <tt>die / exit / header('Location: ...')</tt> in your code. Instead, return a proper status / redirect url in your views/controllers. This way Gallery 2 has the chance to commit/rollback open transactions, do some cleanup, and apply patches to bugs (e.g. <tt>header('Location:')</tt> is buggy on some platforms and we fix it at the end of the request).
* 请勿在代码中呼叫<tt>die / exit / header('Location: ...')</tt>,而应在你的视图/控制器中返回一个合适的状态/重新导向url。这样Gallery2就有机会执行/回滚开启事务(open transactions),进行清除(cleanup),并未bug打上修复补丁(如<tt>header('Location:')</tt>在某些平台上有bug,而我们在请求结尾将其修复了)。


* For PHP functions that are listed in <tt>modules/core/classes/GalleryPhpVm.class</tt>, use
* 对于列在<tt>modules/core/classes/GalleryPhpVm.class</tt>中的PHP函数,使用
<pre><nowiki>
<pre><nowiki>
global $gallery;
global $gallery;
第47行: 第47行:
</nowiki></pre>
</nowiki></pre>


* '''References:''' See [http://gallery.menalto.com/node/33076 how to handle references in PHP 4.4.0]. As a general rule, don't use PHP references unless they really make sense. Also, the performance when using references is not necessarily faster! See: [http://www.blueshoes.org/phpBench.php PHP Benchmark tests]
* '''引用:''' 参见[http://gallery.menalto.com/node/33076 如何处理PHP 4.4.0中的引用]。作为常识,除非这么做有意义,否则的话不要使用PHP引用。而且使用引用时的性能欠佳。参见:[http://www.blueshoes.org/phpBench.php PHP Benchmark的相关测试]


* '''Compatibility:''' G2 code must run with PHP 4 and 5, that is PHP 4.1.0+ (as of G2.2 it'll be 4.3.0+) and PHP 5.0.4+. Do not use any "PHP 5"-only OO code and do not use any methods that are not available in PHP 4.1.0 unless you provide a fallback solution.
* '''兼容性:''' G2代码必须使用PHP4和5才能运行,即PHP 4.1.0+ (对G2.2则是4.3.0+)PHP 5.0.4+。请勿使用任何"PHP 5"-only的OO代码,也不要使用于PHP4.1.0中不可用的方法,除非你能够提供某种回退方案。
<pre><nowiki>
<pre><nowiki>
if (function_exists('foo_bar')) {
if (function_exists('foo_bar')) {
第58行: 第58行:
</nowiki></pre>
</nowiki></pre>


== Filesystem/Platform ==
== 文件系统/平台==


* Do not call any filesystem / platform functions directly (e.g. <tt>fopen, fsockopen, exec, chmod, ...</tt>). Use the Gallery 2 methods instead.
* 请勿直接呼叫任何文件系统/平台函数(如<tt>fopen,fsockopen,exec,chmod, ...</tt>),而是使用Gallery2方法。
<pre><nowiki>
<pre><nowiki>
global $gallery;
global $gallery;
第67行: 第67行:
</nowiki></pre>
</nowiki></pre>


== Strings/Texts and Translation ==
== 字串/文本和翻译 ==


* For all strings / texts that the end user gets to see, use
* 对于所有显示给最终用户的字串/文本,使用
<pre><nowiki>
<pre><nowiki>
$plugin->translate('Some text')
$plugin->translate('Some text')
</nowiki></pre>
</nowiki></pre>
<nowiki>
<nowiki>
</nowiki>If the text is going into the database and <tt>translate()</tt> is called when retrieving it from the database, use
</nowiki>如果文本进入数据库,并且在自数据库进行取回时<tt>translate()</tt>被呼叫的话,使用
<pre><nowiki>
<pre><nowiki>
$gallery->i18n('Some text')
$gallery->i18n('Some text')
</nowiki></pre>
</nowiki></pre>
<nowiki>
<nowiki>
</nowiki>In smarty templates:
</nowiki>在smarty模板中:
<pre><nowiki>
<pre><nowiki>
{g->text text="Some text"}
{g->text text="Some text"}
</nowiki></pre>
</nowiki></pre>
:: '''Note:''' Exceptions are the optional messages in GalleryStatus objects, and unit test failure messages which do not use <tt>translate()</tt>.
:: '''注:''' 例外情况就是GalleryStatus对象中的可选消息,以及不使用<tt>translate()</tt>的单位测试失败的消息。


* If you're using HTML in your string write it using the translation method.
* 如果你在字串中使用HTML,请使用翻译方法进行编写。
<pre><nowiki>
<pre><nowiki>
/* Bad */
/* 不好的写法 */
$plugin->translate('Do <b>NOT</b> do this!');
$plugin->translate('Do <b>NOT</b> do this!');


/* Good */
/* 好的写法 */
$plugin->translate(array('text' => 'Do %sNOT%s do this!', 'arg1' => '<b>', 'arg2' => '</b>'));
$plugin->translate(array('text' => 'Do %sNOT%s do this!', 'arg1' => '<b>', 'arg2' => '</b>'));
</nowiki></pre>
</nowiki></pre>


* Also use the translate arguments when the string includes variables.
* 当字串包括变量时还是使用translate参数。
<pre><nowiki>
<pre><nowiki>
/* Bad */
/*不好的写法*/
$plugin->translate("Next, please read chapter '$chapter'");
$plugin->translate("Next, please read chapter '$chapter'");


/* Good */
/*好的写法*/
$plugin->translate(array('text' => "Next, please read '%s'", 'arg1' => $chapter));
$plugin->translate(array('text' => "Next, please read '%s'", 'arg1' => $chapter));
</nowiki></pre>
</nowiki></pre>
<nowiki>
<nowiki>
</nowiki>In smarty templates:
</nowiki>在smarty模板中:
<pre><nowiki>
<pre><nowiki>
{g->text text="Next, please read '%s'" arg1=$chapter}
{g->text text="Next, please read '%s'" arg1=$chapter}
</nowiki></pre>
</nowiki></pre>


== Misc ==
== 杂项 ==


* '''URL Generation:''' Generate all URLs using methods provided by Gallery.<br /><nowiki>
* '''URL生成:''' 使用Gallery提供的方法生成所有的URL。<br /><nowiki>
</nowiki>In PHP:
</nowiki>In PHP:
<pre><nowiki>
<pre><nowiki>
第118行: 第118行:
</nowiki></pre>
</nowiki></pre>
<nowiki>
<nowiki>
</nowiki>In smarty templates:
</nowiki>在smarty模板中:
<pre><nowiki>
<pre><nowiki>
{g->url arg1= ....}
{g->url arg1= ....}
</nowiki></pre>
</nowiki></pre>


* '''Modifying code:''' Do not modify the code of existing modules. Instead, extend the feature set of Gallery 2 with additional modules. Reason: Users should be able to administer Gallery 2 with a simple web-interface. Adding a new feature should be as easy as installing a new module with a few mouse clicks. We don't want hacky installation instructions like "open file X, find line Y, replace A with B, ...". If you need a change in an existing module, please talk to the module author if this change could be incorporated in the existing module, preferably in a modular way (Factory Registrations), e.g. a module could check in the G2 factory if there are plugins for this module and your new module could register a plugin for the other module, thus extending the functionality in a modular way.
* '''代码的修改:''' 请勿修改现有模块的代码,而应使用额外模块扩展Gallery2的特点集。原因:用户应能使用简单的web界面管理Gallery2。新特点的添加应当是轻点加下鼠标那么简单。我们不希望看到类似"打开文件X,找到第Y行,将A替换为B ..."这样的修改类型的安装指导。如果你需要在现有模块中进行修改,请联系模块编写者,询问一下做出改动是否会导致现有模块的不兼容,最好是以某种模块化的方式,(Factory Registrations),如某模块会检查G2 factory看看是否有针对该模块的插件,而你的新模块可以为另外的模块启用一个插件,从而以模块化的方式对功能进行扩展。


[[Category:Gallery 2:Development|Coding Guidelines]]
[[Category:Gallery 2:Development|Coding Guidelines]]

2008年11月11日 (二) 14:31的版本

此知道描述为Gallery2框架进行编码的方法,以保证它能够在所有的平台上尽可能地稳定运行,并且能够符合Gallery2的要求。

该文档不会涉及Gallery2的编码标准,即编码风格会另辟话题。

数据库

  • 请勿使用依赖DBMS的SQL片断。某些依赖DBMS的SQL 在$storage->getFunctionSql()中是抽象化的,如BIT_OR, BIT_AND等。
  • 请勿直接呼叫数据库相关的方法(如mysql_connect),而是使用Gallery2的方法。
global $gallery;
list ($ret, $results) = $gallery->search('SELECT * FROM [GalleryPhotoItem]');
  • 请勿直接修改Map表格。而是使用GalleryCoreApi::addMapEntry($mapName, ..), ::removeMapEntry, ..
注: 在G2.0中,此为MapNameMap::addMapEntry()
  • 除非必要,不要创建自己的数据库查询,而应使用Gallery2的API方法。
  • 不要使用DDL(SQL 语言的CREATE TABLE, ALTER TABLE, ...子集)。而是使用Entity类别以及包含有XML描述的Maps.xml来新建或修改现有的表格。接下来,一旦你在classes/目录中运行make,Gallery2就会为所有支持的DBMS生成SQL代码。
  • Locking: 当你需要更新永续性数据(存储于数据库中的数据)时,使用读/写lock。记得在完成更新后,释放这些lock。
提示: lockIds与itemIds不同。

大型数据集

  • 当处理大型数据集时,可以考虑使用进度条和$storage->checkPoint来最大限度地限制可能出现的致命超时/错误的作用。
  • 不要使用WHERE / UPDATE字句进行查询,而按较小的批次进行会比较好。 举一个WHERE / UPDATE字句较差情况的例子,假设$allItemIds为一个含有1000+id的列表:
$gallery->search("SELECT * FROM [GalleryItem] WHERE [GalleryItem::id] IN ($markers)", $allItemIds);
注: GalleryCoreApi::loadEntitiesById()和GalleryCoreApi::acquire*Lock()均尚未修复。这就意味着你需要按较小的批次来呼叫这些方法了。就算它们被修整为可以进行批量操作,你还是要面对服务器(不是php)的超时问题。我们无法在API深层使用进度条,因为我们不确定当前视图是否支持进度条。

PHP

  • 请勿在代码中呼叫die / exit / header('Location: ...'),而应在你的视图/控制器中返回一个合适的状态/重新导向url。这样Gallery2就有机会执行/回滚开启事务(open transactions),进行清除(cleanup),并未bug打上修复补丁(如header('Location:')在某些平台上有bug,而我们在请求结尾将其修复了)。
  • 对于列在modules/core/classes/GalleryPhpVm.class中的PHP函数,使用
global $gallery;
$phpVm =& $gallery->getPhpVm();
$phpVm->functionName();
  • 兼容性: G2代码必须使用PHP4和5才能运行,即PHP 4.1.0+ (对G2.2则是4.3.0+)和 PHP 5.0.4+。请勿使用任何"PHP 5"-only的OO代码,也不要使用于PHP4.1.0中不可用的方法,除非你能够提供某种回退方案。
if (function_exists('foo_bar')) {
	foo_bar($data);
} else {
	myFooBar($data);
}

文件系统/平台

  • 请勿直接呼叫任何文件系统/平台函数(如fopen,fsockopen,exec,chmod, ...),而是使用Gallery2方法。
global $gallery;
$platform =& $gallery->getPlatform();
$platform->fopen($path);

字串/文本和翻译

  • 对于所有显示给最终用户的字串/文本,使用
$plugin->translate('Some text')

如果文本进入数据库,并且在自数据库进行取回时translate()被呼叫的话,使用

$gallery->i18n('Some text')

在smarty模板中:

{g->text text="Some text"}
注: 例外情况就是GalleryStatus对象中的可选消息,以及不使用translate()的单位测试失败的消息。
  • 如果你在字串中使用HTML,请使用翻译方法进行编写。
/* 不好的写法 */
$plugin->translate('Do <b>NOT</b> do this!');

/* 好的写法 */
$plugin->translate(array('text' => 'Do %sNOT%s do this!', 'arg1' => '<b>', 'arg2' => '</b>'));
  • 当字串包括变量时还是使用translate参数。
/*不好的写法*/
$plugin->translate("Next, please read chapter '$chapter'");

/*好的写法*/
$plugin->translate(array('text' => "Next, please read '%s'", 'arg1' => $chapter));

在smarty模板中:

{g->text text="Next, please read '%s'" arg1=$chapter}

杂项

  • URL生成: 使用Gallery提供的方法生成所有的URL。
    In PHP:
global $gallery;
$urlGenerator =& $gallery->getUrlGenerator();
$url = $urlGenerator->generateUrl($params, $options);

在smarty模板中:

{g->url arg1= ....}
  • 代码的修改: 请勿修改现有模块的代码,而应使用额外模块扩展Gallery2的特点集。原因:用户应能使用简单的web界面管理Gallery2。新特点的添加应当是轻点加下鼠标那么简单。我们不希望看到类似"打开文件X,找到第Y行,将A替换为B ..."这样的修改类型的安装指导。如果你需要在现有模块中进行修改,请联系模块编写者,询问一下做出改动是否会导致现有模块的不兼容,最好是以某种模块化的方式,(Factory Registrations),如某模块会检查G2 factory看看是否有针对该模块的插件,而你的新模块可以为另外的模块启用一个插件,从而以模块化的方式对功能进行扩展。