功能/功能,使您的应用程序更专业?编码爱好者

时间:2010-09-26 21:38:25

标签: php

功能您在PHP Web应用程序中实现(如何)因为 你认为它在某种程度上“更专业”?或者你有个人的挑剔 和代码爱好者,特别是可能重要的小东西? 哪些不受欢迎的代码或次要功能会花费大量时间来正确

  

Q& A插图的编码爱好者示例:

     

配置数据不在数据库中:应用程序数据!=配置数据,其中   也是必要和效率的问题。

     

网址修复:通过附加尾部斜杠来规范化所有网址,即使技术上不需要也是如此。

     

人类可读的Cookie :对于数据隐私,我尝试避免不透明的会话/数据库句柄(对于用户选项,而不是授权使用)。

     

内容协商:对简单变体有意义   在...之间RSS和Atom格式。但我发现很少使用它。

     

UI中没有数据库ID :避免将数据库内部代理键泄露到URL中。使用ORMs,db-internal密钥甚至不必泄漏到业务逻辑中。

提示(不是规则)

  • 那么,您认为哪种功能会使您的网络应用程序高于平均水平?
  • 为什么不常见?
  • 对用户有利,但同样容易被忽视吗?
  • 更专业,更安全的编码建议非常关注主题。他们总是。
  • 但此Q& A 的预期范围实际上是非常见/唯一功能,可能还有非标准和有争议的功能。迷人的大奖金。
  • 它也与编码偏好和挑剔有关,恰好在PHP中实现。
  • 不要认为太大或太高。小功能也很重要。
  • 如果可行,请显示代码。
  • 然而,语法和编码风格/范例主要是偏离主题的。
  • 我们不要争论有用性或代码质量。 这纯粹是一种特征性的&代码调查。

第一个特征性研究赏金奖:很难确定其中一个好主意。说实话,我只能将其缩小到五个收藏夹并将决定权交给rand()。这个话题非常有趣,足以保证第二轮赏金。休息一下。也许其他人接管来改进范围。

33 个答案:

答案 0 :(得分:40)

<强>文档

想象一下,无论有没有最新的文档,您都可以找到任何开源项目,并感受到它对您认为的专业程度的影响。

答案 1 :(得分:31)

关注安全,尤其是用户私人数据。

使用强大的哈希值存储密码,例如 bcrypt (请参阅crypt文档):

// generating hash
// read up how $costParameter and $salt look like in the crypt() docs
$hash = crypt($password, '$2a$' . $costParameter . '$' . $salt . '$');

// checking if password is correct
if (crypt($whatTheUserEntered, $hash) == $hash) {
    // correct password
}

$salt不应该是静态值。每个用户都应该有所不同。

答案 2 :(得分:24)

专业外观,非常重要的是清洁和美观平面设计。因为封面是卖的,这些天。伤心,但也是如此。具有漂亮代码和丑陋外观的Web应用程序不会引起太多关注。

答案 3 :(得分:22)

健康检查

一系列预先配置的测试,用于确定(可由管理员/网站所有者)随时查看的Web应用程序或网站的基本“健康状况”,显示如下内容:

  • 数据库服务器是否可访问?
  • 必要的文件和目录是否可写?
  • 所有数据结构是否合理且完整?
  • 是否正确显示所有页面/对话框/查询?
  • 是否有足够的磁盘空间可用?
  • 等。等。

简单的状态页面显示具有绿色,橙色或红色背景的系统的当前“健康状况”。

这与单元测试的不同之处在于它处理“真实世界”环境的健康状况,而不是抽象代码完整性。

运行状况检查还可以轻松地将应用程序迁移到另一台服务器。

我已经在几个需要持续监控的项目中实现了这一点;我计划在今年的某个时候将它变成一个小的,可扩展的“drop in”开源应用程序,可用于各种Web应用程序甚至网站。参与和投入非常欢迎 - 有关详细信息,请参阅related SO question

答案 4 :(得分:15)

来源控制。 特别是Git(虽然不是特别是GitHub)

好的,这并不罕见 但是当我外包代码并获得一个整齐的回购,包含所有的历史和曲折时,我对一个充满php文件的文件夹印象更深刻。
并且它展示了在项目中投入了多少额外的工作。

我使用GitFlow,这在使用过程中需要更长的时间,但在完成的项目中更能让人印象深刻。确保客户端看到github图(或等价)所有这些分支看起来整洁和令人印象深刻。 (除了实际有用!)

