You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP 7.4.3环境下strpos/stristr等字符串检测函数服务器端失效问题排查及代码优化咨询

Let's break down exactly what's going wrong with your code on PHP 7.4, and walk through the fixes step by step:

1. The Root Cause: Uninitialized $result Variable

Your biggest issue is that $result isn't initialized before you start concatenating to it.

  • In PHP 8+, uninitialized variables used in string operations are automatically treated as empty strings (""), so your concatenation works as expected.
  • In PHP 7.4, an uninitialized $result is null. When you pass null to stristr() or strpos(), the function returns false (and may trigger a warning depending on your error settings), which breaks your button display logic.

2. Secondary Issue: String Concatenation Risk for Multi-Digit IDs

Even if you fix the initialization, concatenating IDs into a string like "123" creates a hidden bug: if you have a privacy ID like 10, checking if the string contains "1" will incorrectly return true (since "10" has a "1" in it). This will lead to false positives for consent status.

3. Security Risk: SQL Injection in Your SELECT Query

You're directly concatenating $_SESSION['USER_ID'] into your SQL query, which is a critical security vulnerability. Always use prepared statements for database queries that include user input (even session data, since it can be manipulated in some edge cases).


Optimized & Fixed Code

Here's the revised version of your PHP logic that addresses all these issues:

Full Revised Code Snippet

<?php include "../functions/notLoggedIn.php"?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous">
    </script>
    <!-- Eigenes CSS -->
    <link rel="stylesheet" href="custom.css">
    <!-- Titel der Webseite -->
    <title>Datenschutzeinwilligung</title>
    <!-- Favicon Icon -->
    <link rel="icon" href="./favicon.ico" type="image/x-icon" />
</head>
<body>
    <!-- Navigationsleiste -->
    <?php include_once "nav_logedin.php"?>
    <!-- Seiteninhalt -->
    <div class="container x-height-app">
        <h1 class="text-center mt-3">Datenschutzeinwilligung</h1>
        <?php
            include "mysql.php";
            
            // Use prepared statement to fetch agreed privacy IDs (no SQL injection risk)
            // Only select the PRIVACY_ID we need, not full rows
            $stmt = $mysql->prepare("
                SELECT privacy.PRIVACY_ID 
                FROM privacy 
                JOIN privacy_user ON privacy.PRIVACY_ID = privacy_user.PRIVACY_ID 
                WHERE USER_ID = ? 
                AND privacy_user.VALID_TILL IS NULL
            ");
            $stmt->execute([$_SESSION['USER_ID']]);
            // Fetch all IDs into an array (cleaner and safer than string concatenation)
            $agreedPrivacyIds = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);

            // Handle consent update
            if(isset($_POST['update'])){
                $PRIVACY = $_POST['privacy'];
                $USER_ID = $_SESSION['USER_ID'];
                $pdoQuery = "INSERT INTO privacy_user SET USER_ID=:USER_ID, PRIVACY_ID=:PRIVACY_ID, VALID_FROM=now()";
                $pdoQuery_run = $mysql->prepare($pdoQuery);
                $pdoQuery_exec = $pdoQuery_run->execute(array(":USER_ID"=>$USER_ID, ":PRIVACY_ID"=>$PRIVACY));
                
                // Use header redirect instead of meta refresh (avoids duplicate form submissions)
                header("Location: " . $_SERVER['PHP_SELF']);
                exit;
            }

            // Handle consent revocation
            if(isset($_POST['delete'])){
                $PRIVACY = $_POST['privacy'];
                $USER_ID = $_SESSION['USER_ID'];
                $pdoQuery = "UPDATE privacy_user SET `VALID_TILL`=now() WHERE USER_ID=:USER_ID AND PRIVACY_ID=:PRIVACY_ID AND VALID_TILL IS NULL";
                $pdoQuery_run = $mysql->prepare($pdoQuery);
                $pdoQuery_exec = $pdoQuery_run->execute(array(":USER_ID"=>$USER_ID, ":PRIVACY_ID"=>$PRIVACY));
                
                header("Location: " . $_SERVER['PHP_SELF']);
                exit;
            }
        ?>
        <!-- Verarbeitung personenbezogener Daten -->
        <div class="card-body">
            <div>
                <form method="post">
                    <div class="card shadow pb-2 bg-body rounded">
                        <h3 class="text-center card-header">Verarbeitung personenbezogener Daten</h3>
                        <div class="card-body">
                            <input type="hidden" value="1" name="privacy">
                            <?php 
                            // Use in_array() for accurate ID checking (no string matching bugs)
                            echo in_array(1, $agreedPrivacyIds) 
                                ? '<button class="btn btn-danger" name="delete" type="submit">Ich willige nicht ein</button>' 
                                : '<button class="btn btn-primary" name="update" type="submit">Ich willige ein</button>'; 
                            ?>
                        </div>
                    </div>
                </form>
            </div>
        </div>
        <!-- ... rest of your consent sections go here, using the same in_array() pattern ... -->
    </div>
    <!-- Footer -->
    <?php include_once "footer.php"?>
</body>
</html>

Key Improvements Explained

  • Array Storage for Consent IDs: We use $agreedPrivacyIds as an array to store consent IDs, eliminating any string-matching bugs and making the logic more readable.
  • Prepared Statements: All database queries use parameter binding to prevent SQL injection, which is a critical security best practice.
  • Reliable Redirects: Replaced <meta http-equiv='refresh'> with header() redirects, which prevents duplicate form submissions if the user refreshes the page.
  • Efficient Data Fetching: We only fetch the PRIVACY_ID column instead of full rows, reducing unnecessary data transfer from the database.

If you absolutely need to stick with the string approach for some reason, just initialize $result to an empty string before your loop:

$result = ''; // Add this line
foreach($users as $user){
    $result .= $user['PRIVACY_ID'];
}
// Then use strpos with string literals to avoid type issues
echo (strpos($result, '1') !== false) ? '<button class="btn btn-danger" name="delete" type="submit">Ich willige nicht ein</button>' : '<button class="btn btn-primary" name="update" type="submit">Ich willige ein</button>';

But the array approach is far more robust and less error-prone.

内容的提问来源于stack exchange,提问作者max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:29:08