【发布时间】:2021-06-26 13:27:26
【问题描述】:
我一直在阅读一本书,它通过使用 PHP 和 MySQL 的用户控制应用程序来解释 MVC。据我所知,我的问题是我的 MVC 路由在我使用 localhost 时运行良好,但是当我将相同的代码应用到我的提供程序服务器上的相同结构根目录时 - 它加载索引页面,但随后控制器只是为其他所有内容抛出 404。我的登录表单也没有通过控制器/方法,因此可以通过 $_POST 检索它。这一切都在本地完美运行,只是似乎落在了网络服务器上。 Composer 设置正确,我的 PHP 版本在本地和 Web 服务器上是 7.4。我已经用尽了互联网上的材料,真的只是碰了壁。我会将所有相关代码sn-ps放在下面,任何帮助将不胜感激!
index.php (localhost > webroot)
<?php
//define a directory separator e.g. / or \ depending on the machine
defined('DS') || define('DS', DIRECTORY_SEPARATOR);
define('APPDIR', realpath(__DIR__.'/../app/') .DS);
define('SYSTEMDIR', realpath(__DIR__.'/../system/') .DS);
define('PUBLICDIR', realpath(__DIR__) .DS);
define('ROOTDIR', realpath(__DIR__.'/../') .DS);
//initiate config
$config = App\Config::get();
new System\Route($config);
Config.php(本地主机>应用程序)
<?php
namespace App;
use App\Helpers\Session;
class Config {
public static function get() {
//turn on output buffering
ob_start();
//turn on sessions
Session::init();
return [
//set the namespace for routing
'namespace' => 'App\Controllers\\',
//set the default controller
//set to Home for Default view
'default_controller' => 'admin',
//set default method
'default_method' => 'index',
//database credentials
'db_type' => 'mysql',
'db_host' => 'localhost',
'db_name' => '***',
'db_username' => '***',
'db_password' => '***',
];
}
}
Route.php(本地主机>系统)
<?php
namespace System;
use System\View;
class Route {
//construct method expects parameter called $config
public function __construct($config) {
//hold an array from the requested route (in the form of /page/requested)
//when explode is run it finds forward slash in the requested URI (made available by $_SERVER)
$url = explode('/', trim($_SERVER['REQUEST_URI'], '/'));
//controller uses a ternary operator to check if 0 index of $url exists
//otherwise default_controller will be used (defined in the config class)
$controller = !empty($url[0]) ? $url[0] : $config['default_controller'];// Home/Admin
//method checks for the existence of a $url[1] - or again defaults from config class
$method = !empty($url[1]) ? $url[1] : $config['default_method'];
$args = !empty($url[2]) ? array_slice($url, 2) : array();
$class = $config['namespace'].$controller;
//check it the class exists
if (! class_exists($class)) {
return $this->not_found();
}
//check if the method exists
if (! method_exists($class, $method)) {
return $this->not_found();
}
//create an instance of the controller
$classInstance = new $class;
call_user_func_array(array($classInstance, $method), $args);
}
//if the class or method is not found - return a 404
public function not_found() {
$view = new View();
return $view->render('404');
}
}
Admin.php(本地主机>应用程序>控制器)
<?php
namespace App\Controllers;
use System\BaseController;
use App\Helpers\Session;
use App\Helpers\Url;
use App\Models\User;
class Admin extends BaseController {
//set class local variable
protected $user;
//initialise the User Model by calling new User();
public function __construct() {
parent::__construct();
$this->user = new User();
}
//check if logged in
public function index() {
//if they are not logged in, redirect to the login method
//'logged_in' comes from Session::set method
if (! Session::get('logged_in')) {
Url::redirect('/admin/login');
}
//will set the title for the browser window
$title = 'Dashboard';
$this->view->render('admin/auth/login', compact('title'));
}
public function login () {
//check if theres a session in play
if (Session::get('logged_in')) {
Url::redirect('/admin');
}
//create empty errors array
$errors = [];
//check if form has been submitted by checking if $_POST array contains an object called submit
//$_POST comes from the admin>auth>login.php form
if (isset($_POST['submit'])) {
echo "Submitted";
exit();
//htmlspec - security measure, stops script tags from being able to be executed(renders as plaintext)
$username = htmlspecialchars($_POST['username']);
$password = htmlspecialchars($_POST['password']);
//call built in function password_verify
if (password_verify($password, $this->user->get_hash($username)) == false) {
$errors[] = "Wrong username or password";
}
//count the errors, if theres none you can get the data and set the session using Session Helper
if (count($errors) == 0) {
//logged in
$data = $this->user->get_data($username);
Session::set('logged_in', true);
Session::set('user_id', $data->id);
//redirect the user to the admin index page
Url::redirect("/admin");
}
}
//set the title
$title = 'Login';
$this->view->render('admin/auth/login', compact('title', 'errors'));
}
login.php(本地主机 > 应用程序 > 视图 > 管理员 > 身份验证)
<?php
//include header
include(APPDIR.'views/layouts/header.php');
use App\Controllers\Admin;
?>
<div class="wrapper well">
<!--wrapper class will be used to position the DIV-->
<!--include errors to catch any errors or messages -->
<?php include(APPDIR.'views/layouts/errors.php');?>
<!--form will have a POST method to send contents to an ACTION URL -->
<!-- Admin is the class, and login is the method to be called in System\Route-->
<form action="/admin/login" method="post">
<h1>Login</h1>
<!--User Input -->
<div class="control-group">
<label class="control-label" for="username"> Username</label>
<input class="form-control" id="username" type="text" name="username" />
</div>
<!--Password Input -->
<div class="control-group">
<label class="control-label" for="password"> Password</label>
<input class="form-control" id="password" type="text" name="password" />
</div>
<br>
<!-- Submit button -->
<p class="pull-left"><button type="submit" class="btn btn-sm btn-success" name="submit" value="submit">Login</button></p>
<!-- Reset option-->
<p class="pull-right"><a href="/admin/reset">Forgot Password</a></p>
<!-- clear floats -->
<div class="clearfix"></div>
</form>
</div>
<!-- footer include -->
<?php include(APPDIR.'views/layouts/footer.php');?>
.htaccess(位于 index.php 中)
# Disable directory snooping
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Uncomment the rule below to force HTTPS (SSL)
RewriteCond %{HTTPS} !on
#RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Force to exclude the trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.*)/$
RewriteRule ^(.+)/$ $1 [R=307,L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [QSA,L]
ErrorDocument 404 /errors/not-found.html
</IfModule>
【问题讨论】:
标签: php model-view-controller http-status-code-404