Autor Zpráva
tipin
Profil *
Ahoj. Učím se programovat objektově (-> moc tomu ještě nerozumím). Zkusil jsem si vytvořit login uživatelů (viz dole). Při pokusu zjistit atribut objektu User (př. $uzivatel->getName()) mi stránka vypíše:
Fatal error: main() [<a href='function.main'>function.main</a>]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition &quot;User&quot; of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in C:\dev\www\pokus\test.php on line 14

Moje první otázka je proč můj kúd nefunguje. Druhá otázka, má toto řešení přihlašování alespoň trochu hlavu a patu, nebo jsem úplně mimo. (Popřípadně, jak byste to řešili vy.) Dějkuji za odpověď.

<?php
class Login {
  
  private static function getConnection() { 
    static $db;
    
    // připojení je už vytvořeno  
    if(isset($db)) {    
        return $db;      
    }
    
    // připojení zatím nebylo vytvořeno  
    require_once ('db_info.php');
        
    $db = mysql_connect(HOST, USER, PASSWORD) 
            or die("Připojování k DB selhalo.");    
    mysql_select_db(DB_NAME, $db) or die("Vybírání DB selhalo.");
    mysql_query('SET CHARACTER SET utf8') or die(mysql_error($db));
        
    return $db;
  }
  
  public static function logUserIn($email, $password) {
    $sql = 'SELECT * FROM user WHERE 
              email = "'. $email. '" AND 
              password = PASSWORD("'. $password. '")';
    $res = mysql_query($sql, self::getConnection()) 
              or die(mysql_error(self::getConnection()));
              
    if(mysql_num_rows($res)) {
        $user = new User(mysql_fetch_assoc($res));
        
        session_start();
        $_SESSION['user'] = $user;
    }
  }
  
  public static function logUserOut() {
    session_start();
    session_unset();
    session_destroy();
  }
}

class User {
  
  private $id;
  private $first_name;
  private $last_name;
  private $email;
  private $access_lvl;

  function __construct($row) {   
    $this->id = $row["id"];
    $this->first_name = $row["first_name"];
    $this->last_name = $row["last_name"];
    $this->email = $row["email"];
    $this->access_lvl = $row["access_lvl"];
  }
  
  public function getName() {
    return $this->first_name;
  }

}
?>
Alphard
Profil
Proč to nefunguje s jistotou nevím, tuhle chybu vidím poprvé. Asi nejlepší vysvětlení, které jsem našel, sice napovídá mnohé, ale radši napište, který řádek je u vás 14.

A k tomu kódu:
1. O získání připojení k databázi se nemůže starat třída Login. Nemá s tím nic společného.
2. V OOP radši než die() házejte výjimky.
3. session_start() (s ním zřejmě souvisí nefunkčnost) není dobré volat takto. Už teď je ve dvou metodách, za chvíli byste se v tom ztratil.
4. Neošetřujete vstupy proti sql injection (nesouvisí s OOP, ale když už se učíte něco nového)
Asi by šly najít další drobnosti, ale časem je uvidíte sám.
tipin
Profil *
Zbytek kódu vypadá takto:

transactUser.php:
<?php
require_once('user.php');

$action = $_GET['action'];

switch($action) {
  
  case 'login':
    Login::logUserIn("mail@test.cz", "heslo");
    header('Location: test.php');
    break;
    
  case 'logout':
    Login::logUserOut();
    header('Location: test.php');
    break;
}
?>


test.php:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01">
<html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>pokus</title>
  </head>
  <body>
<?php 
session_start();
   
if(isset($_SESSION['user'])) {
    $user = $_SESSION['user'];
    echo "<a href=\"transactUser.php?action=logout\">Odhlásit uživatele</a> ". 
              $user->getName();   
} else {
    echo "<a href=\"transactUser.php?action=login\">Přihlásit</a>";
}

?>
  </body>
</html>


Jinak děkuji za koment. Mám jen ještě pár otázek:
1. Takže to připojení k DB mám řešit přes další třídu?
2. OK
3. Jak mám tedy volat session_start()?
4. OK
tiso
Profil
tipin: riadok 12:
$user = $_SESSION['user'];
zmeň na:
$user = new User($_SESSION['user']);
tipin
Profil *
tiso:
Ahoj. Tomu teď moc nerozumím. To mám vytvořit nový oběkt z objetu v session? Ani mi to moc nefunguje - konstruktor User vyžaduje přece jiné parametry, a nebo jsem zase vedle?
tiso
Profil
tipin: tak inak: nemôžeš volať nestatickú metódu triedy ($user->getName();) bez toho, aby si mal vytvorený objekt ($user = new User($params);). Takže si ho musíš vytvoriť… Neviem čo máš v $_SESSION['user'], predpokladal som, že tam máš obsah riadku z tabuľky user z DB.
tipin
Profil *
tiso:
v $_SESSION['user'] mám právě vytvořenou instanci třídy User... nebo je to hloupost a do session objekty nepatří? (jak jsem psal výše jsem ještě začátečník a ve spoustě věcí nemám jasno)
AM_
Profil
tipin:
nebo je to hloupost a do session objekty nepatří?
Asi ti úplně přesně neumím říct proč, ale do session bych raději ukládal jen ID uživatele a objekt při každém načtení stránky znovu vytvořil - je to takové pružnější a elegantnější.
tiso
Profil
tipin: „v $_SESSION['user'] mám právě vytvořenou instanci třídy User
Si si istý? Čo ti vypíše var_dump($_SESSION['user']);
tipin
Profil *
tiso:
object(__PHP_Incomplete_Class)#1 (6) { ["__PHP_Incomplete_Class_Name"]=> string(4) "User" ["id:private"]=> string(1) "1" ["first_name:private"]=> string(5) "jmeno" ["last_name:private"]=> string(8) "prijmeni" ["email:private"]=> string(12) "mail@test.cz" ["access_lvl:private"]=> string(1) "2" }
tiso
Profil
tipin: a sme doma: http://www.google.com/search?hl=all&q=__PHP_Incomplete_Class&btnG=Google+Search
tipin
Profil *
tiso:
Aha, díky. Už tomu začínám rozumnět. Takže jak to přihlašování dělám já, tak to asi nepůjde, že? Jestli je uživatel přihlášený ověřuji pomocí
if(isset($_SESSION['user']))
, tudíž si volám session_star() ještě před vytvořením objektu User... Správně?

Jinak bude asi nejlepší, když si zagooglím a podívám se jak to řeší jiní. Chtěl jsem něco vymyslet sám, ale jdu na to zřejmě špatně.
Nox
Profil
session_start() můžeš a nejspíš máš volat předtím... prostě uchováváš jen ID v session a to pak třeba dáš konstruktoru uživatele a podle něj se vytvoří

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0