Autor Zpráva
CistiC
Profil *
Zdravím,

začínam s oop a hned jsem narazil na problém a nevím, jaké je správné řešení.
----------------------------------
index.php
...
$mysqli = new mysqli("localhost", "user", "pass", "databaze");
...
$menu = new MojeMenu();
...
----------------------------------
class MojeMenu
{
function __construct()
{
$query = 'SELECT id, nazev FROM menu ORDER BY poradi;';
$result = $mysqli->query($query);
...
$result->close();
}
}
----------------------------------
Vyhazuje to:
Fatal error: Call to a member function query() on a non-object

Když do __construct přidám: $mysqli = new mysqli("localhost", "user", "pass", "databaze");
Musím v každé třídě, která přistupuje k databázi vytvářet připojení k databázi (objekt $mysqli)?

Děkuju za pomoc.

CistiC
Akacko
Profil
CistiC
sice nejsem v oop nějaký profik, ale myslím že by to šlo vyřešit pomoci děděni.

Zkus tvořit třídu takto: class MojeMenu extends mysqli.
a tento řádek potom jako takto $result = mysqli::query($query);

Doufám že jsem nenapsal nějakou blbost.
BetaCam
Profil
Akacko
CistiC

sice nejsem v oop nějaký profik, ale myslím že by to šlo vyřešit pomoci děděni.
Zkus tvořit třídu takto: class MojeMenu extends mysqli.


V žádném případě tohle nedělej. Dědění je sice krásná věc ale mělo by se dodržovat pravidlo, že potomek je specialní případ rodiče. Stejně tak potomek by měl umět zastat funkci rodiče.
CistiC
Profil *
Vyreseno.

Staci si zpristupnit $mysqli uvnitr te tridy pomoci global.
BetaCam
Profil
CistiC
začínam s oop a hned jsem narazil na problém a nevím, jaké je správné řešení.

Mimochodem řešení existuje spousta jenže většina tech řešení se odvozuje podle toho jak je navržená aplikace jako taková. Je těžké navrhovat tu nejaké řešení, když nevíme jak máš koncipovanou aplikaci. Každopáně by ses měl drzet toho co jsem psal v předchozím postu. A navíc ve většině případů je lepší třídy složit než je dědit.
BetaCam
Profil
CistiC
Staci si zpristupnit $mysqli uvnitr te tridy pomoci global.
To mi nepřipadá zrovna jako nejoriginálnější řešení. :)
orsic
Profil
To mi nepřipadá zrovna jako nejoriginálnější řešení. :)
a jaké by tedy bylo originelní řešení ??
lucas
Profil *
napriklad v triede budes mat private $sql_spojenie a cez konstruktor uz len vlozis raz vytvorene spojenie to objektu.
BetaCam
Profil
orsic

Záleží na povaze aplikace. Sem zvyklej dělat aplikace jako MVC proto mi to přijde jako pro mě "divné" řešení.
CistiC má svou třídu pojmenovanou jako MojeMenu z čehož se dá usuzovat, že by to v podstatě měl být nějaký view. Už jen to, že se view se stará o to co by měl dělat Model mi přijde divné, ale jak říkám si je to tím, že sem příliš zvyklí na MVC.

a jaké by tedy bylo originelní řešení ??

Způsobu je hromada. Od parameru až po zdědění třídy v nějaké logické hierarchii tříd.

A popravdě mě OOP a používání globálních proměnných moc k sobě nepasuje. :)
Mastodont
Profil
Jestli ta třída MojeMenu slouží ke generování nabídky (jak odhaduji), tak já bych jí $result předal v konstruktoru nebo jako parametr metody. Dotaz a načítání dat úplně oddělit.
 echo $Formatter:getTable($DAO->getSomeRows($table, $fields, $where));

Asi takto to mám já. Metoda getSomeRows vrací result, getTable hotovou HTML tabulku.
BetaCam
Profil
Mastodont

No jenže tenhle příklad vyplívá z větší či menší části z návrhu tvé aplikace. Je otázka jestli CistiC, který píše, že s OOP začíná má vůbec návrh a strukturu aplikace.
Mastodont
Profil
BetaCam
To asi má, pochybuji, že by psal třídu pro menu, která by nebyla do ničeho zasazena.

Na otázku

Musím v každé třídě, která přistupuje k databázi vytvářet připojení k databázi (objekt $mysqli)?

odpovídám takto: takovou třídu si udělej jen jednu. (Další možnost je třeba singleton vracející handle připojení, který je předáván do dalších tříd dle potřeby. Známá věc, která se dá lehce vygooglit.)
BetaCam
Profil
Mastodont
To asi má, pochybuji, že by psal třídu pro menu, která by nebyla do ničeho zasazena.

