ďťż

[PHP] Łączenie obiektów

       

Podstrony


telcocafe

Rozwiązanie to pewnie banał, ale nie mogę na nie wpaść. Przykład:class jeden { public $_var; public function tworz() { $this->_b = new dwa; } } class dwa { public function wyswietl() { echo $this->_var; } } $a = new jeden; $a->tworz(); $a->_b->_var = &$a->_var; // tutaj jest przepisanie, ale gdy jest wiele zmiennych?... $a->_b->wyswietl();Chcę, by metoda $a->_b->wyswietl() widziała zmienne i funkcje obiektu $a. Jak to prościej zrobić? Bo przepisywanie nie jest zbyt wygodne.
Użytkownik andrzej_aa edytował ten post 12 lipiec 2008, 21:57


Nie do końca rozumiem, ale...

class jeden { public function wyswietl() { echo('metoda klasy jeden'); } } class dwa { public function wyswietl($jeden) { $jeden->wyswietl(); } } $a = new jeden(); $b = new dwa(); $b->wyswietl($a);
Użytkownik Kozack edytował ten post 12 lipiec 2008, 22:27
<?php class jeden { public $_var = array('wha', 'te', 'ver'); public $_b; public function __construct() { echo '==> '.__method__."\n"; } public function tworz() { echo '==> '.__method__."\n"; $this->_b = new dwa(); } } class dwa extends jeden { public function __construct() { echo '==> '.__method__."\n"; } public function wyswietl() { echo '==> '.__method__."\n"; return $this->_var; } } $a = new jeden(); $a->tworz(); print_r($a->_b->wyswietl());

Tylko że to failcode, ja bym został przy:
class jeden { public $_var = array('wha', 'te', 'ver'); } class dwa extends jeden { public function __construct(){} public function wyswietl() { return $this->_var; } } $a = new dwa(); print_r($a->wyswietl());

@Kozack:
Niezbyt, bo musiałbym każdej funkcji przekazywać referencję obiektu.
@Einzeinbleth:
Pierwszy przykład przerabiałem i jest zły, bo w __construct otwieram połączenie z bazą i w zmiennej zapisuję uchwyt, a tym sposobem łączę się dwa razy z bazą.
Drugi przykład... Przed chwilą byłem ku niemu przychylny, ale przypomniałem sobie, że w __construct pierwszej klasy pobieram nazwę modułu do załadowania i innych zmiennych z $_GET. Stąd też nie mogę wywołać klasy, której nie załadowałem.
Ale jeżeli mam się tak głowić, to jednak wolę postawić na prostotę. Zmienne i nazwę modułu pobiorę strukturalnie, załaduję moduł, wywołam klasę i przekażę obiektowi te zmienne. Bo chyba niczego więcej się nie da zrobić.
Zaczynam pracować w OOP, a wiadomo, że początki nie zawsze są łatwe :-)
Użytkownik andrzej_aa edytował ten post 12 lipiec 2008, 23:27


Nie rozumiem w czym problem, przecież możesz stosowac oba kody i w niczym to nie przeszkadza :>
1) nie łączysz się dwa razy, specjalnie dałem wyświetlanie co się dzieje. I tak w pierwszym przypadku:
$a = new jeden(); $a->tworz(); $a->_b->wyswietl();
Co daje:
==> jeden::__construct ==> jeden::tworz ==> dwa::__construct ==> dwa::wyswietl
Trzeba tylko pamiętać by klasa "dwa" również miała __construct, bo inaczej wyjdzie:
==> jeden::__construct ==> jeden::tworz ==> jeden::__construct ==> dwa::wyswietl
I wtedy faktycznie byś mógł mieć dwa połączenia.

2) nadal możesz pobierać wszystko z $_GET i innych, także w __construct ...