相关:
问题跟踪系统。
两者都在代码完成之前(客户端正在审核时)和后记,以允许他们添加新任务 它不仅是划分任务和获得更多工作的一种方式,它还使客户感到项目仍然在我的脑海中。即使我继续前进 我使用Collabtive,这是非常可怕的,因为这些系统可以使用,但是看起来更令人印象深刻的是我尝试过的任何东西,看起来令人印象深刻的东西都被认为是专业的。

答案 5 :(得分:12)

密码强度/匹配

在注册或更改密码时,以交互方式通知用户密码的强弱。当他们打字时确认匹配时也通知他们。

实时表单验证

与密码一样,表单条目的实时验证比允许用户在知道错误之前完成整个表单或省略他们跳过的必填字段要小得多。

具有友好异常/错误处理的防御性编程

永远不要使用神秘的错误消息,并且通常会参考您可以找到的最佳案例示例,以获得良好的友好错误消息。在最好的情况下,这通常需要一位才华横溢的复制作者,以保持良好的语调等。

这与可靠的异常处理和良好的防御性编程密切相关。

Defensive Design是关于这个主题的相当不错的书。

答案 6 :(得分:12)

编写易于维护的代码。在开始编写之前,请多考虑一下对象的界面。添加许多事件触发器,即使您现在不需要它们也是如此。它们可能在该功能中很有用。

将代码编写为外部库。即使您正在处理商业,封闭式应用程序也将其视为开源项目。考虑可能希望在不更改现有代码的情况下更改现有代码行为的其他用户。当你使用类型提示时,你应该检查接口而不是类,所以:

public function add(Storable $resource);    # Good
public function add(SessionStore $session); # Bad

不要使用全局命名空间和“全局功能”。定义全局常量或使用__autoload()(而不是使用spl_autoload_register()注册另一个自动加载器)是一种不好的做法。

使用第三方代码。那里有很多库。大多数时候开发自己的ORM或Mailer是没有意义的。它减少了开发应用程序所需的时间 - &gt;它降低了成本。

创建API文档。我认为不需要任何解释。

让您的代码看起来干净并保留一些编码约定。

不要创建无用的页面。没有什么比404 Not Found页面更令人讨厌的了,只有一个404 404 NOT FOUND信息。您应该为每个资源提供几个未找到页面。因此,如果我访问/video/123/how-to-swim并且此类资源不存在,则我们很抱歉,该视频不存在或已被删除。添加如下内容:最近的视频< / em>,也许你正在寻找:“如何进行游戏”,“游泳:abc”(标题类似于标题形式网址的游戏(如何游泳))等。

允许用户自定义网站。想象一下,您有一个包含多个“框”的主页:最近的视频,最近的照片,最近的活动主题,新闻,推广的图库等。允许用户访问隐藏其中一些,改变他们的顺序 - 有人可能对照片和视频而不是新闻和线程更感兴趣所以他/她可能想要将它们放在页面顶部,其他人可能会有不同的偏好并可能想要有不同的顺序。为每个框添加首选项,例如:“显示:5,10,20个近期视频”。

答案 7 :(得分:11)

添加更多(不那么面向PHP的)积分,这将增强用户体验并使您的应用更专业,但处理后端:

良好的压缩/缩小
Web应用程序通常会在加载和使用过程中发送大量请求。缩小可以帮助减少初始负载重量,也可以使用CSS精灵和GZipping内容。帮助您尽可能快速简化和使您的应用程序的一个很好的方法是Yahoo的FireSug扩展的YSlow插件:

萤火虫: http://getfirebug.com/

YSlow的: http://developer.yahoo.com/yslow/

另外 - 一些好的做法: http://developer.yahoo.com/performance/rules.html

YSlow将帮助您确定如何使您的应用程序整洁,快速和干净。我还建议使用PHP Minify来处理大部分文件压缩,它是一个非常强大的工具:

PHP Minify:http://code.google.com/p/minify/

获得Firebug的另一个原因是它在开发任何Web应用程序时带来的巨大好处,其中最重要的是确定应用程序的安全性,因为在操作过程中您可以跟踪创建的数据流。

<强>模糊处理
---分成以下更详细的答案

善用Apache重写
除了提供干净的URL以增强浏览体验和给出逻辑归档内容的印象的基本好处之外,一个好的.htaccess文件可以为您的站点添加额外的安全层,压缩内容服务器端并添加其他标识符(E-例如,标签虽然它们的好处是有争议的)。每个Web应用程序都应该有一个很好的.htaccess。

