echo 在函数内部还是外部?从自身调用函数?

Posted

技术标签:

【中文标题】echo 在函数内部还是外部?从自身调用函数?【英文标题】:Echo inside or outside the function? Call function from itself? 【发布时间】:2012-04-11 14:54:32 【问题描述】:

翻译模块

简介

到目前为止,我的代码正在运行,但我不知道这是否是实现我想要的正确方法。我有一个小功能可以翻译网页上的字符串。如果我用数字调用它,它会在一个表中搜索 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. 在函数内回显好还是在函数外回显好?

我已经阅读了this 问题,并且我不打算进一步操作字符串。所以,从那篇文章中,我猜最好的主意是像我已经做过的那样做,在函数内部呼应,但我想知道你对这个特殊情况的看法,因为我仍然不确定。 返回值并回显该值还是从函数中回显会更好吗?为什么?我的问题集中在性能和使代码友好。

2. 从函数内部调用这个函数有危险吗?

如您所见,在最后一行中我写了text(Wrong_sentence);。我知道你可以从另一个函数调用一个函数,但是你能从同一个函数调用一个函数吗?我担心它会进入一个调用自身的无限循环,例如,如果 table 关键字Wrong_sentence 被删除或修改。另外,我不知道可能存在其他安全后果。

欢迎对代码提供任何其他类型的反馈!

【问题讨论】:

我宁愿把这个发到codereview.stackexchange.com。 我实际上是从那里开始写这个问题的,但是因为它是a specific programming problem,所以我认为这会更好,因为它可以归类为Tools, best practices, improving, or conducting code reviews,所以我没有在那里问它。我不得不多次阅读这两个常见问题解答。 1:使用描述性标题。 “我有一个问题”是一个糟糕的标题。 2:每个问题问一个问题 简短回答:1. Read about separation of concerns. 将表示、业务逻辑和数据访问混合在一起是维护的噩梦。 2. 是的,你可以,这就是所谓的递归。递归可能很漂亮,如果你不注意你提到的无限递归,它可能很糟糕。递归调用没有比任何其他函数调用更多的安全问题。 meagar,抱歉并感谢您指出。我认为因为它们是如此相关并且对于相同的代码,它会很好。 @NullUserException,谢谢你的回答,我不完全理解关注点分离,但我会更努力地研究它。 【参考方案1】:

关注点分离是首先要处理的部分。那只是必不可少的。

通常,您所做的是对此有意义的全局函数。它至少应该在视图中可用。虽然我有些担心:

    全局变量:您使用全局变量,只是不喜欢那样。更糟糕的是,你甚至不检查里面有什么。如果您最终开始使用它们,请确保在使用它们之前检查它们。例如,它可能会被覆盖或任何会产生模糊错误的东西。

    关注点分离:这个函数应该只是向模型询问文本。就是这样。该模型可能返回 false/void/error 或仅返回文本。处理

    此函数的位置:通常,这在 MVC 术语中称为 Helper,因此查看 Helpers 可能会很有趣。例如在 Cakephp 中是这样的:http://book.cakephp.org/2.0/en/views/helpers.html 这样您就可以更标准地对其进行样式设置,并且您也可以使用标准,这使得其他开发人员很容易找到它。如果我看到一个我知道在哪里寻找它的助手,则可以在系统的任何位置定义一个全局函数。

    从不回显:回显不是很好,我们更愿意仅在需要时将它们直接放入视图中。为什么?因为它使调试结果更容易,我们只需要一种方法,但在变量和回显中使用它们。

    回显文本(123);

它不需要更多的代码或其他东西,但它会生成一个标准。例如,如果您在变量或其他方法中需要它:

echo strtotupper(text(123));

如果您正在测试您需要相同的内容,则需要该函数的响应。显然可以测试回声,但返回效果更好。

    网址与文字的组合:一段文字属于其他内容。该 URL 链接到该内容,但似乎不是正确的链接。例如,获取一个标题在 URL 中有错字的页面。 URL 已修复,但您的文本不再链接。

    在一个函数中组合 2 个功能:当您开始单元测试代码时,您会注意到为什么这会产生更多复杂性问题。您有 2 个函数,getTextById 和 getTextByKeyword。基本上你已经在这里看到了这个问题:

    "SELECT * FROM htranslations WHERE 关键字='$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("SELECT * FROM htranslations WHERE keyword='$Id'") or die ('Could not query:' .mysql_error());

只需创建一些 PDO 语句或其他安全的东西,并确保捕获错误、验证输入等。由于这类问题,已经看到了很多黑客行为。

    已有的解决方案:您不是第一个翻译文本的人。那么你为什么不看看已经可用的系统,比如支持多语言的框架或http://www.gnu.org/software/gettext/。已经有这么多花样了,为什么还要开发新的呢?

    递归:如果您当前使用错误的键调用您自己的函数,因为找不到错误,它将一次又一次地调用。只是不太好。将您的错误处理(这是一个开发错误)拆分为一个单独的类。这可以处理它自己的错误处理。这也是关注点分离。

显然,您可以添加更多反馈,但认为这可以让您完全开始重新思考您的方法。不仅有一个好的解决方案,而且您肯定可以在第一个概念上进行很多改进。

【讨论】:

真的很长很完整的答案,谢谢。关于您的第一个问题,已经检查了变量的值。关于其余的答案,有很多东西要学习,谢谢。此外,它全面地回答了这两个问题。再次感谢您的回答,我会好好“研究”它并改进我的代码。 感谢您的快速回复,希望对您的支持!关于第一个问题:不,不是。我会解释你为什么:就在你的一个脚本中的某个地方 $FullUrl='newpageurl/anotherurl.newextension';例如在新页面脚本中。那时您已经在某个时候检查了变量,但现在它变得无效并且可能会出现问题。所以请不要使用它们;) 是的,有些东西现在对我来说太高级了,但我正在学习很多。 $FullUrl 实际上不是“完整网址”。它只是当前目录。在此之前有一些代码会检查并从 $FullUrl 中删除每个“。”之后的所有内容。和每一个'?还有文件名。因此,对于页面 example.com/path/to/file.php?var=5&amp;varb=68,$FullUrl 将是 /path/to/ 回去查看旧问题并意识到我现在如何直观地完成几乎所有的建议(:我没有关注的唯一两个是这个 [now] 类的问题(不要'不需要/想要它专门用于此类)和已经可用的解决方案。Here is the final version of it。 听起来不错的改进和发展。也很高兴看到你将它发布在 GitHub 上,从那时起它可能会改进很多。【参考方案2】:

由于从其他答案和 cmets 中可以清楚地看出第二个问题,我将回答第一个问题(虽然我觉得回答自己很奇怪,但我为我的问题找到了更合适的答案)。我可以两者兼得,同时在室内或室外回响。代码如下:

// 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);
            
        
    

所以,如果我只想 ECHO 一些文本,我会写 tex(56)text(Existing_string)text(Non_existing_string)。但是要将这些相同的文本作为变量返回,我只需要写tex(56,1)text(Existing_string,1)"Non existing string"。请注意,要使用“非现有字符串”,我不需要传递它并返回自身。

该代码仍然存在许多问题,但正如您所见,我正在学习和改进它。到目前为止,这段代码运行良好。

【讨论】:

以上是关于echo 在函数内部还是外部?从自身调用函数?的主要内容,如果未能解决你的问题,请参考以下文章

python - 从自身内部调用函数

PHP局部变量与全局变量

js 函数内部创建的setTimeout调用自身函数

如何在类内部从自身调用方法?

JS 闭包

为啥我不能从内部调用一个类的 start 函数?