Aha, już wiem czemu. Ale mimo wszystko, użyję metody z Twojego drugiego przykładu, bo w konstruktorze pierwszej klasy mam tworzenie połączenia z bazą, a rozszerzanie klasy nie rozszerza obiektu... tylko właśnie klasę. Jak wrócę do domu, wrzucę tutaj dwie moje klasy, by było to widoczne.
// Edytowano
Okrojony kod. Plik index.php:<?php class Sprzedawczyk { public $_p; public $_db; function __construct() { session_start(); $allowed = array('home', 'error', 'about', 'books', 'contact', 'admin', 'item', 'buy', 'rules', 'login', 'logout', 'add', 'profile', 'subjects'); if (!isset($_GET['p'])) $this->_p = array($allowed[0]); else { $this->_p = explode('/', htmlspecialchars($_GET['p'])); if (!in_array($this->_p[0], $allowed)) return new Error('Strona nie istnieje', 'exit'); if (empty($this->_p)) $this->_p = array($allowed[0]); } $this->_db = new Database; $this->_db->connect(); } } class Database { private $_connection; private $_resource; public $_count; public function connect() { if (!$this->_connection = sqlite_open('bin/sprzedawczyk.sqlite')) return new Error('Nie można połączyć się z bazą', 'exit'); $this->query('PRAGMA COUNT_CHANGES=off'); $this->query('PRAGMA TEMP_STORE=MEMORY'); $this->query('UPDATE books SET active=\'0\' WHERE active=\'1\' AND date2 < '.time()); } public function disconnect() { $this->query('VACUUM'); sqlite_close($this->_connection); } public function query($query) { if ($this->_resource = sqlite_query($this->_connection, $query)) return true; return false; } public function getItem($query) { if (!$this->query($query)) return new Error('Nie można wykonać zapytania SQL'); $this->_count = sqlite_num_rows($this->_resource); return sqlite_fetch_array($this->_resource, SQLITE_ASSOC); } public function getList($query, $key = null) { if (!$this->query($query)) return new Error('Nie można wykonać zapytania SQL'); $this->_count = sqlite_num_rows($this->_resource); $list = array(); if ($key) { while ($row = sqlite_fetch_array($this->_resource, SQLITE_ASSOC)) $list[$row[$key]] = $row; } else { while ($row = sqlite_fetch_array($this->_resource, SQLITE_ASSOC)) $list[] = $row; } return $list; } public function getRow($query) { $this->query($query); return sqlite_fetch_single($this->_resource); } } $app = new Sprzedawczyk; require 'bin/parser.php'; $parser = new Parser; require $parser->parse('_header'); require 'pages/'.$app->_p[0].'.php'; $app->_page = new Page(); $app->_page->_db = &$app->_db; $app->_page->_p = &$app->_p; $app->_page->display(); $lastList = $app->_db->getList('SELECT id, name FROM books WHERE active=\'1\' ORDER BY date DESC LIMIT 10'); require $parser->parse('_footer'); $app->_db->disconnect(); ?>I plik pages/home.php:<?php class Page { public function display() { $list = $this->_db->getList('SELECT id, price, icon, name, subject, userid, username FROM books WHERE active=\'1\' ORDER BY date DESC LIMIT 20'); $subjects = $this->_db->getList('SELECT id, subject FROM subjects', 'id'); $parser = new Parser; require $parser->parse('home'); } } ?>
Użytkownik andrzej_aa edytował ten post 13 lipiec 2008, 12:19
Pytanie z innej beczki.
Czemu przechowujesz obiekt do obslugi bazy danych w "$this->_db"?
Pewnie w wielu innych obiektach też tak masz. Użyj schematu Singleton a rozwiąże on wieele twoich problemów.

Dlatego, ponieważ nie chcę używać global $db. A możesz podać konkretny przykład? Bo tego z manualu nie rozumiem za bardzo...

static function &instance () { static $instance; if (!is_object($instance)) $instance = new self; return $instance; }
Wstawiasz to do każdej klasy i teraz egzemplarza tej klasy nie tworzysz za pomoca "new" lecz tak
$klasa=klasa::instance();
I już masz egzemplarz. Dodatkowo jeżeli w każdtym innym miejscu strony dasz $klasa=klasa::instance(); To nie dostaniesz nowego egzemplarzu obiektu tylko ten stary. Dlatego singleton idealnie nadaje sie do obiektow obslugi baz danych, czy tez przechowywujacych ustawienia. Ja stosuje do wszystkich przez co nie mam problemu z zarzadzaniem obiektami,
Użytkownik polasek edytował ten post 13 lipiec 2008, 14:08
Ale to mi w niczym nie pomoże. Chyba że źle myślę... Zostanę przy rozszerzaniu klas, bo to jest jak dla mnie wygodniejsze.

Nie powiedziałem, że rozwiąże problem z tematu.
Dałem ci tylko radę, żebyś nie przechowywywał tak egzempalrzy obiektów z zmiennych klas (u ciebie np _db);

Przecież to niczemu nie szkodzi. A mi nawet ułatwia pracę. Nawet kodu jest mniej niż używając metody Singleton...

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • nvm.keep.pl

  • Sitedesign by AltusUmbrae.