<强>兼容性/验证
我总是强烈要求任何开发人员使用最广泛(合理)的长度来确保他们的所有输出代码都是有效的,评论的,逻辑的和清洁的。 W3C做得非常出色,不仅可以清晰地显示HTML,还可以了解Web应用程序的运行方式。遵循他们的指导,以提高您编写的任何内容的兼容性,以确保它适用于每个人如何设想。

一些很棒的工具:

HTML验证器:http://validator.w3.org/

其他验证:http://validator.w3.org/unicorn/

有些规格需要注意:

W3C Web应用程序(WebApps)工作组:http://www.w3.org/2008/webapps/

W3C辅助功能指南:http://www.w3.org/WAI/guid-tech.html

W3C WAI-ARIA倡议:http://www.w3.org/WAI/intro/aria.php

在Javascript方面,JS lint是一个很好的工具,可以确保你的JS中的任何错误(当你检查时可能不会影响性能)被压扁:

JSLint:http://www.jslint.com/

通过代理,为了帮助开发,美化JS可以帮助您更好地构建代码以进行开发,预先缩小:http://jsbeautifier.org/

或者美化PHP当然...... http://beta.phpformatter.com/

最后 - 一些不那么黑白的东西
人源化

创建基于Web的应用程序的最大好处之一可能是它们可以提供的连接,不仅是用户之间的连接(为了鼓励协作工作),还有用户和应用程序本身之间以及负责其持续性的人员之间的连接。开发和维护。

如果您考虑像37 Signals这样的项目 - 其中一个吸引人的因素是它们向用户传达了项目(代码)本身已经人性化并具有特征的感觉,有助于吸引用户并与之相关联应用程序,鼓励使用和与他人沟通。我并不是说应用程序似乎“活着”,但更多的是它感觉更“平易近人”,用户可以“识别”它。

然而,这只是人性化硬币的一个方面,几乎让用户对应用程序/代码/框架/体验感同身受,因此鼓励他们使用它。另一方面是打破应用程序与其背后的界限。

我们都想知道我们使用的人,人等等 - 因为我们从他们那里传递了大量的信息,并且经常将它不合理地应用到应用程序本身,实际上我们对它的“喜欢”(就像史蒂夫·乔布斯,购买) Apple等。尽管这是一个任性的例子)。有一条路线可以让我们在遇到困难时与真人联系,这是一个简单的步骤,有一个开发者博客,新闻流等 - 围绕应用程序建立一个人性化的元节点给它可信度和感觉它可能比各部分之和。

不可否认,人性化可能既不在这里也不在那里 - 而且构建起来肯定非常困难(不同的人有不同的朋友),但是开发人员可以通过任何方式打磨更临床的外科手术应用程序的边缘它更舒适,平易近人,充满乐趣,每天使用者都是我书中的赢家。

答案 8 :(得分:10)

无强制注册
这是日常Web应用程序的常见问题。强制帐户注册不是用户友好的。现在,这是防止垃圾邮件和滥用的必要条件。但它阻碍了采用。

我想每个人都听说过Stackoverflow。他们不强制注册。你可以在没有帐户的情况下进行游说。它不是强制注册,而是系统地鼓励它。然而,重要的是,在提交之前至少有选择逐渐习惯。

这是一个简单的概念。但同样难以实施。您很少能够使用临时和可选的用户帐户,必须为其准备基本应用程序逻辑和数据库结构。无论实施工作如何,我相信这是一个重要的,并且是一个未充分利用的功能。

答案 9 :(得分:9)

经常被忽视的一个:可打印的CSS 。编写它很痛苦,但对于想要在应用程序中打印出某些数据的用户来说会产生很大的不同。

<link href="print.css" rel="stylesheet" type="text/css" media="print"> 

答案 10 :(得分:8)

续点

示例:您提交表单,您将被重定向,现在着陆页应该包含通知。大多数网站只是将该通知存储在会话中。这意味着:接下来将访问的任何页面都将显示该消息。在大多数情况下没问题,但我的脑海里真的很乱。我认为会话是针对会话数据,而不是下一个请求数据。

我的解决方案:创建一个数组,将数据(通知以及更多内容)写入其中,使用sessionid +唯一标识符将其保存在memcache中,并在重定向上添加param __continuation = {唯一标识符}。然后下一页再次加载该数据并进行处理。

当您希望获得的数据多于短消息时,这会变得更加方便。

有问题吗?

答案 11 :(得分:6)

一致的编程风格,可变命名,支撑等。遵守编码标准(任何编码标准。)确保不同人编写的文件看起来相同,以便维护代码不需要知道是谁编写的。 / p>

答案 12 :(得分:5)

