Autor Zpráva
Donny
Profil *
Dobrý deň,

začal som si tak trochu študovať objektové programovanie v php, dá sa povedať že už pomerne skoro som narazil na problém.. skrátene, mám 3 základné subory na ktorých by som chcel stavať:

- Súbor mainClass.php - obsahuje komplet prácu z databázou
- Súbor aditionalClass.php - iné pre dôležité funkcie, ktoré by mali s databázou pracovať
- Súbor test.php - testovací, spúšťací súbor

Poznámka: Funckie v súboroch sú vo väčšine skrátené a fungujú a pre moju situáciu ktorú riešim sú nepodstatné..

mainClass.php
class mod_db
{
   function connection()   
   {
     // pripojenie na db
   }
   function update()
   {
     //update 
   }
   function insert()
   {
     //vlozenie
   }
   function delete()
   {
     //zmazanie
   }      
}
 

aditionalClass.php
Class pridavnaTrieda extends mod_db
{
    function setLanguage($setupID, $userID, $langID)     
    {  
       /*
       - setupID = poradove cislo v tabulke userSetup
       - userID = id uzitela
       - langID = id jazyka
       */
       
       $updateString = "userID = '$userID', langID = '$langID', lastChange = now()";
       $sql->update("$tabulka1", "$updateString", "setupID = '$setupID'");              
    }
}

Subor test.php
   //nacitanie externych suborov 
   include('settings.php');
   include(libraries.'mainClass.php');
   include(libraries.'aditionalClass.php');
   
   //spustenie tried  
   $sql = new mod_db(); 
   $create = new pridavnaTrieda();
   
   //spustenie toho co potrebujem
    $create->setLanguage($setupID, $userID, $langID);

No a tu nastáva vec ktorej tak celkom nerozumiem. Funkcia setLanguage využíva update databáze (teda funkciu z triedy mod_db) a napriek tomu že táto trieda už je spustená v podobe ako to mám zapísané to nefunguje.

Po drobnej úprave súboru aditionalClass.php to fungovať začne, ale ..

takto to funguje
Class pridavnaTrieda extends mod_db
{
    function setLanguage($setupID, $userID, $langID)     
    {         
       include('settings.php');      
       include(libraries.'mainClass.php'); 
       $updateString = "userID = '$userID', langID = '$langID', lastChange = now()";
       $sql->update("$tabulka1", "$updateString", "setupID = '$setupID'");              
    }
}

Toto riešenie my príde ako blbosť a predstavuje to pre mňa 2 zbytočné riadky vždy pri práci s databázov.. Do takého riešenia sa my veľmi ísť nechce, nezdá sa my efektívne..

Premýšľal som nad využitím výrazu public ale tak to tiež nefugnovalo..

Vedel by ste ma niekto nasmerovať čo robím zle, resp. čo som nepochopil?

Ďakujem.
ShiraNai7
Profil
Neextendoval bych mod_db - ale instanci mod_db predaval v konstruktoru, priklad:

class pridavnaTrieda
{

   protected $db;

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

   public function setLanguage($setupId, $userId, $langId)
    {
        $this->db->update( ... );
    }

}

Ale cele tve reseni je nejake prapodivne. Konfiguracni veci bych dal alespon do konstant nebo nejlepe do instance tridy urcene pro tento ucel. Neni dobre psat kod pulka OOP, pulka procedural.
Ugo
Profil
ještě dodám důvod proč to nefunguje .... jde o viditelnost proměnných, $sql definuješ v globálním prostoru a ve funkci třídy tedy není přístupná a musíš jí tam nějak dostat, doporučuji to co ShiraNai7 . Pro pochopení si tam ale můžeš ještě dát global $sql; na začátek té fce.
Donny
Profil *
Ďakujem páni, na základe rád som to (čiastočne) vyriešil. Momentálne skúšam vytvoriť spomínanú konfiguračnú triedu..

To že to nefunguje kvôli viditeľnosti som viac menej predpokladal, ale napriek tomu sa nemôžem ubrániť dojmu že veci definujem (resp. musím definovať) x krát.


