PHP删除.htaccess中指定RewriteRule失败问题求助
解决PHP删除.htaccess指定RewriteRule失败的问题
问题场景
尝试通过PHP删除.htaccess中选中的RewriteRule规则,但系统提示无法找到对应规则,无法完成删除操作。.htaccess文件权限为644,相关代码及.htaccess内容如下:
用户提供的PHP代码(版本1)
<?php if (isset($_GET['delete_id'])) { $delete_id = $_GET['delete_id']; // 获取要删除页面的slug $statement = $pdo->prepare("SELECT page_slug FROM tbl_page WHERE page_id=?"); $statement->execute([$delete_id]); $page_slug = $statement->fetchColumn(); $htaccess_path = '../.htaccess'; $htaccess_content = file_get_contents($htaccess_path); $rewrite_rule = "RewriteRule ^".$page_slug."/?$ page/".$page_slug." [NC,L]"; $pattern = "/".preg_quote($rewrite_rule, '/')."/"; $htaccess_content = preg_replace($pattern, '', $htaccess_content, 1, $count); if ($count === 0) { $_SESSION['error_message'] = 'Error: Could not find RewriteRule for ' . $page_slug . ' in .htaccess'; } else { // 将更新后的内容写回文件 file_put_contents($htaccess_path, $htaccess_content); if ($htaccess_content === false) { $_SESSION['error_message'] = 'Error deleting RewriteRule from .htaccess'; } else { $_SESSION['success_message'] = 'RewriteRule deleted successfully.'; } } // 从数据库删除页面 $statement = $pdo->prepare('DELETE FROM tbl_page WHERE page_id = ?'); $statement->execute([$delete_id]); header('Location: ' . BASE_URL_ADMIN . 'page'); exit; } ?>
用户提供的PHP代码(版本2)
<?php if (isset($_GET['delete_id'])) { $delete_id = $_GET['delete_id']; // 获取要删除页面的slug $statement = $pdo->prepare("SELECT page_slug FROM tbl_page WHERE page_id=?"); $statement->execute([$delete_id]); $page_slug = $statement->fetchColumn(); // 从.htaccess移除对应的RewriteRule $htaccess_path = '../.htaccess'; if (file_exists($htaccess_path) && is_writable($htaccess_path)) { $htaccess_content = file_get_contents($htaccess_path); $htaccess_content = preg_replace("/RewriteRule \^" . preg_quote($page_slug, '/') . "\/?$ page\/" . preg_quote($page_slug, '/') . " \[NC,L\]\n?/m", '', $htaccess_content, 1, $count); if ($count === 0) { echo 'Error: Could not find RewriteRule for ' . $page_slug . ' in .htaccess'; } else { file_put_contents($htaccess_path, $htaccess_content); if ($htaccess_content === false) { echo 'Error deleting RewriteRule from .htaccess'; } else { echo 'RewriteRule for ' . $page_slug . ' has been successfully removed from .htaccess'; } } } else { echo 'Error deleting RewriteRule from .htaccess'; } } ?>
当前.htaccess内容
RewriteEngine On # If the requested file or directory does not exist RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # Rewrite the URL to append .php and try again RewriteRule ^([^\.]+)$ $1.php [NC,L] # If the requested directory exists, add a trailing slash and try again RewriteCond %{DOCUMENT_ROOT}/$1 -d RewriteRule ^(.*[^/])$ /$1/ [R=301,L] RewriteRule ^ewewe/?$ page/ewewe [NC,L] RewriteRule ^ffffff/?$ page/ffffff [NC,L] RewriteRule ^demo/?$ page/demo[NC,L]
问题分析
- .htaccess语法错误:最后一条规则
RewriteRule ^demo/?$ page/demo[NC,L]中,page/demo和[NC,L]之间缺少空格,这会导致Apache解析错误,同时直接让正则匹配失败。 - 正则匹配过于严格:现有正则要求规则完全匹配(包括空格、格式),但实际场景中可能存在多余空格、换行差异,或者规则参数格式变化,都会导致匹配失败。
- 代码逻辑缺陷:版本1未检查文件可写性,版本2的正则转义处理不够灵活,且部分逻辑判断错误(比如用读取的内容判断写入结果)。
解决方案
步骤1:修复.htaccess语法错误
先修正最后一条规则的空格问题,确保所有RewriteRule格式一致:
RewriteRule ^demo/?$ page/demo [NC,L]
步骤2:优化PHP删除逻辑
使用更灵活的正则表达式,允许规则前后有空格、换行,同时完善文件操作的错误检查。修改后的完整代码如下:
<?php if (isset($_GET['delete_id'])) { $delete_id = $_GET['delete_id']; // 获取要删除页面的slug $statement = $pdo->prepare("SELECT page_slug FROM tbl_page WHERE page_id=?"); $statement->execute([$delete_id]); $page_slug = $statement->fetchColumn(); if (!$page_slug) { $_SESSION['error_message'] = 'Invalid page slug'; header('Location: ' . BASE_URL_ADMIN . 'page'); exit; } $htaccess_path = '../.htaccess'; // 检查文件存在且可写 if (!file_exists($htaccess_path)) { $_SESSION['error_message'] = '.htaccess file not found'; header('Location: ' . BASE_URL_ADMIN . 'page'); exit; } if (!is_writable($htaccess_path)) { $_SESSION['error_message'] = '.htaccess file is not writable'; header('Location: ' . BASE_URL_ADMIN . 'page'); exit; } $htaccess_content = file_get_contents($htaccess_path); if ($htaccess_content === false) { $_SESSION['error_message'] = 'Failed to read .htaccess file'; header('Location: ' . BASE_URL_ADMIN . 'page'); exit; } // 构建灵活的正则匹配规则:允许前后空格、规则内的任意空格,匹配整行 $escaped_slug = preg_quote($page_slug, '/'); $pattern = '/^\s*RewriteRule\s+\^' . $escaped_slug . '\/?\$\s+page\/' . $escaped_slug . '\s+\[NC,L\]\s*$/m'; $new_content = preg_replace($pattern, '', $htaccess_content, 1, $count); if ($count === 0) { $_SESSION['error_message'] = 'Error: Could not find RewriteRule for ' . $page_slug . ' in .htaccess'; } else { // 写回文件,检查写入结果 $write_result = file_put_contents($htaccess_path, $new_content); if ($write_result === false) { $_SESSION['error_message'] = 'Error deleting RewriteRule from .htaccess'; } else { $_SESSION['success_message'] = 'RewriteRule deleted successfully.'; } } // 从数据库删除页面 $statement = $pdo->prepare('DELETE FROM tbl_page WHERE page_id = ?'); $statement->execute([$delete_id]); header('Location: ' . BASE_URL_ADMIN . 'page'); exit; } ?>
代码关键点说明
- 灵活的正则:使用
\s*匹配任意数量的空格(包括0个),配合/m多行模式匹配整行,确保即使规则前后有空格或换行也能准确匹配。 - 完善的错误检查:依次检查文件存在性、可写性、读取状态,提前拦截错误。
- 正确的写入验证:使用
file_put_contents的返回值判断写入是否成功,避免之前逻辑中用读取内容判断写入结果的错误。
内容的提问来源于stack exchange,提问作者Nita Patel
相关产品推荐
相关产品推荐

