询问 PHP 中的易用性以及为什么无法执行我描述的操作

Query about ease of use in PHP and why it is not possible to do what I describe

[不是重复的 - 请参阅问题底部的解释]

我对我一直在思考的事情有​​疑问 - 开始为大型站点编写 PHP 代码,以及为什么无法最大限度地简化 PHP 代码。

我的意思是: 我正在处理的网站有一个 functions.php(你猜对了)他们所有的 PHP-function - login-function + 所有 getTable-/insertTable-/updateTable-functions 等等

所以它有一个 getAllVideos-function 用于显示页面上所有视频的页面......和一个 getVideo-function 用于视频查看页面,您可以在其中播放 select ed 视频...和主页的 getVideoRecommended-function,在顶部您可以查看推荐的视频 selected 并按推荐算法排序...还有一个 updateAvatar-function 供用户查看更新他们的头像图片...然后...您得到图片...

总而言之,对于所有 login-/video-/userinfo-/get-/insert-/update-/etc-functions,functions.php 文件有 21.347 行长,有时很难进行故障排除。

所以大约 10 秒后,我思考并发现,我认为这是一个非常合理的解决方案,可以真正简化代码,使其长约 2-300 行,并且非常容易排除故障...然后我试过了,很失望它不起作用,也不明白为什么。

解决方法: 作为一个例子,首先我们写一个 all-inclusive get-function ,其中包含要传递的所需变量,并在可能的情况下将它们的默认值设置为 ALL

<?php
    function getTable($pdo,$columnNames = "*",$tableNames,$condition = 1,$orderBy = "date",$limitOffset = 0,$limitMax = 65000) {
    // Reset variables
    // Reset session cookies

然后我们尽可能使用变量中的值进行查询

    $prepareTable = $pdo->prepare( "SELECT ? FROM ? WHERE ? ORDER BY ? LIMIT ?, ?" );
    $prepareTable->execute([$columnNames,$tableNames,$condition,$orderBy,$limitoffset,$limitmax]);
    $getTable = $prepareTable->fetchAll();

然后我们检查是否找到任何东西并做我们需要做的事情

    if (!getTable) {
        // Take appropriate action, or write appropriate error message
    } else {
        // make a variable for each column by exploding $columnNames by , and create a session cookie for each to use on webpage
        $columnName[] = explode(',',$columnNames);
        foreach ($columnName as $row) {
            $_SESSION['variable'][] = $row['$columnName'];
        }
    }
?>

就是这样...您现在只有一个 select 查询可以满足您的所有需求

现在假设在视频页面上我想显示所有视频缩略图+标题+描述我只是通过首先定义必要的变量来调用所有视频

<?php
    $columNames = "thumbnail,title,description";
    $tableNames = "videos";

然后只需调用 getTable-function(所有查询都相同)

    getTable($pdo, $columnNames, $tableNames, $condition, $orderBy, $limitOffset, $limitMax)
?>

它会写一个 select 看起来像

的语句
SELECT thumbnail,title,description FROM videos WHERE 1 ORDERBY date LIMIT 0, 65000

并从网站上的所有视频中搜索和查找缩略图、标题和说明

或者假设我希望它们按标题排序,我只需添加

    $orderBy = title;

等等

如果我只想要 5 个结果,我会添加

    $limitMax = 5;

等等

你明白了。

使用这种方法,您可以只使用一个 getTable-function 来创建您想要的任何可能的 SELECT-statement(这同样适用于只有一个 INSERT-statement,只有一个 UPDATE-statement,等等),无论您的站点大小如何,都将 function.php 从超过 20.000 行减少到不到 200 行。

此外,在故障排除方面:

Troubleshooting now:
There is a problem with the channel-page...
1. go to channel-page and see what function is used
2. go to functions.php and scroll through 20.000+ lines to find the function used
3. find, fix and check error
4. (if more than one function used) repeat 2, 3 and 4 as many times as necessary

Troubleshooting with my approach:
1. go to channel-page and find, fix, and check error in 2-20 lines of code where the getTable-function is called
And Done!

因此,无论您的站点和数据库的大小如何,我的方法不仅会大大减少 functions.php 的大小,最多减少 300 行代码...而且一旦您检查过它是否适用于一个您现在再也不必返回并再次检查 functions.php 页面是否有错误...从那时起,所有错误都将始终在出现问题的特定页面上找到...并且所有故障排除都将在 max 上完成9 行代码 pr。 function-call 检查您定义的变量...仅此而已...

我想问一下这个网站上的好人,为什么 PHP 使我的解决方案无法工作? (您不能为 colomNames、TableNames、整个条件、and/or orderBy 使用变量 - 您仍然需要在条件中指定 columnNames、tableNames 和 columnName,并根据需要在单独的函数中指定 orderBy

SELECT title (columnNames)
FROM videos (tableNames)
WHERE username = ? (condition)
ORDER BY date (orderBy)

等等,这使得有必要为您的每个需求单独制作一个 getTable-function,这违背了我的解决方案的目的,并使 functions.php 随着您的需求、站点和数据库的增长而增长)

我的解决方案怎么不可能?

有人请告诉我为什么将变量传递给 columnNames、tableNames、entire condition 和 orderBy 比其他值更具有安全风险(至少到了不能执行我上面描述的事情的程度) )