a to my príde nepraktické..
ShiraNai7
Profil
Donny:
Závislosti stačí "definovat" (předat přes konstruktor) pouze jednou.. a to při vytváření instance daného objektu. Pak je jen používáš.
Ugo
Profil
Donny:
nepraktické to v určitých situacích je, ale má to právě tu výhodu že když to "definuješ" víckrát, tak to můžeš víckrát zadefinovat trošku jinak, což ti může pomoct při úpravách a znovupoužití stejného kusu kódu
Donny
Profil *
ShiraNai7
Áno rozumiem že v aktuálnom prípade sa jedná o jedno predanie do prídavnej triedy, osobne sa ale zamýšľam aj trošku dopredu.. Programovaniu sa venujem viac menej amatérsky ale už som si na určitý systém práce zvykol, je pre mňa prehľadný. Preto prepokladám že budem mať viac tried s ktorými budem pracovať v rôznych situáciách.

Len tak z hlavy ma napádajú tak 4 ďalšie základné triedy, ktoré by spravovali iné funkcionality. Základné načítanie sa dá vyriešiť funkciou autoload ale keďže všetky funkcie budú pracovať s databázou + budú potrebovať konfiguráciu, vzniká tu duplicita funkcie construct ktorá tam bude musieť byť vždy, tj. min 3 riadky vždy. Ak sa jedná o pár tried nie je to nič tragické ale ak by som tých tried mal 40 tak je to už trošku také ťažkopádnejšie.. aspoň mne to tak príde
Ugo
Profil
<?php
class DatabaseWorker {
  protected $db;
  public function __construct($db) {
    $this->db = $db;
  }
}
class pridavnaTrieda extends DatabaseWorker {
/* uz bez constructu */
}

je to taková rodina pracovníku s databázi kde se řemeslo předává z generace na generaci již při narození :D
ShiraNai7
Profil
Hlavně dělej 1 třídu na 1 věc. Nedělej univerzální supertřídy třídy na všechno.
Donny
Profil *
Ugo:
Zaujímavý námet, Ďakujem :). Napáda ma preto otázka prečo (ak to teda ide takto) nemôžem využiť priamo tú triedu mod_db, ktorá spravuje všetky veci ktoré slúžia na pripojenie?

class mod_db
{
   protected $db;
   public function __construct($db) {
    $this->db = $db;
   }
   // pripojenie na db
   public function connection()   
   {
     
   }
   //update 
   public function update()
   {

   }
   //vlozenie
   public function insert()
   {

   }
    //zmazanie
   public function delete()
   {

   }      
}


ShiraNai7:
áno, na toto som narážal, som zvyknutý oddelovať funkcionality..

1. súbor - databáza
2. súbor - jazykove nastavenia
3. súbor - identifikácia
4. Súbor - štatistiky

a podobne, keď som si to premietol na to že to "preklopím na triedy" tak to na mňa pôsobilo dosť neprakticky..
Majkl578
Profil
Donny:
prečo nemôžem využiť priamo tú triedu mod_db, ktorá spravuje všetky veci ktoré slúžia na pripojenie
Protože by to nedávalo smysl. Třída se nestará o připojení, ale o pouze manipulaci s daty. Nebude připojení ani sama nějak tajuplně vytvářet. Třída připojení jen využívá, tudíž jej dostane v konstruktoru (jako závislost) a následně bude pouze využívat.
Lamicz
Profil
Donny
Zastávám názor, že základní výhoda OOP je autoload tříd. Nastudování ušetří spoustu require a problémů s chybějícími třídami.
Donny
Profil *
Dobrý deň,

Po vašej rade, som sa tejto tematike začal intenzívnejšie venovať a opäť som narazil na problém, keďže to viac menej pokračuje nebudem vytvárať nové vlákno, aby sa nestratilo prepojenie s týmto problémom.

Vytvoril som si triedu front, ktorej úlohou je generovať načítanie a spustenie konkrétnej triedy a metódy na základe adresy, funguje to takto:

