2011-04-22 142 views
1

所以我正在练习一些oop的arround并试图做一个基本的oop用户类我试图让我的系统,以便在每一页上我可以只包括config.php和everthing我需要被加载,但由于某些原因,当我尝试登录它抛出我这个错误:序列化/反序列化/ OOP

致命错误:调用一个成员函数的login()一个非对象

的config.php:

<?php 
session_start(); 

// Mysql details 
$username = "torlolol"; 
$password = "torlolol"; 
$hostname = "localhost"; 
$database = "torlolol"; 

// Autoloads classes when needed 
function __autoload($class_name) { 
    include 'Classes/' . $class_name . '.php'; 
} 

$db = new DBConnector($hostname, $username, $password); 

// If there is no user in the session stored make a new one otherwise unserialize it 
if(empty($_SESSION['user'])) 
    $user = new User(); 
else 
    $user = unserialize($_SESSION['user']); 

function onExit() 
{ 
    //When exiting the page serialize the user object and store it in the session 
    $_SESSION['user'] = serialize($user); 
} 

register_shutdown_function("onExit") 
?> 

login.php

<?php 
include "config.php"; 
global $user; 
$user->LogIn(); 
?> 

用户等级:

class User { 
    public $Logged = false; 

    public function LogIn() 
    { 
     $this->Logged = true; 
    } 

    public function LogOut() 
    { 
     $this->Logged = false; 
    } 
} 
?> 

的index.php:

   <?php 
       include "config.php"; 
       global $user; 
       if ($user->Logged != true) 
        echo '<form action="login.php" method="post">Username :<input type="text" name="username" /> Password :<input type="password" name="password" />&nbsp;&nbsp;<input type="submit" value="Login" /></form>'; 
       else  
        echo '<form action="logout.php" method="post"><input style="submit" value="Logout" /></form>'; 

那么,为什么它抛出的错误?为什么它不在索引文件中发生:S ?>

+0

如果你直接在你的index.php中包含用户类是否有效?你的httpd日志文件中有任何错误? – sdolgy 2011-04-22 12:41:38

+0

您是否尝试使用'var_dump($ user);''来查看'$ user'变量中的实际内容?你是否已经检查了在'config.php'中创建'$ user'实例的所有步骤? – zerkms 2011-04-22 12:43:36

+0

调试你的代码,你会看到有什么问题!我的意思是一个调试器! – markus 2011-04-22 12:48:23

回答

3

您必须在开始会话之前包含类文件,否则序列化对象将无法正确加载。不幸的是......

+0