Ani bych se nedivil kdyby nebyla. :) Vetšina začátečníků s OOP má pocit, že OOP je o uzavření kódu do tříd. Na prvotní návrh kašlou. Až když začnou opravdu "myslet" a OO programovat začnou aplikaci navrhovat v pravém smyslu OOP.

Třeba sou mé názory pomýlené a možná zbytečně CistiCe podceňuji, ale většinou, když se setkám s aplikací od OOP začátečníka tak to má s OOP opravdu společného snad jen to slovo class. :)
Mastodont
Profil
Vetšina začátečníků s OOP má pocit, že OOP je o uzavření kódu do tříd.

Známá věc :-)))

//index.php
$app = new Application();
$app->Start();
...
radekzatec
Profil
neni to ma práce ale inspirace to myslim bude kazdej si upravi dle vlastních potreb

<?php
  // soubor heslo.php
  $mysqluzivatel="user";    // jméno uživatele pro přístup k MySQL 
  $mysqlheslo="paswd";     // heslo
  $mysqlhost="localhost";   // název počítače, na kterém běží MySQL
  $mysqldb="nazev_DB";  // název databáze
?>


<?php

// Kvůli lepšímu zabezpečení přesuňte heslo.php do složky,
// která není přístupná z WWW a upravte cestu k souboru
// v require.once


class MojeDb {
  protected $mysqli;
  protected $zobrazitchyby = TRUE;   // nastavte na FALSE, pokud nechcete vidět chybové zprávy
  protected $zobrazitsql   = FALSE;  // nastavte na TRUE, pokud chcete při ladění vidět všechny dotazy SQL
  protected $sqlpocitadlo = 0;     // počitadlo pro příkazy SQL
  protected $radkypocitadlo = 0;     // počitadlo pro vrácené řádky SELECTů
  protected $dbcas     = 0;     // počitadlo času pro provedení dotazů
  protected $pocatecnicas;

  // konstruktor
  function __construct() {
    require_once('heslo.php');
    $this->mysqli = @new mysqli($mysqlhost, $mysqluzivatel, $mysqlheslo, $mysqldb);
    // bylo připojení navázáno v pořádku?
    if(mysqli_connect_errno()) {
      $this->tiskchyby("Nepodařilo se navázat připojení! (" . mysqli_connect_error() . ")");
      // sem je možné doplnit HTML
      // pro ukončení stránky (</body></html> apod.)
      $this->mysqli = FALSE;
      exit();
    }
    $this->pocatecnicas = $this->microtime_jako_float();
  }

  // destruktor
  function __destruct() {
    $this->close();
   }

  // explicitní uzavření
  function close() {
    if($this->mysqli)
      $this->mysqli->close();
      $this->mysqli = FALSE;
  }

  function odkaznaMysqli() {
    return $this->mysqli; }

  // spuštění dotazu SELECT, vrácení pole
  function dotazPoleObjektu($sql) {
    $this->sqlpocitadlo++;
    $this->tisksql($sql);
    $cas1  = $this->microtime_jako_float();
    $vysledek = $this->mysqli->query($sql);
    $cas2  = $this->microtime_jako_float();
    $this->dbcas += ($cas2 - $cas1);
    if($vysledek) {
      if($vysledek->num_rows) {
        $vysledek_array = array();
        while($radek = $vysledek->fetch_object())
          $vysledek_array[] = $radek;
        $this->radkypocitadlo += sizeof($vysledek_array);
        return $vysledek_array; }
      else
        return FALSE;
    } else {
      $this->tiskchyby($this->mysqli->error);
      return FALSE;
    }
  }

  // spuštění dotazu SELECT, vrácení pole
  function dotazPole($sql) {
    $this->sqlpocitadlo++;
    $this->tisksql($sql);
    $cas1  = $this->microtime_jako_float();
    $vysledek = $this->mysqli->query($sql);
    $cas2  = $this->microtime_jako_float();
    $this->dbcas += ($cas2 - $cas1);
    if($vysledek) {
      if($vysledek->num_rows) {
        $vysledek_array = array();
        while($radek = $vysledek->fetch_array())
          $vysledek_array[] = $radek;
        $this->radkypocitadlo += sizeof($vysledek_array);
        return $vysledek_array; }
      else
        return FALSE;
    } else {
      $this->tiskchyby($this->mysqli->error);
      return FALSE;
    }
  }


  // spuštění dotazu SELECT, který vrací jen jednu
  // položku (například SELECT COUNT(*) FROM tabulka);
  // vrátí tuto položku
  // pozor: při výskytu chyby vrátí -1, nikoli 0!
  function dotazJednaPolozka($sql) {
    $this->sqlpocitadlo++;
    $this->tisksql($sql);
    $cas1  = $this->microtime_jako_float();
    $vysledek = $this->mysqli->query($sql);
    $cas2  = $this->microtime_jako_float();
    $this->dbcas += ($cas2 - $cas1);
    if($vysledek) {
      if ($radek=$vysledek->fetch_array()) {
        $vysledek->close();
        $this->radkypocitadlo++;
        return $radek[0];
      } else {
        // dotaz nevrátil žádná data
        return -1;
      }
    } else {
      $this->tiskchyby($this->mysqli->error);
      return -1;
    }
  }