www.nieco.sk -> spustí základnú preddefinovanú triedu
www.nieco.sk/blog -> načíta subor class.blog.php, triedu blogControler a metodu blog()
www.nieco.sk/blog/clanok/1/ -> načíta subor class.blog.php, triedu blogControler a metodu clanok() s id 1

Princíp je fajn, funguje to presne tak ako si predstavujem (nepodstatné časti kódu v ukážke preskakujem,nakoľko je to dlhé), mám tu však 1 problém + 1 otázku.
<?php
class Front
{
    protected $_file;
    protected $_controller;
    protected $_method;    

    public function run()
    {
        //spracovanie adresy
        $route = str_replace(ALIAS, '', $_SERVER['REQUEST_URI']);
        $params = explode('/', trim( $route, '/') );
            
        if(!empty($params [1]))
        {
            /*
            overenie jednotlivych parametorv z adresy a nacitanie premených 
            subor.php do premenej this->_file, 
            trieda do $this->_controller 
            metoda do $this->_method
            */
        }
        else
        {
             //ak nie je param, nacitaj hlavnu triedu          
     }
    } 
    // ak subor existuje nacitaj ho a spusti prislusne veci
    if (file_exists($this->_file)) 
    {
          require($this->file);
          $className = $this->_controller. 'Controller';
          $controller = new $className();          
          call_user_func(array($controller, $this->_method));  
    } 
    else 
    {      
         require("class.extensions");
         $controller = new extensionsController;
         call_user_func(array($controller, "chyba()"));  
    }
}

a tu je problém resp. otázka.
1. v jednotlivých triedach občas potrebujem pracovať s databázov, ak nadväzujem na našu predošlú diskusiu a vašu radu mal by som teda pri takomto automatizovanom postupe funkcie spúšťať takto $controller = new $className($sql); a do každej triedy tým predávať možnosť pripojenia na sql databázu? Ak som tomu teda porozumel správne, tak trieda blog by pre otestovanie mohla vyzerať takto:

blog.php
<?php
Class blogController
{
    protected $db;    
 
    public function __construct($sql)
    {        
       $this->db = $sql;              
    }
    //vyber z tabulky
    public function blog()
    { 
        $query = "SELECT *  FROM `$tabulka1`";
        $dotaz = mysql_escape_string($query);                  
        $pocet = $this->db->nums($query);
        echo $pocet;
    }                
}
?>

Výsledok je ale pre mňa dosť prekvapivý, Call to a member function nums() on a non-object, čo znamená že nie je možné spúšťať metodu mimo objektu, ale veď nato tam dávam to dedenie nie?

2. je lepsie používať call_user_func() alebo klasické $controller->metoda();
ShiraNai7
Profil
Donny:
Výsledok je ale pre mňa dosť prekvapivý, Call to a member function nums() on a non-object
Určitě předáváš v konstruktoru tu instanci? Vydumpuj si před tím řádkem s chybou, co tam skutečně je.
var_dump($this->db);

$dotaz = mysql_escape_string($query);
Tohle je nesmysl ze 2 důvodů:
1) escapuješ celou query - proč? funkce se má používat na stringové části dotazu
2) když už máš funkce ohledně databáze v té třídě, tahle by tam měla být taky

2. je lepsie používať call_user_func() alebo klasické $controller->metoda();
Vždy používej $objekt->metoda();. Funkce call_user_func/call_user_func_array() je pro případy, kdy to prostě jinak nejde (callback předaný v argumentu, popř. variabilní počet argumentů v poli, v PHP 5.4 můžeš proměnnou obsahující callback volat rovnou jako $promenna()).
Donny
Profil *
Pri pohľade na var_dump sa my "rozsvietilo", chyba bola že som predával $controller = new $className($sql); správne má byť $controller = new $className($this->_db);

Tohle je nesmysl ze 2 důvodů:
1) escapuješ celou query - proč? funkce se má používat na stringové části dotazu
2) když už máš funkce ohledně databáze v té třídě, tahle by tam měla být taky


Berte len ako ukážkový kód, ale dám si na to escapovanie dotazu pozor a escapovaciu funkciu dám určite do triedy pre mysql.

2. Super.

Ďakujem.

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