1

我之前问过这个问题,但没有得到回应,所以我删除了最后一个问题,并简化/澄清了问题,并重新发布


我有一个漫画网站...我正在开发一个 SO 风格的标记系统。用户可以选择一个或多个标签来显示所有相关的漫画。

为了记住用户的选择,我将它们存储在 $_SESSION 数组中。

我遇到的问题是,在用户选择后存储在 $_SESSION['tagnames'] 数组中的字符串之一“业务”在数组中找不到...

它应该工作的方式是用户选择一个标签,然后取消选择它,他们再次单击它......所以我检查字符串是否在 $_SESSION 中......如果是,取消设置它......这里是一个片段:

    //var_dump shows these are both set fine when a user clicks on the tag they want
    $tagid = (isset($_GET['tagid']) ? ($_GET['tagid']) : null); 
    $tagname = (isset($_GET['tagname']) ? ($_GET['tagname']) : null); 

    ...

//Tag IDS are added and removed without issue:
    //if tag id exists in $_SESSION['tags'] array, remove it 

    if ($key = array_search($tagid, $_SESSION['tagids'])) {
        unset($_SESSION['tagids'][$key]);
    }
    else {
        $_SESSION['tagids'][] = $tagid;
    }

    ...

//but one of the tag names, 'business', is not being removed... and is actually added again even when I press F5 to refresh

    if ($key =  array_search($tagname, $_SESSION['tagname'])) {
        unset($_SESSION['tagname'][$key]);
    }
    else {
        $_SESSION['tagname'][] = $tagname;
    }

这是var_dumpsql 语句的一个:它正确地显示正在根据选择的标记 id 更改的查询。

在此处输入图像描述

这是其中的一个var_dump……$_SESSION['tagname']你可以看到它识别出标签 2 和 3(差异和相似之处)何时已经添加(我曾经array_search()检查过),但它没有找到 tagid 1,'business',即使它是显然被添加了好几次。

在此处输入图像描述

这是将所选标签名称返回给用户的函数:

function getSelectedTags() {

 global $tagid, $tagname;

    if ($key =  array_search($tagname, $_SESSION['tagname'])) {
        unset($_SESSION['tagname'][$key]);
    }
    else {
        $_SESSION['tagname'][] = $tagname;
    }

    var_dump($_SESSION['tagname']);

    foreach ($_SESSION['tagname'] as $tagname) { 
        echo '<span class="tags">' . $tagname . '</span>';
    }
}

任何想法为什么标记名称“业务”是唯一导致问题的原因?

即使在我销毁会话后,按 F5 刷新也会自动将标记名“业务”放入$_SESSION['tagname'] array.


编辑:更全面的代码:

Homepage.php:用户单击从 getDBTags() 返回的标签以将标签添加到 imageDisplay.php 上的 $_SESSION 数组

<h5>Tags</h5>
<?php echo getDBTags(); ?>
<br/>
<p>Your tags:</p>
<?php echo getSelectedTags(); ?>

imageDisplay.php:负责处理图像如何过滤和显示...

getDBTags()从数据库中返回标签选择,以便用户可以点击它们:

function getDBTags() {
include 'dbconnect.php';

global $cat;

$sql = "SELECT tagid, tagname FROM tags";

$query = $mysqli->query($sql);

while ($row = $query->fetch_assoc()) {
    echo '<span class="tags"><a href=".?action=homepage&cat='.$cat.'&tagid='.$row['tagid'].'&tagname='.$row['tagname'].'">'.$row['tagname'].'</a></span>';
}
mysqli_close($mysqli);
}

getFilters()决定如何通过动态查询过滤图像,然后将查询发送到 pagination(),它在页面上显示过滤后的图像。

function getFilters() {
include 'dbconnect.php';

global $cat, $site, $table, $tagid;

$order = " ORDER BY date DESC";

//if tag id exists in $_SESSION['tags'] array, remove it 
if ($key = array_search($tagid, $_SESSION['tagids'])) {
    unset($_SESSION['tagids'][$key]);
}
//if it doesn't, add it
else {
    $_SESSION['tagids'][] = $tagid;
}
//var_dump($_SESSION['tagids']);

if ($cat != null) $catquery = " AND catidFK = $cat";
else $catquery = null;

$sql = 
 "SELECT c.*, t.* 
 FROM comics c 
 INNER JOIN comictags ct ON (c.id = ct.comicID)
 INNER JOIN tags t ON (t.tagid = ct.tagID)
 WHERE ct.tagID IN ('" . implode(', ', $_SESSION['tagids']). "')
". $catquery ." " . $order;

if (!$mysqli->query($sql)) printf("<br /><b>Error:</b> %s\n", $mysqli->error); 

$query = $mysqli->query($sql);

var_dump($sql);
mysqli_close($mysqli);

return $query;
}

getSelectedTags()将选定的标签标题返回给用户,以便他们可以看到他们选择的内容。如果他们再次单击一个标签(从上面的getDBTags()返回),它将从 $_SESSION['tagname'] 中删除该标签。这是问题区域:

function getSelectedTags() {

global $tagid, $tagname;
if ($key =  array_search($tagname, $_SESSION['tagname'])) {
    unset($_SESSION['tagname'][$key]);
}
else {
    $_SESSION['tagname'][] = $tagname;
}
//var_dump($key =  array_search($tagname, $_SESSION['tagname']));
var_dump($_SESSION['tagname']);

foreach ($_SESSION['tagname'] as $tagname) { 
    echo '<span class="tags">' . $tagname . '</span>';
}

}
4

1 回答 1

1

有三个突出的问题(两个突出,一个非常微妙)。

1.只打开一个DB连接并离开它:

首先,不要在函数中打开和关闭连接,而是$mysqli在脚本开始时执行一次并保持打开状态。您需要修改您的函数以接受$mysqli作为参数(首选)或通过global $mysqli;(非首选)访问它。无需调用mysqli_close(),因为这是隐式完成的。

在您的getFilters()函数中,您实际上是在关闭 MySQLi 资源$mysqli,然后尝试查找结果资源return $query;在哪里$query。这样做会使结果资源无用。

// Pass $mysqli as a parameter
function getFilters($mysqli) {
  //...
  // Do alll your stuff...
  // And do not call mysqli_close()!
  return $query
}

2. 使用严格的比较和测试FALSEwith array_search()

使用时array_search(),如果您的结果是数组中 key 处的第一个元素,则[0]周围if ()条件会将其视为虚假返回,而不是应有的肯定结果。因此,位置处的标签[0]将被重复添加而不是删除。这将需要在几个地方修复......

// First get the key, which is an int or FALSE
$key = array_search($tagid, $_SESSION['tagids']);
// Unset if it is FALSE by strict comparison
if ($key !== FALSE) { 
  unset($_SESSION['tagids'][$key]); 
} 
else {
   $_SESSION['tagids'][] = $tagid;
}

3. 全局变量$tagname被 a 破坏了foreach

您已访问全局$tagnamein getSelectedTags()。但是在那个函数中,你有一个foreach循环:

foreach ($_SESSION['tagname'] as $tagname)

$tagname在那里用作循环的变量时,它实际上是$tagname在每次迭代时覆盖全局。您需要将其更改为不同的值,或者无论何时调用getSelectedTags()$tagname全局都将成为最后一个标签的任何内容$_SESSION['tagname'],无一例外。

// use a different varname in the loop
foreach ($_SESSION['tagname'] as $tn) {
  // Also calling htmlspecialchars to escape here. Do this in any variable to HTML output...
  echo '<span class="tags">' . htmlspecialchars($tn) . '</span>';
}
于 2013-03-02T00:56:30.330 回答