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

为何被包含文件无法访问我的PHP数组?

动态向全局菜单数组添加插件菜单条目问题

我正在从零搭建兼具练习和帮朋友开发用途的网站,其中核心需求之一是通过自定义插件和模块动态生成导航菜单。目前config.php中定义了基础配置和初始的$menuItems数组,期望User插件能向该数组追加新的菜单项,但在插件中调用$menuItems时提示变量未定义——已确认config.php被正确包含,但无法访问该数组。

相关代码片段

config.php

<?php
function Deny() {
if(!defined("__directaccess")) {
  header("Location: /");
  exit();
  }
}
//Deny();
$Plugins = array("Bootstrap", "MySQL", "User");
$menuItems = array (
  "Home"  => "/",
);

//Create a root directory base name to reference
define('__root', dirname(__file__));
//Create Class Reference Global Variable
define('__class', __root . '/classes');
//Create Module reference
define('__modules', __root.'/modules');
//Create Plugin reference
define('__plugins', __root.'/plugins');

User.class.php

$menu = array (
  "User Panel"  => "/index.php?page=user",
  "Logout" => "/index.php?page=login&module=logout",
);

print_r($menuItems);

function __isOnline() {
if(isset($_SESSION['username'])) {
  return true;
  } else {
  return false;
  }
}

class UserFunctions extends webConn {
  public function userDetails($arg, $username) {
    $query = <<<SQL
    SELECT * FROM account WHERE username = :username
SQL;
    $resource = $this->db->prepare( $query );
    $resource->execute( array (
      ":username" => $username,
    ));
    $result = $resource->fetch(PDO::FETCH_ASSOC);
    return $result[$arg];
  }
}
$userFunction = new UserFunctions();

index.php

LoadPlugins($Plugins);
LoadModule("TopNav");
LoadPages();

loader.php

session_start();
define("__directaccess", true);

require_once("config.php");
//Loads All Class Functions
function LoadClasses() {
    foreach(glob(__class.'/*.class.php') as $class) {
    if(file_exists($class)) {
        require_once($class);
        }
    }
}

function LoadPlugins($Plugins) {
foreach($Plugins as $Plugin) {
  LoadPlugin($Plugin);
    }
}


function LoadPages() {
if(isset($_GET['page'])) {
        if(file_exists(__root. '/includes/' . $_GET['page'] . '.php')) {
            require_once(__root. '/includes/' . $_GET['page'] . '.php');
    } else {
        echo "Page not Found"; //Make a 404 Error Page
    }
}
if(!isset($_GET['page'])) {
            if(file_exists(__root . '/includes/homepage.php')) {
                require_once(__root . '/includes/homepage.php');
            }
    }
}


function LoadModule($moduleName, $page="index") {
    $path = __modules . '/' . $moduleName . '/' . $page . '.php';
        if(file_exists($path)) {
            require_once($path);
        } else {
            echo "Failed to Load module " . $moduleName;
        }
}

function LoadPlugin($pluginName) {
    $path = __plugins . '/' . $pluginName . '/' . $pluginName . '.class.php';
    if(file_exists($path)) {
        require_once($path);
    } else {
        echo "Failed to load plugin " . $pluginName;
    }
}

问题原因

问题出在变量作用域上:$menuItems是在全局作用域中定义的,但LoadPlugin是一个函数,函数内部有独立的作用域,加载插件文件时,文件内的代码默认在函数作用域中执行,无法直接访问全局的$menuItems变量。

解决方案

方法1:在插件中声明全局变量

在User.class.php开头添加global $menuItems;,然后合并菜单数组:

global $menuItems;
$menu = array (
  "User Panel"  => "/index.php?page=user",
  "Logout" => "/index.php?page=login&module=logout",
);
// 合并到全局菜单数组
$menuItems = array_merge($menuItems, $menu);

方法2:修改加载函数,传递全局变量

修改LoadPlugin函数,先声明全局的$menuItems,确保插件加载时能访问到:

function LoadPlugin($pluginName) {
    global $menuItems;
    $path = __plugins . '/' . $pluginName . '/' . $pluginName . '.class.php';
    if(file_exists($path)) {
        require_once($path);
    } else {
        echo "Failed to load plugin " . $pluginName;
    }
}

方法3:封装菜单管理类(更优雅的方案)

创建一个MenuManager类统一管理菜单,避免全局变量的作用域问题:

在classes/MenuManager.class.php中添加:

class MenuManager {
    private static $menuItems = [];

    // 初始化基础菜单
    public static function init($initialItems) {
        self::$menuItems = $initialItems;
    }

    // 添加菜单项
    public static function addItems($items) {
        self::$menuItems = array_merge(self::$menuItems, $items);
    }

    // 获取所有菜单项
    public static function getItems() {
        return self::$menuItems;
    }
}

在config.php中替换原$menuItems定义,改为初始化菜单管理器:

// 替换原来的$menuItems定义
require_once(__class . '/MenuManager.class.php');
MenuManager::init([
  "Home"  => "/",
]);

在User.class.php中添加菜单:

$menu = array (
  "User Panel"  => "/index.php?page=user",
  "Logout" => "/index.php?page=login&module=logout",
);
MenuManager::addItems($menu);

在TopNav模块中获取菜单用于渲染:

$menuItems = MenuManager::getItems();
// 编写渲染菜单的代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:01:19