1

以前この質問をしましたが、回答がなかったので、最後の質問を削除し、質問を単純化/明確化し、再投稿しています


私はコミック サイトを持っています... SO スタイルのタグ付けシステムに取り組んでいます。ユーザーは、関連するすべてのコミックを表示する 1 つまたは複数のタグを選択できます。

ユーザーの選択を記憶するために、$_SESSION 配列に保存しています。

私が抱えている問題は、ユーザーが選択した後に $_SESSION['tagnames'] 配列に格納されている文字列の 1 つ「ビジネス」が配列に見つからないことです...

それが機能するはずの方法は、ユーザーがタグを選択し、それを選択解除するには、もう一度クリックすることです.スニペット:

    //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 ステートメントの 1 つです。どのタグ ID が選択されているかに基づいて変更されるクエリを正しく示しています。

ここに画像の説明を入力

var_dumpこれは$_SESSION['tagname']...タグ2と3(相違点と類似点)がすでに追加されていることを認識していることがわかります(以前は確認していました)が、 tagid array_search()1の「ビジネス」は見つかりません。明らかに数回追加されています。

ここに画像の説明を入力

選択したタグ名をユーザーに返す関数は次のとおりです。

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 キーを押して更新すると、タグ名 'business' が自動的に$_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() に送信します。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

際立った問題が 3 つあります (2 つは際立っており、1 つは非常に微妙です)。

1. DB 接続を 1 つだけ開き、そのままにします。

まず、関数内で接続を開いたり閉じたりするのではなく$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. 厳密な比較とテストを使用FALSEarray_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は以下によって台無しにされますforeach:

$tagnameでグローバルにアクセスしました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 に答える