  // spuštění příkazu SQL, který nevrací data
  function provest($sql) {
    $this->sqlpocitadlo++;
    $this->tisksql($sql);
    $cas1  = $this->microtime_jako_float();
    $vysledek = $this->mysqli->real_query($sql);
    $cas2  = $this->microtime_jako_float();
    $this->dbcas += ($cas2 - $cas1);
    if($vysledek)
      return TRUE;
    else {
      $this->tiskchyby($this->mysqli->error);
      return FALSE;
    }
  }

  // zjištění insert_id po příkazu INSERT
  function vlozeneId() {
    return $this->mysqli->insert_id; }

  // vložení \ před ', " atd.
  function escape($text) {
    return trim($this->mysqli->escape_string($text)); }

  // vrátí 'NULL' or '<uvozovkovaný řetězec>'
  function sql_retezec($text) {
    if(!$text || trim($text)=="")
      return 'NULL';
    else
      return "'" . $this->escape(trim($text)) . "'";  }

  function error() {
    return $this->mysqli->error; }

  private function tisksql($sql) {
    if($this->zobrazitsql)
      printf("<p><font color=\"#0000ff\">%s</font></p>\n",
        htmlspecialchars($sql));    }

  private function tiskchyby($text) {
    if($this->zobrazitchyby)
      printf("<p><font color=\"#ff0000\">%s</font></p>\n",
        htmlspecialchars($text));  }

  function zobrazitStatistiku() {
    $totalTime = $this->microtime_jako_float() - $this->pocatecnicas;
    printf("<p><font color=\"#0000ff\">Příkazy SQL: %d\n",
      $this->sqlpocitadlo);
    printf("<br />Celkem vráceno řádků: %d\n",
      $this->radkypocitadlo);
    printf("<br />Celková doba provádění dotazů (MySQL): %f\n",
      $this->dbcas);
    printf("<br />Celková doba zpracování (PHP): %f\n",
      $totalTime - $this->dbcas);
    printf("<br />Celkový čas od posledního vytvoření/vynulování objektu MojeDB: %f</font></p>\n",
      $totalTime);    }

  function vynulovatStatistiku() {
    $this->sqlpocitadlo = 0;
    $this->radkypocitadlo = 0;
    $this->dbcas     = 0;
    $this->pocatecnicas = $this->microtime_jako_float();  }

  private function microtime_jako_float() {
    list($usek, $sek) = explode(" ", microtime());
    return ((float)$usek + (float)$sek); }

}
AM_
Profil
Když už píšete třídu pro rozšířenou obsluhu MySQL, není lepší to psát řekněme jako dědice třídy mysqli? Nejsem zas tak ostřílený objektař, ale přijde mi to logičtější i jednodušší.
fuckin
Profil *
Am_
V zadnem pripade, trida mysqli je zbytecne komplexni a zbytecne by v tom udelala bordel, ceho bys ti jako dosahl? Vzdy se dela oop trida pro db, nikdy jsem vsak nevidel jako dedice mysqli. A logictejsi ci jednodussi to neni...
AM_
Profil
No stejne ji pouzijes, tak mas po ni dedit nebo psat tridu jejiz clenskou promennou bude odkaz na instanci mysqli? Zalezi tedy, na co to chces pouzit:
1-jako univerzalni rozhrani s DB (az web pobezi na jine DB, trida se da prepsat) - pak ano, zvlast tridu
2-jako rozsireni funkcionality mysqli o ruzne zlepsovaky - neni duvod po ni nededit. Proc by to, ze je sama o sobe komplexni, melo byt duvod? A hlavne pak mas instanci jedne tridy, a ne instanci tve tridy s pridelenim clena instance mysqli tridy.
rixi
Profil
k tejto tebe ak som dobre pochopil, tak pri connecte sa vyuziva inicializacia triedy mysqli a pri spracovavani vysledkov, konkretne mysqli->query vytvori a vyuziva dalsiu triedu a to mysqli_result, je tak? ak ano, v php manualu som o tom, co funkcia vracia, nic take nenasiel. otazka znie ci su moje uvahy spravne a ze preco sa to v manualu o tom nespomina. vychadza princip z toho, ze by na to mal prist clovek sam?

tiez nie som v oop zdatny, takze nie som si isty, ci som to dobre pochopil a tak sa za pripadne "blaboly" ospravedlnujem.

d

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: