【问题标题】:How to give meaningful names to functions in PHP?如何为 PHP 中的函数赋予有意义的名称?
【发布时间】:2015-09-24 09:21:46
【问题描述】:

这似乎是一个愚蠢而琐碎的问题。我在 PHP 中命名函数时遇到问题。我有两个函数可以根据学生的 id 或姓名和电子邮件检索学生的所有信息。

由于 PHP 没有与 JAVA 相同的函数重载,我很难命名函数。

这就是我所做的。这些是我给他们起的名字。

get_students_with_id($id)get_students_with_name_and_email($name, $email)

但是参数会增加。我需要一个更好更简单的解决方案来命名这些函数或方法。顺便说一句,它们都属于同一类。那我该怎么办?提前致谢。

【问题讨论】:

  • 这些函数名有什么问题?
  • 如果我想获取一个学生的 id、姓名、电子邮件、密码、班级、部门等。那么函数名称将类似于 get_student_with_id_and_name_and_email_and_password_and_class_and_section。你有我的问题吗?
  • 这很正常,get_student_by_id、get_student_by_email 等。除非您愿意,否则您不必为函数提供完整的有意义的名称和描述等。不幸的是,PHP 中没有函数重载,但您可以编写一个函数 get_student() 并使用 get_func_args() 来确定提供了哪种输入来选择获取信息的最佳方式。
  • 参数越多,函数名越复杂
  • 在我看来,您应该创建类似search_students(array $queries) 的方法,该方法接受一个或多个搜索查询(例如使用多维数组)。然后,该方法可以使用这些查询在数据库中搜索记录。为表中每个可能的列组合使用一种方法是愚蠢的。

标签: php function methods naming-conventions php-5.5


【解决方案1】:

在 PHP 中不存在方法覆盖的概念,例如在 JAVA 中,但您可以发送默认参数,例如:

get_students($id, $name = null, $email = null)

这意味着你不需要调用带有三个参数的函数。你可以通过一个调用它来做到这一点,它会假设它是 id。例如,如果您想让一个函数适用于上面的示例,您可以执行以下操作:

function get_students($id, $name = null, $email) {
  if (!empty($id)) {
    // Get students by their ids
  } else if (!empty($name) && !empty($email)) {
    // Get students by their names and emails
  }
}

你可以调用上面的函数:

get_students(1); //Will retrieve studen with id 1
get_students(null, "Name", "email@email.com"); //Will retrieve students with name "Name" and email "email@email.com"

【讨论】:

  • 感谢您的回答。我也想到了这个解决方案,但正如我所说的功能变得太重了。
【解决方案2】:

搜索方法可能如下所示:

class Student {

    public static $columns =  ['id', 'name', 'email', 'password', /* ... */];

    // Imagine that this method is called with the following array:
    // ['name' => 'Joe', 'password' => 'Pa55w0rD']
    public static function search(array $queries) {

        // We will be appending WHERE clauses to this SQL query
        $sql = 'SELECT * FROM students WHERE ';

        // Get the column names
        $parameters = array_keys($queries);

        // Create a parameterized WHERE clause for each column
        foreach ($parameters as & $param) {
            if ( ! in_array($param, self::$columns)) {
                throw "Invalid column";
            }
            $param = "{$param} = :{$param}";
        }
        // Squish parameterized WHERE clauses into one
        // and append it to the SQL query
        $sql .= implode(' AND ', $parameters);

        // The query will now look something like this:
        //     SELECT * FROM students WHERE name = :name AND password = :password

        // Prepare the SQL query
        $stmt = DB::instance()->prepare($sql);

        // Go over the queries and bind the values to the columns
        foreach ($queries as $col => $val) {
            $stmt->bindValue(":" . $col, $val);
            // Internally the query will look something like this:
            //     SELECT * FROM students WHERE name = 'Joe' AND password = 'Pa55w0rD'
        }
        // Execute
        $result = $stmt->execute();
        // ...
    }
}

要使用该方法,您可以执行以下操作:

$student = Student::search([
    'name'     => 'Joe',
    'password' => 'Pa55w0rD',
]);

您可能希望以更安全的方式处理数据(例如,确保密码经过哈希处理),但总体思路就在那里。

【讨论】:

    【解决方案3】:

    为什么不将get_students($id=0, $name='', $email='') 等用于其他参数,然后让函数根据传递的参数执行任何必要的操作?

    如果太多,请通过数组检查键。因此,如果 array('id' => 1) 被传递,那么 if (array_key_exists('id', $input)) {...} 将捕获它并继续实际的功能工作,但如果传递了其他键/值,则后续适当的 elseif 将捕获它。

    更新:根据我在问题中读到的一些 cmets,我认为这样的格式可能能够处理您的大多数用例。不确定您的数据库是什么,所以这是在考虑 MySQL 的情况下完成的。

    function get_students($input) {
        $where = array();
        $allowed_columns = array('id', 'name', 'email');
    
        foreach ($allowed_columns as $key) {
            if (!array_key_exists($key, $input)) continue;
            $where[] = "`$key` = '" . mysqli_escape_string($input[$key]) . "'";
        }
    
        if ($where) {
            $query = 'SELECT ... FROM `...` WHERE ' . join(' AND ', $where);
            // etc...
        } else {
            return false;
        }
    }
    

    【讨论】:

    • 我明白你的意思,但是函数本身变得太大和复杂。
    • 我不确定。您最终会得到一些顺序逻辑块;它永远不会真正做任何你不打算做的事情,因此要么功能包含在一个地方,要么分布在许多功能中。我假设这被引导到 SQL 中。所以制作一个$where = array() 并将其填入块中。最后,如果它不为空,则组装并运行查询;如果为空,则返回nullfalse 或任何合适的值。
    • 当你说 some 顺序逻辑块时,我不确定我的情况是否属实,因为我有很多争论的可能性。
    • 请查看答案的更新,并尽量保持对 Stark 的关注(jk,抱歉无法抗拒)
    【解决方案4】:

    我会使用一个类而不是多个函数

    class Student
    {
        public static function byName($name)
        {
            // ...
        }
    
        public static function byId($id)
        {
            // ...
        }
    }
    
    $student = Student::byName('joe');
    

    这将使它更加简洁和可扩展,因为您可以将通用逻辑放在类中受保护的静态方法中。

    如果你想做多个,你可以做一些更复杂的链接。

    我已经模拟了一个可以逆向工程的快速ideone:

    http://ideone.com/duafK4

    【讨论】:

    • 如果我需要通过 nameid 检索学生怎么办?
    • 我添加了一个我会做什么的例子。希望它不会太难理解。
    • 2 次调用或添加第三种方法
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多