翻译模块
介绍
到目前为止,我的代码正在工作,但我不知道这是否是实现我想要的正确方法。我有一个小函数来翻译我的网页上的字符串。如果我用一个数字调用它,它会在一个表中搜索 id,并且仅在它用于该页面时才显示它。如果我用字符串调用它,它会在另一个表中搜索该字符串,如果该字符串不存在,该函数会打印传递的字符串,将"_"替换为带有警告的空格。
我想知道有两件事是否正确实现(如前所述,它们有效,但我不确定它们是否是一个好主意)。但首先是代码。
代码
// Function to output language strings.
function text($Id)
{
// Already defined and tested that are valid (sql injection avoided also)
global $Lang;
global $FullUrl;
if (is_int($Id)) // If a number is being passed
{
$results = mysql_query("SELECT * FROM translations WHERE id='$Id' AND page='$FullUrl'") or die ('Could not query:' . mysql_error());
$row = mysql_fetch_assoc($results);
if (!empty($row[$Lang])) echo $row[$Lang]; // If there is some, echo it
else error($FullUrl,$Lang); // Else, calls error function
}
else // If a string is being passed
{
$results = mysql_query("SELECT * FROM htranslations WHERE keyword='$Id'") or die ('Could not query:' . mysql_error());
$row = mysql_fetch_assoc($results);
if (!empty($row[$Lang])) echo $row[$Lang]; // If it exists in the table, echo it
else // Else (it doesn't exist)
{
$NewId = str_replace("_", " ", $Id); // Replace the "_" with " "
echo "<span style='color: red;' title='"; // Set a red color (warning)
text(Wrong_sentence); // Call this function and echo "This sentence could be wrong"
echo "'>".$NewId."</span>"; // Echo the passed string with spaces
error($FullUrl,$Lang,$Id);
}
}
}
1.功能内部回声还是功能外回声更好?
我已经阅读了这个问题,我不打算进一步操纵字符串。所以,从那篇帖子中,我猜最好的主意是像我已经做的那样,在函数内部回响,但我想知道你对这种特殊情况的看法,因为我仍然不确定。返回值并回显该值还是从函数中回显该值会更好?为什么?我的问题集中在性能和使代码友好上。
2. 从函数内部调用此函数有危险吗?
如您所见,在我写的最后一行中text(Wrong_sentence);
.我知道您可以从另一个函数调用一个函数,但是您可以从同一个函数调用一个函数吗?我担心它会进入调用自己的无限循环,例如,如果 table 关键字Wrong_sentence
被删除或修改。另外,我不知道可能存在的其他安全后果。
代码提出任何其他反馈!!
关注点分离是要注意的第一部分。这只是一个必不可少的。
通常,您所做的是一个对此有意义的全局函数。它至少应该在视图中可用。虽然我有一些担忧:
- 全局变量
:你使用全局变量,只是不喜欢这样。更糟糕的是,你甚至不检查里面有什么。如果您最终开始使用它们,请确保在使用它们之前检查它们。例如,它可能会被覆盖或任何产生模糊错误的东西。
关注点分离:此函数只应向模型请求文本。就是这样。该模型可以返回假/空/错误或仅返回文本。处理
此函数的位置:通常,这在 MVC 术语中称为帮助程序,因此查看帮助程序可能会很有趣。例如在CakePHP中,像这样:http://book.cakephp.org/2.0/en/views/helpers.html 这样,您可以以标准方式对其进行样式设置,并且还可以使用标准,这使得其他开发人员可以轻松找到它。如果我看到一个帮助程序,我知道在哪里查找它,可以在系统的任何位置定义全局函数。
从不回显:回声并不好,我们更喜欢只在需要时将它们直接放入视图中。为什么?因为它使调试结果更容易,我们只需要一种方法,但在变量和回显中使用它们。
回显文本(123);
它不需要更多的代码或其他东西,但它会生成一个标准。例如,如果您在变量或其他方法中需要它:
echo strtotupper(text(123));
如果你正在测试你需要相同的,你需要来自函数的响应。显然,可以测试回声,但返回效果要好得多。
网址和文本的组合:一段文本属于其他内容。URL 链接到该内容,但似乎不是正确的链接。例如,以标题的页面为例,URL 中有拼写错误。网址已修复,但您的文本不再链接。
在一个函数中组合 2 个功能:当您开始单元测试代码时,您会注意到为什么这会产生更多复杂性问题。你有2个函数,getTextById和getTextByKeyword。从本质上讲,您已经在这里看到了问题:
"从翻译中选择 *,其中关键字='$Id'"
您正在查找一个似乎是关键字的$Id。容易出错的代码。选择一种口味并坚持下去。一般来说,我不喜欢硬编码的id,因为它们什么都不说。所以我建议使用类似的东西:
text('CONTACT_ADDRESS')
这种标记是可读的(这在视图中很重要,而且很有意义。例如一个不好的:
<p><?php text(24234); ?></p>
<p><?php text(96985); ?></p>
你不知道它是什么。但是,如果我在视图中写下这个,那就完全清楚了:
<p><?php text('ORGANISATION_INTRODUCTION'); ?></p>
<p><?php text('ORGANISATION_FOUNDERS'); ?></p>
这是 2 段文字,但现在你知道是哪些。此外,如果您看到页面本身,您也知道在哪里可以找到它们。如您所见,这些简单示例使用页面前缀,但显然也可能有全局文本。就像侧边栏中的文本一样。根据您的需求,这里有很多选择。您甚至可以自动添加页面名称等。
滥用MySQL函数:不要再这样做了:
$results = mysql_query("从 htranslations 中选择 * WHERE 关键字='$Id'") 或死亡('无法查询:' . mysql_error());
只需创建一些PDO语句或其他安全的东西,并确保捕获错误,验证输入等。由于此类问题,已经看到了许多黑客攻击。
已经可用的解决方案:您不是第一个翻译文本的人。那么,您为什么不看看例如支持多语言或 http://www.gnu.org/software/gettext/的框架等已经可用的系统。已经有这么多花样了,为什么要开发一个新的?
递归:如果你用错误的键调用你自己的函数,错误是找不到它,它会一次又一次地调用。只是不太好。将错误处理(这是一个开发错误)拆分为单独的类。这可以处理它自己的错误处理。这也是关注点的分离。
显然,您可以添加更多的反馈,但认为这可以让您完全开始重新思考您的方法。不仅有一个好的解决方案,而且可以肯定的是,您可以在第一个概念上进行很多改进。
由于第二个问题从其他答案和评论中很清楚,我将回答第一个问题(虽然我认为回答自己很奇怪,但我为我的问题找到了一个更合适的答案)。我可以同时拥有两者,在内部或外部同时回响。这是代码:
// Function to output language strings.
function text($Id)
{
// Already defined and tested that are valid (sql injection avoided also)
global $Lang;
global $FullUrl;
$numargs = func_num_args(); // Get the number of arguments that are being passed.
if ($numargs == 2) // If there are actually two
$Var=func_get_arg(1); // Set $Var with the second value (1).
if (is_int($Id)) // If a number is being passed
{
$results = mysql_query("SELECT * FROM translations WHERE id='$Id' AND page='$FullUrl'") or die ('Could not query:' . mysql_error());
$row = mysql_fetch_assoc($results);
if (!empty($row[$Lang]) && !isset($Var)) echo $row[$Lang]; // If there is some, echo it
elseif ($Var==1) return $row[$Lang];
else error($FullUrl,$Lang); // Else, calls error function
}
else // If a string is being passed
{
$results = mysql_query("SELECT * FROM htranslations WHERE keyword='$Id'") or die ('Could not query:' . mysql_error());
$row = mysql_fetch_assoc($results);
if (!empty($row[$Lang]) && !isset($Var)) echo $row[$Lang]; // If it exists in the table, echo it
elseif (!empty($row[$Lang]) && isset($Var)) return $row[$Lang];
else // Else (it doesn't exist)
{
$NewId = str_replace("_", " ", $Id); // Replace the "_" with " "
echo "<span style='color: red;' title='"; // Set a red color (warning)
text(Wrong_sentence); // Call this function and echo "This sentence could be wrong"
echo "'>".$NewId."</span>"; // Echo the passed string with spaces
error($FullUrl,$Lang,$Id);
}
}
}
所以,如果我只想回显一些文本,我会写tex(56)
、text(Existing_string)
或text(Non_existing_string)
。但是要返回这些相同的文本作为变量,我只需要写tex(56,1)
、text(Existing_string,1)
或"Non existing string"
。请注意,要使用"不存在的字符串",我不需要传递它并返回自身。
该代码仍然存在许多问题,但正如您所看到的,我正在学习和改进它。到目前为止,这段代码运行良好。