我已经尝试了这两种方法,并将我的自动加载放在会话开始前并结合下面的答案,我还删除了全局变量,但仍然得到同样的错误:( – Quincy 2011-04-22 13:12:32

+0

我认为没有(积极的)把自动载入方法放在session_start()前面的效果,因为这个方法被称为重要的地方...我有问题存储对象的会话,但我没有不使用__autoload,所以我简单地把include'xyz'放在我的session_start()前面 – strauberry 2011-04-22 13:17:50

+0

我也试着做一架飞机,包括相同的结果 – Quincy 2011-04-22 13:27:04

1

通过删除,

global $user; 

因为当你被包括文件,$用户会自动在文件中包含。

2

如果您反序列化一个对象,哪个类尚未声明,它将被反序列化为__PHP_Incomplete_Class,这显然没有LogIn方法。所以,你要么需要手动包括文件,或者注册一个unserialize_callback_func:在config.php文件

ini_set('unserialize_callback_func', '__autoload'); 
0

您注册与用户的一个实例设置$ _SESSION [“用户”]关机功能($用户变量)...但由于你管理instancied类的方式(通过使用全局变量),你需要在onExit函数中重新声明global $user;

function onExit() 
{ 
    //When exiting the page serialize the user object and store it in the session 
    global $user; 
    $_SESSION['user'] = serialize($user); 
} 

我个人推荐拥有一个主要的全局类来处理整个应用程序中需要的类的实例。

编辑:看我的答案here

+0

这是依赖注入的地方。有一个独立的应用程序抓包 - 代码实际上并不是一个好的方法,它很容易实现,当然,但更难以维护,并且很难编写测试代码,而是将其分解成片段和inje将这些片段放入需要使用它们的对象中。 – 2011-04-22 14:03:36

+0

@ kevinmajor1好点!你会推荐Symfony依赖注入容器吗?我在C#中多次使用Spring.net,看起来它的用法很相似。 – 2011-04-26 08:18:36

+0

我对Ninject最为熟悉,但实际上,任何有信誉的DI容器都应该这样做。这在很大程度上是一个舒适的问题。 – 2011-04-26 12:18:33

0

这里有一个类,它允许跟踪全局变量的变化:

abstract class CSTReportDelegate { 

    abstract public function emitVariableChange($variableName, $oldValue, $newValue); 
    abstract public function emitVariableSetNew($variableName, $newValue); 

} 

class CSTSimpleReportDelegate extends CSTReportDelegate { 

    public function emitVariableChange($variableName, $oldValue, $newValue) { 
     echo '<br />[global/change] '. $variableName . ' : ' . print_r($oldValue, true) . ' &rarr; ' . print_r($newValue, true); 
    } 

    public function emitVariableSetNew($variableName, $newValue) { 
     echo '<br />[global/init] '. $variableName . ' &rarr; ' . print_r($newValue, TRUE); 
    } 

} 


class CSysTracer { 

    static protected 
     $reportDelegate; 

    static private 
     $globalState = array(); 

    static private 
     $traceableGlobals = array(); 

    static private 
     $globalTraceEnabled = FALSE; 

    static public 
    function setReportDelegate(CSTReportDelegate $aDelegate) { 
     self::$reportDelegate = $aDelegate; 
    } 


    static public 
    function start() { 

     register_tick_function (array('CSysTracer', 'handleTick')); 

    } 


    static public 
    function stop() { 

     unregister_tick_function(array('CSysTracer', 'handleTick')); 

    } 

    static public 
    function evalAndTrace($someStatement) { 

     declare(ticks = 1); { 
      self::start(); 
      eval($someStatement); 
      self::stop(); 
     } 
    } 

    static public 
    function addTraceableGlobal($varName) { 

     if (is_array($varName)) { 
      foreach($varName as $singleName) { 
       self::addTraceableGlobal($singleName); 
      } 
      return; 
     } 

     self::$traceableGlobals[ $varName ] = $varName; 

    } 

    static public 
    function removeTraceableGlobal($varName) { 
     unset(self::$traceableGlobals[ $varName ]); 
    } 

    /** 
    * Main function called at each tick. Calls those functions, which 
    * really perform the checks. 
    * 
    */ 
    static public 
    function handleTick() { 

     if (TRUE === self::$globalTraceEnabled) { 
      self::traceGlobalVariable(); 
     } 

    } 

    static public 
    function enableGlobalsTrace() { 
     self::$globalTraceEnabled = TRUE; 
    } 


    static public 
    function disableGlobalsTrace() { 
     self::$globalTraceEnabled = FALSE; 
    } 

    static public 
    function traceGlobalVariable() { 

     foreach(self::$traceableGlobals as $aVarname) { 

      if (! isset($GLOBALS[ $aVarname ])) { 
       continue; 
      } 

      if (! isset(self::$globalState[ $aVarname ])) { 

       self::$reportDelegate->emitVariableSetNew($aVarname, $GLOBALS[ $aVarname ]); 
       self::$globalState[ $aVarname ] = $GLOBALS[ $aVarname ]; 
       continue; 
      } 

      if (self::$globalState[ $aVarname ] !== $GLOBALS[ $aVarname ]) { 

      self::$reportDelegate->emitVariableChange($aVarname, self::$globalState[ $aVarname ], $GLOBALS[ $aVarname ]); 

      } 

      self::$globalState[ $aVarname ] = $GLOBALS[ $aVarname ]; 

     } 

    } 

} 

使用方法如下:

CSysTracer::addTraceableGlobal(array('foo', 'bar')); 

CSysTracer::setReportDelegate(new CSTSimpleReportDelegate()); 
CSysTracer::enableGlobalsTrace(); 

CSysTracer::start(); 
declare(ticks = 1); 

    $foo = 10; 
    echo "<br>First output"; 
    $foo *= $foo; 
    $foo = 'bar'; 
     echo "<br>Next output"; 
    $otherFoo = array (1,2,3); 
    $bar = 23; 
    echo "<br>Finished!"; 

CSysTracer::stop(); 

Whill输出

[global/init] foo → 10 
Hi! 
[global/change] foo : 10 → 100 
[global/change] foo : 100 → bar 
Gotta run 
[global/change] foo : bar → Array ([0] => 1 [1] => 2 [2] => 3) 
[global/init] bar → 23 
Bye! 

尽管此版本CSysTracer跟踪全局变化,您可以创建变体traceGlobalVariable()来跟踪会话变量或变化的变化方法通话。