以Jus为例:网址“修复”
对于http-URLs,我将路径片段视为必需的,就像每个浏览器一样 确实。所以我指出“修复”用户输入和导入数据,并始终添加 拖尾斜线到例如http://example.org显示或存储此类值之前。 可能不是“超级专业”,但规范化URL往往简化了交易 与他们在一起。而且不知道,它似乎“更好”。

 $url = preg_replace("/^(http:..[-\w.\d]+)$/", "$1/", $url);

所以无论怎样,我总是会有http://example.org/的价值观。 这不会使您的HTML符合标准,但它只是 my 宠物的一个。

答案 13 :(得分:5)

UI中没有数据库ID
大多数数据库对象都使用一些代理键进行枚举。我是什么 认为看起来不太时髦(并且可能偶尔会出现安全隐患)正在将这些泄漏到UI中,就像在URL中一样。将user.php?id=37310843的任何内容更改为user.php?name=title并不是什么大问题。并且数据库查找id或名称几乎没有什么区别。所以这不是关于SEO的愚蠢,而是关于一个光芒四射的外表

  • 使用正确的ORM,这些数据库内部ID甚至不会泄漏到应用程序逻辑中。
  • 展览维基百科:想象他们使用代理键而不是页面标题。 (见CoWiki)
  • 为了让外部链接始终指向标准内容,应该避免使用代理键。如果确实有足够的重要分配,那么无论如何都应该使用GUID。

答案 14 :(得分:4)

任何2.0 Web应用程序预计会有一个重要的事情是 -

  1. 搜索 - 是全文搜索,关键字搜索,是否有自动建议或(最新的)实时搜索之一。如果没有这个功能,当我访问任何网站(特别是对搜索引擎不熟悉的网站)时,我会感到窒息。对于任何现代的2.0网站,必须有一个明确的必须。
  2. MVC框架 - 由于这与web-dev(不依赖于PHP)有关,因此必须使用Model-View-Controller框架。过多的代码库和更快的迭代周期正确的结构是防止未来麻烦和必要的必要条件。无法追踪的虫子。
  3. AJAX - 需要我这样说:)这改变了我们大多数人浏览网站的方式。一个AJAX使网站是一个很酷的功能。
  4. 调试信息 - 这适用于应用崩溃的情况。你怎么发现出了什么问题?你维护日志吗?你可以从日志中追溯问题来源(发生几小时后)吗?你应该让日志变得多么简洁?
  5. 缩小的Javascript&amp; CSS - 减少加载时间&amp;使网站更加流畅,从而让用户在浏览网站时感觉更舒服。
  6. 缓存 - 再次极大地增加了用户的感知响应时间,从而使网站更“专业”。

答案 15 :(得分:4)

联合申请

问问自己 - 如果您正在运行在线商务系统且您的信用卡付款供应商离线,您的客户是否仍然无法浏览您的产品,甚至可以使用不同的付款方式结帐?

应用程序的构建方式可以切换“交换机”,不会使整个站点进入“维护模式”,而只是使应用程序中的页面或部分以优雅的方式不可用,而其余的您的应用程序stil可供其他用户使用。

集合应用程序可能是一个俗气的名称,但我完全相信它有更好的东西,但它绝对是许多人在开发可用应用程序时往往会忘记的方法之一。

智能蛮力保护

假设您的应用程序中有一个管理部分,其中包含大量客户信息。绝对是您不希望任何人接触的数据。即使你有一个很好的盐和良好的算法来哈希你的密码,邪恶的用户仍然可以对你的登录表单执行DOS / rainbow-table(暴力?)攻击。

第一个选择显然是使用自动化软件来执行这些攻击,并通过对密码进行合格猜测来手动执行。很容易找到有关用户猜测他或她的密码的足够信息,考虑只使用谷歌可以获得多少信息。 此外,如果您居住在瑞典这样的国家 - 没有太多信息,您无法通过单一电话向当局了解 - 社会安全号码,合作伙伴姓名,婚姻状况,儿童名称,宠物和更多信息,这些信息都是非常合格的普通用户密码猜测。

如果我们有look on how ordinary people choose their passwords,安全应该非常容易妥协。当然,我们可以设置长度,特殊字符等用户密码的限制,但这不会影响情况。仍然可以进行蛮力攻击。

如果用户尝试登录并且未能通过未知IP进行第二次尝试,则应显示重新访问以防止自动登录。在另一次(n)尝试失败后,该帐户应完全锁定并需要重新激活才能完成登录。

为了防止因性能而导致的自动攻击,一个好主意可能是完全阻止在一定时间内使(n)登录尝试失败的IP,从访问登录页面,直到它已被手动列入白名单。

