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

PHP报错:非对象上下文使用$this问题求助

问题分析与解决方案

首先,你遇到的Uncaught Error: Using $this when not in object context报错,核心原因是在静态方法里调用了依赖对象上下文的实例方法,再加上你的类设计有几个关键问题,导致代码无法正常运行。下面是具体的修复步骤和优化建议:

1. 核心报错原因:静态方法与实例方法的冲突

你的User类里的getUsers()、getOneLevel()等都是静态方法,里面用self::all()、self::query()调用Model类的实例方法。但实例方法(比如all())依赖$this->table、$this->con这些对象属性,静态上下文没有对象实例,自然会报错。

解决思路:把User的静态方法改为实例方法,通过实例化User来调用方法;或者重构Model的方法为静态,但前者更符合面向对象的设计。


2. 逐个修复你的类

修复Connect类(数据库连接)

原来的Connect类只是创建了连接,但没有把连接对象保存下来,导致Model无法拿到真正的mysqli连接。同时修正错误的错误函数名:

<?php
namespace Core;

class Connect {
    private const DB_NAME = "vp_test";
    private const DB_USER = "root";
    private const DB_PASSWORD = "";
    private const DB_HOST = "localhost";
    
    public $connection; // 保存mysqli连接对象
    
    public function __construct() {
        $this->connection = mysqli_connect(self::DB_HOST, self::DB_USER, self::DB_PASSWORD, self::DB_NAME);
        
        if (!$this->connection) {
            die("Connection error: " . mysqli_connect_error()); // 修正为mysqli的错误函数
        }
    }
}

修复Model类(基础模型)

修正连接获取方式,用$this调用实例方法,同时优化execute方法的返回值(原来只返回一行数据,无法处理多条结果):

<?php
namespace Core;

use Core\Connect;

class Model {
    protected $con; // 改为protected,让子类可以访问
    public $table;

    public function __construct() {
        $connectInstance = new Connect;
        $this->con = $connectInstance->connection; // 获取真正的mysqli连接
    }

    public function all(){
        $sql = "SELECT * FROM {$this->table}";
        return $this->execute($sql); // 用$this调用实例方法,而非self
    }

    public function query($select, $where = false){
        $sql = "SELECT {$select} FROM {$this->table}";
        if ($where) {
            $sql .= " {$where}";
        }
        return $this->execute($sql);
    }

    public function find($id){
        return $this->query("*", "WHERE id = {$id}");
    }

    protected function execute($sql){ // 改为protected,允许子类访问
        $query = mysqli_query($this->con, $sql);
        if (!$query) {
            die("SQL Error: " . mysqli_error($this->con)); // 增加SQL错误提示
        }
        // 根据结果行数返回对应格式:多条返回数组,单条返回关联数组
        return mysqli_num_rows($query) > 1 
            ? mysqli_fetch_all($query, MYSQLI_ASSOC) 
            : mysqli_fetch_assoc($query);
    }
}

修复User类(业务模型)

去掉冗余的Model实例化,调用父类构造函数,将静态方法改为实例方法,补充缺失的return语句,同时修正SQL中的引号问题:

<?php
namespace App;

use Core\Model;

class User extends Model {
    public function __construct() {
        parent::__construct(); // 必须调用父类构造,初始化数据库连接
        $this->table = "users"; // 直接设置父类的public属性,无需额外实例化Model
    }

    public function getUsers(){
        return $this->all(); // 用$this调用父类的实例方法
    }

    public function getOneLevel($level){
        return $this->query("*", "WHERE level = {$level}");
    }

    public function getLevel($id){
        return $this->query("level", "WHERE id = {$id}"); // 补充return
    }

    public function getParent($id){
        $child = $this->find($id);
        // 注意:这里要给字符串加单引号,避免SQL语法错误
        $parentId = $this->query("id", "WHERE username = '{$child["sponsor_username"]}'");
        return $this->find($parentId['id']); // 补充return,取到父ID后查询父信息
    }

    public function getChildren($id){
        $parent = $this->find($id);
        return $this->query("*", "WHERE sponsor_username = '{$parent["username"]}'"); // 补充return
    }
}

3. 正确使用方式

现在你可以通过实例化User类来调用方法,避免静态上下文的问题:

// 示例代码
$userModel = new App\User();

// 获取所有用户
$allUsers = $userModel->getUsers();

// 获取指定等级的用户
$level1Users = $userModel->getOneLevel(1);

// 获取某个用户的上级
$parentUser = $userModel->getParent(1);

额外建议:避免SQL注入

当前代码直接把变量拼接到SQL中,存在严重的SQL注入风险。建议使用mysqli预处理语句,比如把find方法改为:

public function find($id){
    $sql = "SELECT * FROM {$this->table} WHERE id = ?";
    $stmt = mysqli_prepare($this->con, $sql);
    mysqli_stmt_bind_param($stmt, "i", $id); // "i"表示整数类型
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);
    return mysqli_fetch_assoc($result);
}

内容的提问来源于stack exchange,提问作者M'Baku

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:13:37