【问题标题】:PHP, MySQL: How to retain and retrieve correct data when dealing with paginationPHP,MySQL:处理分页时如何保留和检索正确的数据
【发布时间】:2010-06-05 04:29:52
【问题描述】:

我有一个表单(由 25 个以上的字段组成),这些字段的值范围从很小的值到串联的字符串。这就像一个搜索工具。现在,当用户填写表单并提交信息时,他可以看到与表单中的条件匹配的所有相关数据。我一次向用户显示 15 条记录。我已经实现了分页以使用户也可以查看其他记录。

主要问题:

这部分,直到用户提交信息并取回第一组数据是好的。当用户尝试通过分页转到第二页(或他选择的任何页面)时,就会出现问题。用户能够导航到其他页面,但不会触发正确执行以从数据库中提取结果所需的查询。请注意,最初它是在表单中执行的 POST 操作,而分页执行的是 GET 操作。所以我丢失了用户输入的表单的值,我想保留这些值并使用这些值查询数据库。

我试图避免通过 GET 发送表单字段值,因为我担心数据可能会超过 URL 中允许的最大值(& 因为它不如 POST 操作安全)。如果我尝试使用 POST 操作(如更新查询),可以在结果页面上执行其他操作,这些操作可能会导致表单值丢失。会话不会真正起作用,因为用户可以选择在具有不同输入的不同选项卡中运行相同的表单来比较结果,这可能导致旧查询的数据被新查询的数据替换。我没有想到 cookie,因为用户可能选择阻止它。几乎所有的选择似乎都用尽了。

那么我可以做些什么来保留表单值,运行正确的查询并取回相关值,而不管同一用户在不同浏览器选项卡/窗口中处理相同表单的次数,而不使用会话(考虑到通过 GET 传递数据并可能在 POST 操作中丢失数据的限制)并且还能够在页面上执行其他活动?

提前谢谢你。

【问题讨论】:

    标签: php mysql forms pagination


    【解决方案1】:

    首先,GET 的安全性不亚于 POST。两者都不值得信任(修改 url 字符串更有吸引力,但绝不更难)...

    你有几个选择:

    第一,将保持搜索结果的全球“存储”。您可以使用带有id, data 的数据库表,其中数据是变量的序列化数组。然后当有人提交搜索时,检查数据是否在表中。如果是这样,请使用该 ID。如果没有,则序列化数据并插入(并获取 id)。然后重定向到如下页面:results.php?id=4。这样,他们可以共享链接,但它可以保持相当安全,不会被篡改(他们无法更改搜索参数)。这里的缺点是表格可能会变大。

    另一种方法是对数据进行 base64 编码并将其作为 get 参数 (base64_encode(serialize($data));) 传递。如果您担心篡改或网址长度,我会尽量避免这样做。

    另一种解决方案是拦截 JS 中的下一个链接点击,并使用它从隐藏变量向您的服务器发出 POST。

    编辑:删除了会话解决方案。意识到这对您的问题不起作用。

    【讨论】:

    • 感谢您的回复。存储在数据库中听起来不错。我只需要密切关注他们。我将更多地考虑如何使用相同的方法来完成它。谢谢。
    • 数据列上的索引(保存变量的序列化数组)将如何影响我们的搜索结果?上面的索引肯定会更快,但考虑到数据的长度,你有什么建议?
    • 好吧,创建两个索引。 id 上的 PK 和 data 上的索引。这样,这两个操作都是简单的索引查找...现在,由于数据的索引长度会更小(对 data 字段使用 Text 列,因此索引大约为 255 个字符),这不是真正的索引查找,但即使有数万或数十万次搜索,它也应该足够快......
    • 感谢您的澄清。欣赏它。
    【解决方案2】:

    我试图避免发送表单 通过 GET 获取字段值,因为我担心 数据可能超过最大值 URL 中的允许值

    然后您还必须使用表单进行分页,以便他们也可以发布。要么,要么您必须在服务器端的某个地方(可能在会话中)存储查询术语 - 但不要忘记用户可能一次打开多个选项卡,因此您需要能够存储超过按用户查询。

    但没有理由不能在单个会话中存储多个查询,例如$_SESSION['查询'][1234]。然后你的分页链接看起来像 ?query=1234&page=3

    但请考虑,用户能够共享其搜索结果的 URL 可能很有用。例如,如果 google 仅使用 POST,我无法向您发送指向 http://google.com/search?q=somequery 的链接

    (& 因为它不如 POST 操作安全)

    不是真的。

    【讨论】:

    • 感谢您的回复。在我的情况下,会话不太有用。您能告诉我您提到的有关 URL 共享的内容吗?我有点失去你了。
    • 假设您的用户 Bob 希望与他的同事 Sally 共享他在您的应用程序中查看的结果页面。为了使其正常工作,地址栏中的 URL 必须包含足够的信息来重建整个查询。
    • 感谢您的澄清。
    【解决方案3】:

    一种可能的方法是将您用于在数据库中搜索的整个查询存储在一个名为search_queries 的表中。该表应基本上包含两列,一个哈希和用于该搜索项的查询。

    当用户提交搜索表单时,他的查询被评估并插入到该表中,并且他被重定向到具有他的 search_hash 的页面。每次他导航到不同的页面时,他的哈希值都会从数据库中提取出来,并相应地重新评估结果——当然还有适当的 LIMIT。

    确保你 cron 那个表(为此你可能需要每个搜索项的时间戳)

    此方法的另一个可行实现是将查询存储在 SESSION 变量中,并将其用于查询目的。对于分页,您可以使用/search?page=1,而您的_SESSION['query'] 将是例如"SELECT * FROM Topics WHERE title LIKE '%test%'"。你基本上会添加"LIMIT "+($page*$perpage)+", $perpage"

    但是,后一种方法无法检测到该用户在网站上拥有的多窗口。您可以在 _SESSION['queries'] 中使用一个数组,并让用户提交一个 /search?id=0&page=1 ,其中 id 代表您在该窗口中查询的数组的哪个查询。

    【讨论】:

    • 感谢您的回复。在我的情况下,会话没有多大用处。我曾考虑按照 ircmaxell 的建议在 DB 中使用存储,并且我看到您以不同的方式提出了类似的方法。谢谢你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-28
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2012-11-24
    • 2014-04-21
    相关资源
    最近更新 更多