答案 16 :(得分:3)

注册系统。

我之前已经多次谈到存储对象和范围问题以及我所知道的最好的方法,这是通过使用带有getter和setter的Static / Abstract类来帮助你在应用程序周围传输对象保存您必须修改类,以便您可以专门导入对象以供使用。

这个类可以像一个带有2个方法和1个数组的抽象静态类一样简单,这些是超出范围问题的基本要素,而不影响烤箱内的其他任何东西。

以下是我所说的一个小例子:

abstract class Registry
{
    private static $objects = array();

    public static function set($name,$object)
    {
        self::$objects[$name] = $object;
    }

    public static function get($name)
    {
        return self::$objects[$name];
    }
}

看着那个类的简单性没有什么可以害怕的,没有什么可以让你修改你当前的框架/应用程序来采用这个方法,但如果你不确定它是如何工作的,那么让我给你一些例子

Firsty假设我们index.php包含startup.phpstartup.php包括您的库和核心框架代码,但在启动时加载以下内容

  • 数据库
  • 会话
  • FileWriter的
  • 输入
  • 输出

现在如果你想使用FileWriter对象作为在Database对象中登录的工具,你通常会有一个名为$FileWriter的变量,你可以在{{Database中使用global关键字1}}对象

但是通过以下方式:

Registry::set('Database', new Database())
Registry::set('Session', new Session())
Registry::set('FileWriter', new FileWriter())
Registry::set('Input', new Input())
Registry::set('Output', new Output())

您将所有内容存储在Registry对象中,以便查看我们的数据库对象/类

class Database
{
    //..

    public function connect()
    {
        if(!$this->connected())
        {
            try
            {
                $this->connect();
            }catch(Exception $e)
            {
                Registry::get('FileWriter')->Write('db_logs',array($this,$e),'unable to connect to database');
            }
        }
    }

    //..
}

现在您可以看到Registry在类的范围内可用,并且它干净,安全,您不会占用额外的变量或使用globalization的更多代码,只需清理简单且安全的< / p>

希望你喜欢阅读。

答案 17 :(得分:3)

自动单元测试

重要的是,健康检查页面非常重要。一旦我的代码增长超过800行代码,我就不记得我在第100行做了什么,我可能会在没有意识到的情况下破解它。

答案 18 :(得分:3)

WRT 不在数据库中配置,使用memcache,例如,五分钟到期。更复杂的选择是在配置发生变化时触摸“重新加载配置”页面;诀窍是确保你触摸服务器场中每个应用服务器实例的页面(这就是为什么我更喜欢内存缓存)。

答案 19 :(得分:3)

全站点SSL / TLS加密