编辑:删除了可能重复但无关紧要的第二个问题,因为它......对于我寻求答案的主要问题来说微不足道

提前致谢

APM

区别:

我只问 IF/HOW 这可能是事后的想法(因为可能有一个我没有考虑过的解决方案 - 似乎已经存在 - 请参阅已接受的解决方案)

我知道它被认为是一种安全风险,因为它破坏了准备好的语句的安全性......而且我知道不可能完全按照我的意愿去做(已经抛出足够多的致命错误来知道这一点).. .我的主要问题不是如何或为什么我不明白为什么代码不起作用...我的主要问题是为什么不可能做我描述的事情?:

他们可以根据需要经常推荐正确的用法 - 但在 SELECT-/UPDATE-/INSERT-query 安全不是问题的情况下 - 比如显示所有视频或显示一些视频deos 或...为什么他们无法执行我的建议?

就目前而言 - 做我想做的事(显着减少代码,更重要的是使故障排除成为 breeze)我将不得不使用公认的解决方案,它比我想要的要麻烦一些做(但仍然比现在做的要好得多)或使用两个数据库连接 - 一个 PDO(例如安全至上的登录功能)和一个 'old-school' mysqli-query security-not-needed 函数...

这只会带来一系列全新的问题

这就是我的问题不同的原因... 我的问题更像是一个哲学问题,为什么我没有选择采取所需的安全措施并在我想要的时候跳过安全措施,因为这是我的网站可以随心所欲地处理(理论上)......是安全风险真的很大,我不应该被允许这样做吗?如果是,为什么? - 这是我的主要问题...

Shadow...请删除您的重复声明或指出我的主要问题已被提出和回答的地方(顺便说一句,您链接到的问题没有涵盖)

这不是安全问题,而是与您的操作有关。

prepare 准备对数据库的查询('compiling'、优化等),然后等待变量。显然它需要所有 SELECTS 等。

然而,您可以构建一个字符串,如 "SELECT $a FROM $b WHERE $c = ?" 等,它应该可以工作。

您的问题似乎归结为想要对 SQL 语句的部分使用占位符,但对于任何部分,而不仅仅是它们设计的实际参数。您可以使用变量插值 ("SELECT {$fields} FROM {$table} WHERE {$whereClause} ORDER BY {$orderField} {$orderDirection}") 构建它们,但这也可能会消除准备语句(占位符中的数据)提供的一些安全性。

像'whereClause'这样的字符串仍然可以使用占位符,但它们必须传入并匹配(命名占位符会使这更容易)。

$whereClause = "(tablename.username = :username) OR (tablename.userid = :userid)";
$orderField = 'tablename.username';
$orderDirection = 'DESC';
$parameters = ['username' => 'fred', 'userid' => 5];

更好的长期解决方案是将查询拆分为各种 class 查询,这些查询可以重复使用并从发生 SQL 构建的公共基础扩展。在这里,查询将在它们自己的 classes 中,可能以数据库表名命名。例如,您可以让(抽象的)base-class 需要从子 classes 方法。将这些方法放入 classes 中也应该能够进行更好的测试——如果您先编写测试(编写您期望能够发生的事情),然后编写代码以允许测试 运行成功。

然后,您还可以在 classes 中创建更专门的函数,用于更复杂的查询。

更好的是使用一个通用库,该库使用像 'Object Relationship Mapper' (ORM) 或 'Active Record'.

这样的设计模式