Php 了解vars的类和范围

Php 了解vars的类和范围,php,class,autoloader,Php,Class,Autoloader,我正在重写我的许多旧代码,目前正试图掌握类、函数,并围绕MVC模型松散地重建我的站点 然而,我无法获取标题模板include,以引用由主配置文件自动加载的用户帐户详细信息,我认为我错过了一个非常重要的步骤 错误消息是致命错误:对成员函数的调用是非对象上的\u loggedin()。,因此我猜在template.class.php中执行的include无法访问account.class.php函数 更新:在header.tpl.php中形成var\u转储(get\u included\u file

我正在重写我的许多旧代码,目前正试图掌握类、函数,并围绕MVC模型松散地重建我的站点

然而,我无法获取标题模板include,以引用由主配置文件自动加载的用户帐户详细信息,我认为我错过了一个非常重要的步骤

错误消息是
致命错误:对成员函数的调用是非对象上的\u loggedin()。
,因此我猜在template.class.php中执行的include无法访问account.class.php函数

更新:在header.tpl.php中形成
var\u转储(get\u included\u files())
表明account.class.php和template.class.php都被包含(按顺序)。我还尝试手动将account.class.php包含在header.tpl.php的顶部,以查看它是否会产生任何影响……但没有。帮助:(

我还应该注意,我可以在index.php中调用
$\u account->is\u loggedin()
,而不必在附带的文件header.inc.php中调用.Jst

很可能我会把这一切都搞错了,所以下面是我的代码的简写,如果有人能提供一些指导的话:

index.php

<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $_template->load('header'); ?>
....
</body>
session_start();

// define path settings
// connect to database, memcache
// lots of other stuff....

//autoloader for functions
spl_autoload_register(function ($class) {
  if (file_exists(CLASS_PATH.DS.$class.'.class.php'))
  {
    include CLASS_PATH.DS.$class.'.class.php';
  }
});

$_account = new account();  // autoload user account stuff
$_template = new template(); // autoload templates
class account
{
  private $db;

  public function __construct($db) {
    $this->db = $db;
  }


  public function is_loggedin() {
    // do various session checks
  }
}
class template
{
  public function load($template)
  {
    if (file_exists(TPL_PATH.DS.$template.'.tpl.php'))
    {
      include TPL_PATH.DS.$template.'.tpl.php';
    }
  }
}
<div id="header">
<?php if($_account->is_loggedin() == true): ?>
  <p>logged in</p>
<?php else: ?>
  <p>not logged in</p>
<?php endif; ?>
<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $headerTemplate->printContent(); ?>
<?php $bodyTemplate->printContent(); ?>
</body>
account.class.php

<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $_template->load('header'); ?>
....
</body>
session_start();

// define path settings
// connect to database, memcache
// lots of other stuff....

//autoloader for functions
spl_autoload_register(function ($class) {
  if (file_exists(CLASS_PATH.DS.$class.'.class.php'))
  {
    include CLASS_PATH.DS.$class.'.class.php';
  }
});

$_account = new account();  // autoload user account stuff
$_template = new template(); // autoload templates
class account
{
  private $db;

  public function __construct($db) {
    $this->db = $db;
  }


  public function is_loggedin() {
    // do various session checks
  }
}
class template
{
  public function load($template)
  {
    if (file_exists(TPL_PATH.DS.$template.'.tpl.php'))
    {
      include TPL_PATH.DS.$template.'.tpl.php';
    }
  }
}
<div id="header">
<?php if($_account->is_loggedin() == true): ?>
  <p>logged in</p>
<?php else: ?>
  <p>not logged in</p>
<?php endif; ?>
<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $headerTemplate->printContent(); ?>
<?php $bodyTemplate->printContent(); ?>
</body>
template.class.php

<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $_template->load('header'); ?>
....
</body>
session_start();

// define path settings
// connect to database, memcache
// lots of other stuff....

//autoloader for functions
spl_autoload_register(function ($class) {
  if (file_exists(CLASS_PATH.DS.$class.'.class.php'))
  {
    include CLASS_PATH.DS.$class.'.class.php';
  }
});

$_account = new account();  // autoload user account stuff
$_template = new template(); // autoload templates
class account
{
  private $db;

  public function __construct($db) {
    $this->db = $db;
  }


  public function is_loggedin() {
    // do various session checks
  }
}
class template
{
  public function load($template)
  {
    if (file_exists(TPL_PATH.DS.$template.'.tpl.php'))
    {
      include TPL_PATH.DS.$template.'.tpl.php';
    }
  }
}
<div id="header">
<?php if($_account->is_loggedin() == true): ?>
  <p>logged in</p>
<?php else: ?>
  <p>not logged in</p>
<?php endif; ?>
<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $headerTemplate->printContent(); ?>
<?php $bodyTemplate->printContent(); ?>
</body>
header.tpl.php

<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $_template->load('header'); ?>
....
</body>
session_start();

// define path settings
// connect to database, memcache
// lots of other stuff....

//autoloader for functions
spl_autoload_register(function ($class) {
  if (file_exists(CLASS_PATH.DS.$class.'.class.php'))
  {
    include CLASS_PATH.DS.$class.'.class.php';
  }
});

$_account = new account();  // autoload user account stuff
$_template = new template(); // autoload templates
class account
{
  private $db;

  public function __construct($db) {
    $this->db = $db;
  }


  public function is_loggedin() {
    // do various session checks
  }
}
class template
{
  public function load($template)
  {
    if (file_exists(TPL_PATH.DS.$template.'.tpl.php'))
    {
      include TPL_PATH.DS.$template.'.tpl.php';
    }
  }
}
<div id="header">
<?php if($_account->is_loggedin() == true): ?>
  <p>logged in</p>
<?php else: ?>
  <p>not logged in</p>
<?php endif; ?>
<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $headerTemplate->printContent(); ?>
<?php $bodyTemplate->printContent(); ?>
</body>

登录

未登录


您试图访问的
$\u帐户
模板::加载
方法的函数范围内的一个变量,您初始化的
$\u帐户
是一个全局变量

如果要使用全局变量,应在函数中使用
global$\u account
声明它,或使用
$GLOBALS[''u account']

一个简单的模板示例(其余部分从源代码复制):

Template.class.php

interface IApiHandler {
    public function printContent();
}
class SomeTemplate implements Template {
    public function printContent() {
        $account = Account::getCurrent();
        ?>
        <div id="header">
        <?php if($account->is_loggedin() == true): ?>
            <p>logged in</p>
        <?php else: ?>
            <p>not logged in</p>
        <?php endif;
    }
}
class Account {
    private static $current = null;
    public static function getCurrent() {
        if(self::$current === null) {
            self::$current = new Account();
        }
        return self::$current;
    }
    public function __construct() {
        //account init...
    }
    public function isLoggedIn() {
        return rand()%2;
    }
}
session_start();

// define path settings
// connect to database, memcache
// lots of other stuff....

//autoloader for functions
spl_autoload_register(function ($class) {
  if (file_exists(CLASS_PATH.DS.$class.'.class.php'))
  {
    include CLASS_PATH.DS.$class.'.class.php';
  }
});

$headerTemplate = new HeaderTemplate();//not included in the example...
$bodyTemplate = new SomeTemplate();
SomeTemplate.class.php

interface IApiHandler {
    public function printContent();
}
class SomeTemplate implements Template {
    public function printContent() {
        $account = Account::getCurrent();
        ?>
        <div id="header">
        <?php if($account->is_loggedin() == true): ?>
            <p>logged in</p>
        <?php else: ?>
            <p>not logged in</p>
        <?php endif;
    }
}
class Account {
    private static $current = null;
    public static function getCurrent() {
        if(self::$current === null) {
            self::$current = new Account();
        }
        return self::$current;
    }
    public function __construct() {
        //account init...
    }
    public function isLoggedIn() {
        return rand()%2;
    }
}
session_start();

// define path settings
// connect to database, memcache
// lots of other stuff....

//autoloader for functions
spl_autoload_register(function ($class) {
  if (file_exists(CLASS_PATH.DS.$class.'.class.php'))
  {
    include CLASS_PATH.DS.$class.'.class.php';
  }
});

$headerTemplate = new HeaderTemplate();//not included in the example...
$bodyTemplate = new SomeTemplate();
defaults.php

interface IApiHandler {
    public function printContent();
}
class SomeTemplate implements Template {
    public function printContent() {
        $account = Account::getCurrent();
        ?>
        <div id="header">
        <?php if($account->is_loggedin() == true): ?>
            <p>logged in</p>
        <?php else: ?>
            <p>not logged in</p>
        <?php endif;
    }
}
class Account {
    private static $current = null;
    public static function getCurrent() {
        if(self::$current === null) {
            self::$current = new Account();
        }
        return self::$current;
    }
    public function __construct() {
        //account init...
    }
    public function isLoggedIn() {
        return rand()%2;
    }
}
session_start();

// define path settings
// connect to database, memcache
// lots of other stuff....

//autoloader for functions
spl_autoload_register(function ($class) {
  if (file_exists(CLASS_PATH.DS.$class.'.class.php'))
  {
    include CLASS_PATH.DS.$class.'.class.php';
  }
});

$headerTemplate = new HeaderTemplate();//not included in the example...
$bodyTemplate = new SomeTemplate();
index.php

<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $_template->load('header'); ?>
....
</body>
session_start();

// define path settings
// connect to database, memcache
// lots of other stuff....

//autoloader for functions
spl_autoload_register(function ($class) {
  if (file_exists(CLASS_PATH.DS.$class.'.class.php'))
  {
    include CLASS_PATH.DS.$class.'.class.php';
  }
});

$_account = new account();  // autoload user account stuff
$_template = new template(); // autoload templates
class account
{
  private $db;

  public function __construct($db) {
    $this->db = $db;
  }


  public function is_loggedin() {
    // do various session checks
  }
}
class template
{
  public function load($template)
  {
    if (file_exists(TPL_PATH.DS.$template.'.tpl.php'))
    {
      include TPL_PATH.DS.$template.'.tpl.php';
    }
  }
}
<div id="header">
<?php if($_account->is_loggedin() == true): ?>
  <p>logged in</p>
<?php else: ?>
  <p>not logged in</p>
<?php endif; ?>
<php require 'defaults.php'; ?>
<html>
<head>
...
</head>
<body>
<?php $headerTemplate->printContent(); ?>
<?php $bodyTemplate->printContent(); ?>
</body>

...
还应该注意的是,MVC中缺少C,这只是一个如何将模板作为类的示例

通常索引(或者在本例中是default.php)只需要决定哪个控制器应该处理请求。然后控制器必须决定(或者默认为)应该使用哪个模板(如果有的话)


另外,如果所有html都包含在模板中,则最好在控制器处理请求之前不打印输出。

在使用该类之前,执行
var\u转储(get\u included\u files())
查看是否包含类文件。您描述的错误通常来自不存在的类。要么自动加载程序注册失败,要么类文件中包含的某个地方存在错误。请逐步调试,您应该离解决问题更近一步。您的应用程序模型可以得到改进和改进你的代码风格有点像旧式的PHP4,但对于一个新来的类、模式和模型来说,这是一个很好的开始。作为提示,我将通过类似
else{throw new Exception(“include file not found”);}的方式扩展template.class.php中的
if
子句
-查看文件是否真的包含在内。是的,不幸的是,我很老派,但试图打破习惯。我在defaults.php中的autolaer和template.class.php中都添加了例外,但没有发现任何错误。模板肯定包含在内,因为当我访问索引时,我看到了hea的内容der模板…但除此之外,我不确定我是否会从抛出错误的行之前的
var_dump
ing
$\u account
开始,这样你就可以确切地看到它认为变量是什么。是否使用全局“hack”来绕过我在模型中引入的问题?如果是,有没有更好的方法来绕过这个问题?是的一般来说,与全局变量一样,这是一种黑客行为。最好使用静态类变量而不是全局变量,它们仍然是全局变量,但至少是按类组织的,IDE可以更好地处理它们。如果你想完全避免全局变量,你必须将其作为参数到处传递(哪种选择更好是一个有着自己宗教辩论的完整话题)。只需对此进行一点扩展:当您使用
include
require
时,就像您在
模板::load
中所做的那样,它直接将文件包含在适当的位置,这种情况意味着它是
load
函数体的一部分。这可能不是您真正想要的,而且它可能会在其他方面咬到您(类似)方法。例如,如果在包含的文件中定义类的任何函数,它们也不会在函数之外有作用域。但我不确定解决方案是什么,即如何包含变量文件。不过,这似乎应该是常见的。解决这一困惑的简单方法是定义模板s作为类(具有通用基类或接口)并通过自动加载器将其包括在内。这样会减少范围混淆,您的IDE也将能够正确确定变量范围。感谢所有的帮助。我想我了解您所说的要点,但我不能完全理解。如果您有机会,我真的很欣赏一个例子。