正如最近发布的Firesheep所示,在开放的WiFi环境中窃取会话cookie(例如许多图书馆,酒店和其他场所提供)以及任何未切换的以太网网段仍然无法解决。 (理论上,on switched ones too

Firesheep现在使其成为普通Joe的双击操作,整个站点加密不再被视为奢侈品。 (同时在会话cookie上设置安全标志,以确保兼容的浏览器不会意外地将它们泄露到不安全的请求中)Neither扩展名和问题都将消失。

根据Adam Langly的博客,谷歌发现SSL / TLS isn't as bad as people tend to guess,并且稍微调整一下(他们正在Chrome中构建),甚至是建立与额外圆形连接的延迟组件 - 旅行可以有效消除。

即使证书成本也没有许多人想象的那么大,因为StartCom提供免费的SSL证书,并且他们的根证书已经存在于所有主流浏览器中。

答案 20 :(得分:3)

PHP中的delve函数允许您:

$a = delve($array,'a.b.c.d','default'); // $a->b['c']->a
$b = delve($object,'a.b.c.d','default'); // $a->b['c']->a

如果没有这个,你将不得不做痛苦的issets和empties以及数据类型检查所有的血腥时间。这是迄今为止我最喜欢的功能。

关于什么使得更专业的代码是单元测试,文档版本控制并先做(然后如果你做不到,那么恢复到堆栈溢出)。

/**
 * Delve into an array or object to return the value of a set of keys
 * @version 1, December 24, 2009
 * @param mixed $holder
 * @param mixed $keys
 * @param mixed $default
 * @return mixed
 * @package balphp
 * @author Benjamin "balupton" Lupton <contact@balupton.com> - {@link http://www.balupton.com/}
 * @copyright Copyright (c) 2009-2010, Benjamin Arthur Lupton - {@link http://www.balupton.com/}
 * @license http://www.gnu.org/licenses/agpl.html GNU Affero General Public License
 */
function delve ( $holder, $keys, $default = null) {
    # Prepare
    $result = null;
    $end = false;

    # Prepare Keys
    ensure_keys($keys, $holder);

    # Handle
    $key = array_shift($keys);
    if ( $key === null ) {
        # Reched the end of our key array, so holder must be what we want
        $result = $holder;
        $end = true;
    } else {
        switch ( gettype($holder) ) {
            case 'array':
                if ( array_key_exists($key, $holder) ) {
                    # We exist, so recurse
                    $result = delve($holder[$key], $keys, $default);
                } else {
                    $end = true;
                }
                break;

            case 'object':
                if (
                    /* Already accessible via normal object means */
                    isset($holder->$key)
                    /* Is Doctrine Record */
                    ||  (   ($holder instanceOf Doctrine_Record)
                            &&  ($holder->hasAccessor($key)
                                    ||  $holder->getTable()->hasField($key)
                                    ||  ($holder->hasRelation($key) && (!empty($holder->$key) || $holder->refreshRelated($key) /* < returns null, hence the OR and extra check > */ || isset($holder->$key)) ) // && $holder->$key->exists())
                                )
                        )
                    /* Is normal object */
                    ||  (   !($holder instanceOf Doctrine_Record)
                            &&  method_exists($holder, 'get')
                            &&  $holder->get($key) !== null
                        )
                ) {
                    # We exist, so recurse
                    $result = delve($holder->$key, $keys, $default);
                } else {
                    $end = true;
                }
                break;

            default:
                $end = true;
                break;
        }
    }

    # Check Default
    if ( $end && $result === null ) {
        $result = $default;
    }

    # Done
    return $result;
}

此处提供完整文件(和库): http://github.com/balupton/balphp/blob/master/lib/core/functions/_arrays.funcs.php

答案 21 :(得分:3)

国际化/区域设置支持

提供不同语言的应用程序翻译,并根据用户的区域设置提供适当的语言。

移动版

检测用户代理字符串并提供应用的移动/触摸友好版本。使用xhtml mobile profiles非常容易。

使用支持多个后端的ORM

作为开发人员和用户,通过编辑配置文件来交换数据库后端是很好的。这样,您可以运行SQLite等开发/单用户用途,以及PostgreSQL或MySQL等用于生产的东西。

(不显眼)Javascript被禁用时的通知

在关闭或禁用JS的情况下曾经使用Stack Overflow吗?有时我会忘记noscript已打开,并且SO有用地告诉我。然后,我可以决定是否要将其重新打开;但至少我知道我缺少功能,而不仅仅是认为应用程序是蹩脚的。

Firebug / Javascript日志记录

提供大量日志记录有助于调试ajax问题。只需在javascript中执行console.log(message)就会将消息记录到firebug中。在您的应用程序配置文件中有一个生产/开发开关,可以打开或关闭它(让php不在生产模式下生成日志消息)

答案 22 :(得分:2)

配置数据不在数据库中:应用程序数据属于数据库。 但配置设置没有。为什么呢?

  • 在每个PHP请求上查询数据库的运行时选项效率不高。
  • 设置不会每天更改,静态存储就足以满足大多数用例。
  • 数据库配置文件之间的差异,但数据库中剩余的运行时选项似乎很愚蠢。
  • IMO通常由于懒惰而完成,因为安全设置和修改文件(ini)存储比仅涉及另一个SQL表更多。
  • 作为例外,如果没有数据库存储,用户设置和每个域配置将无法管理。

虽然在实践中很少需要,但实际上我希望我的用户能够编辑运行时配置(每年一次)。因此,实际上我在config file modification functions上花费的时间比在数据库中需要的时间多。优点:比SQL配置表更容易备份和版本控制。

缺点:如果访问/归档/版本控制不是问题,那么如果与APC或memcached(为了高效访问)结合使用,SQL就会成为一个好的配置存储。缓存文件也是一种可能的解决方案。

答案 23 :(得分:2)

我知道这是可怕的代码,值得投票。只想举例说明内容协商实际上很容易实现。

function q_order($src) {
    $src = str_replace(",", ";q=0.99,", "$src;last;q=0.975");   // inject placeholder values
    foreach (explode(",", $src) as $prt) {   // split entries
        $q[trim(substr($prt, 0, strpos($prt, ";")))]   // append TOKEN until ";" 
        = floatval(substr($prt, strpos($prt, "q=") + 2));  // and first float after "q="
    }  
   arsort($q);
   return($q);
}   

这允许快速排序HTTP_ACCEPT标头,这对RSS和Atom提要格式之间的自动交替很有用。或者仅用于设置默认语言。 (无论如何,你经常需要语言标记/链接,但这比默认为英语更好。)

$lang = q_order($_SERVER["HTTP_ACCEPT_LANGUAGE"]);
if ($lang["de"] >= $lang["en"]) { ...

答案 24 :(得分:1)

自动永久链接

使用此功能,任何人都可以将其设置为链接的href,它将自动获取页面的URL以便于永久化。

//Gets the URL of the current page
//set $p to yes to echo the urlturn the url or no to re
function page_url($p)
{
    $s = empty($_SERVER["HTTPS"]) ? ''
        : ($_SERVER["HTTPS"] == "on") ? "s"
        : "";
    $protocol = strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
    $port = ($_SERVER["SERVER_PORT"] == "80") ? ""
        : (":".$_SERVER["SERVER_PORT"]);
    switch ($p)
        {
        case 'yes':
            echo ($protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI']);
            break;
        case 'no':
            return $protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI'];
            break;
        default:
            echo('javascript:alert(\'invalid Argument in function page_url($p)\')');
        }
}
function strleft($s1, $s2)
{
    return substr($s1, 0, strpos($s1, $s2));
}

答案 25 :(得分:1)

  你有个人挑剔和代码吗?   木马,特别是小东西   这可能算多少?哪个不好意思   代码或次要功能吗?   花费过多的时间   说得对吗?

正确引用数组键

任何非数字数组键(即非索引)都应该用单引号括起来,以确保在所有情况下都能正确处理PHP,并且在大多数优秀的代码编辑器中都会检测到语法。 e.g:

$array['key'];

不是

$array[key];

需要/包含一次

总是问自己为什么要使用require_once和include_once。大部分时间是为了防止您可能已经或可能没有提取的重复代码 - 如果这是可能的,您是否真的以最有效和最有效的方式编写了PHP?

清洁加载和提高速度的缓冲输出

添加:

ob_start('ob_gzhandler'); 

脚本的开始和:

ob_end_flush();

最后将压缩和缓冲脚本的输出,以便它们更快速地加载,并且在提供内容时不会以递增方式显示。

预定义循环

每次循环运行时,应在启动之前设置最大值。我看到太多涉及函数的事件(尽管这被广泛涵盖),即:

for($=0;$i<count($x);$i++){
// code
}

这意味着每次代码循环时都会运行count函数,这是低效的。做以下事情要好得多:

$stop=count($x);
for($=0;$i<$stop);$i++){
// code
}

RegEx与PHP字符串/数字处理程序

如果你正在处理字符串并且有一个PHP等价物,stripos,strncasecmp和strpbrk会更快,减少对RegEx的依赖。 strtr比preg_replace快5倍左右。 ctype_alnum,ctype_alpha和ctype_digit可用于帮助形成验证以代替RegExp。

清理工作区

完成后,请始终关闭数据库连接,并始终取消设置变量。它的好,如果是完美的,练习。

一致使用行情

一致使用单引号和双引号。即使你使用:

echo "this is a 'string' not a number";

不要使用:

echo 'this is a "string" not a number';

如果您需要撤消订单,请不要保持相同并转义递归引号。此外,PHP使用双引号封装的字符串更好,您可以封装变量而无需连接。例如:

echo "this and $thisvariable here";
// instead of
echo 'this and '.$thisvariable.' here';

答案 26 :(得分:0)

答案 27 :(得分:0)

人力不可用非常安全会话Cookie

我相信人类可读的cookie,当它们引用会话内容(即自动登​​录)时,就是一种安全威胁。根据PHP-Nuke的经验,这是完全(多年前,大约7版本)的管理员登录漏洞,我开始加密cookie。 此外,由于cookie几乎都是以明文形式传输的,我开始将它们绑定到IP ,或者更好地绑定子网。

I18n,l10n

本地化很重要。我从不在页面中写出人类可读的文字,我更喜欢使用共享的字符串库制作英文和意大利文的网站。通常我用英语单词覆盖那些尚未翻译的字符串以避免显示错误的字符串ID

主题支持

如果用户可以在浏览过程中更改主题,那么Web应用程序看起来非常专业。主题不仅意味着CSS,而且所有图形(图标,按钮)都必须可以更改,而无需触及核心。当我写phpMyBitTorrent高达1.2版本时,我付出了很多很多关注主题,不幸的是,这导致使用不同颜色/字体/图像曝光相同的确切布局。下一代主题是模板,因此您可以完全更改网站的外观。我相信使用MVC模式时模板化网站会更容易。

跨数据库支持

或者,更好,数据库的独立性。我不喜欢在我的代码中显式调用mysql_query()。我更喜欢在抽象层上运行查询,这允许我在不重写核心组件代码的情况下更改DBMS(即SQLite或Oracle)。

<强>登录

记录是简化调试和收集FFDA(现场故障数据分析)有用信息的最佳方法。 Apache log4php可以解决问题,但必须使用适当的日志记录语句正确检测代码以获取可用信息。许多学术研究表明开发人员从未达到足够的日志记录:他们记录太多或不够,并且由于缺少或不清楚日志记录声明,故障通常仍然不清楚。遗憾的是,日志随着时间的推移变得越来越胖,因此您必须只能保留那些可以帮助您找到有关应用程序问题的记录。日志也可以用于性能目的,但永远不要忘记开销日志引入。最后,我目前的高级论文是关于一套经过科学验证的日志记录规则,适用于复杂应用程序中的FFDA,每个开发人员都应该看一下。

<强> ORM

嗯,最后一点更多的是关于跨数据库支持。说实话,当我放弃PHP for ASP.NET时,我开始使用NHibernate ORM。如果我必须恢复PHP,我会首先找到一个合适的ORM来避免我的代码中的查询。

这些是我的聪明主意

答案 28 :(得分:0)

可读代码:

源代码必须写得很好,其他开发人员也很容易理解。它们必须具有短函数和离散类。它们必须具有描述性功能和类名,这将导致较少的注释。职能或班级必须承担单一责任。每个功能的参数数量有限。智能编写的代码需要更少的因子分解,易于升级,可扩展性等。

答案 29 :(得分:0)

<强>可测

我不是指一个快速的脚本,“健康检查”应用程序,这些大多是毫无价值的。如果强大的测试涵盖了大部分或全部代码,那么您和您的客户更有可能从精心设计的敏捷代码中受益。

<强>可读性

其他人将使用您的代码,稍后您将更新它。如果你无法阅读你的代码,它就毫无价值(评论不计算在内)。应该正确命名变量,并且应该易于识别上下文到上下文的流程。

for ( $i=0; $i < count($myList); $i++)  // obviously an index
foreach ( $k as $a => $b ) // wtf?
foreach ( $definitions as $word => $definition ) // better

答案 30 :(得分:0)

使用线程在后台尽可能多地工作。这样用户界面永远不会冻结。 当进程需要记录器超过一秒时才能完成显示好的进度条。

答案 31 :(得分:0)

人类可读的Cookie
我个人认为总是诉诸SESSIONs有点无用,因为变量更容易用PHP存储。

会话ID在技术上通常也是cookie,但不是人类可读和不透明的存储句柄。所以相反,如果它是简单的用户偏好(不是自动化的东西),我喜欢发送可读的cookie名称和值,例如product_order=descfav_background=orange

通常我也会参加会议。但对于我关心数据隐私(意味着用户权利)的个人项目,我忍受了所有的缺点:

  • 多个cookie的微管理开销。
  • 单独检查每个cookie的有效性,因为它们都成为用户输入。
  • 可能需要定义额外的到期Cookie或以其他方式随机续订。 (由于我发现2038个cookie的到期时间同样是非常的,并且只使用适当的时间。)
  • 不能用于与授权相关的任何内容,只能用于用户和显示选项。
  • 我认为识别真正的cookie和会话cookie之间的语义差异很重要。但是,如果几乎没有人看到它,在这里注意是否重要?

然而,它使我的数据隐私大脑部分感到高兴。对于some use cases来说,这是一个简单易懂的问题。

答案 32 :(得分:-1)

密码劫持
我们最初在这里得到了一个关于for-and anti-user security的答案。建议是关于用户注册,并使用提供的注册电子邮件检查用户SMTP / POP3(?)服务器提供的密码,如果用户懒惰地重复使用他的电子邮件/ pop3帐户密码,则会给出粗略的错误消息。

显然,它被低估了,因为闯入用户电子邮件帐户是有问题的(即使意图显然是为了教育)。所以答案被删除了。但我喜欢对用户粗鲁的元概念,如果它有助于他的安全。

其次我认为,虽然这个功能对于公共网站来说是合法的错误(如果事先没有明确的警告或事情),对于 Intranet Web应用程序来说这是一个非常可能的概念。我认为公司内部IT政策甚至是一个常见的事情,即确保密码在更敏感的系统中是独一无二的。