Stránka 1 z 1

PHP+OOP = Naschvály a hotové peklo

Napsal: 16 srp 2013, 02:16
od zdenda204
Ahoj, rozhodl jsem se přepsat web do OOP ale PHP mi dělá naschvály :(

//Edit: Ok, to hlavní bych vyřešil, ale teď je tu malá sviňárna (alespoň pro mě)

Spoiler: zobrazit

Kód: Vybrat vše

//MySQL webu
$mysql_host "localhost";
$mysql_user "root";
$mysql_psw "toor";
$mysql_db "web";


class 
databaze {
    public function 
prikaz($sql){
        
$mysqli = new mysqli($mysql_host$mysql_user$mysql_psw$mysql_db);
        
$mysqli->set_charset("UTF8");
        
$result $mysqli->query($sql);
        return 
$result;
    }

Ale v té spodní části, jak je připojení k MySQL, mi to vždy hodí undefined na všechny ty proměný s údaji od MySQL :(

Re: PHP+OOP = Naschvály a hotové peklo

Napsal: 16 srp 2013, 07:55
od vojtamaniak
V php jsem dlouho nedělal, ale zkus takto:
Spoiler: zobrazit

Kód: Vybrat vše

class databaze {

    private $mysql_host = "localhost";
    private $mysql_user = "root";
    private $mysql_psw = "toor";
    private $mysql_db = "web";

    public function prikaz($sql){
        $mysqli = new mysqli($this->mysql_host, $this->mysql_user, $this->mysql_psw, $this->mysql_db);
        $mysqli->set_charset("UTF8");
        $result = $mysqli->query($sql);
        return $result;
    }
}

Re: PHP+OOP = Naschvály a hotové peklo

Napsal: 16 srp 2013, 09:12
od Mysteria
To první je absolutně mimo, to druhé to sice bude funkční, ale i tak je mimo. Proč při každém příkazu se znova připojovat k databázi? Má to být asi takto:

Kód: Vybrat vše

<?php
class Database 
{
    private db;
    
    __construct
($host, $user, $pw, $db) {
        $this->db = new MySQLi($host, $user, $pw, $db);
        $this->db->set_charset('UTF8');
    }
    
    public function command
($sql) {
        return $this->db->query($slq);
    }
}

/* Použití */
...
$db = new Database('localhost', 'root', 'password', 'test');
$result = $db->command('SELECT * FROM test.tabulka;');
var_dump($result);
...
 
Mimochodem je bestpractise mít v jednom souboru pouze jednu třídu a nic víc (žádnej další kód, žádná další třída, ideálně pojmenovat nazevTridy.class.php, takže toto database.class.php.

Re: PHP+OOP = Naschvály a hotové peklo

Napsal: 16 srp 2013, 13:27
od zdenda204
Nojo, ale já právě chci aby se údaje třeba zadaly jen do nějákého configu a ta třída se sama připojovala :(
Abych pak v kódu už jen tahal a nemusel jí vždy dávat údaje.
Popřípadě nějaké vysvětlení na co je to $this? Učím se z DevBooku a u jednoho příkladu to pochopím, u druhýho zase ne :(

Re: PHP+OOP = Naschvály a hotové peklo

Napsal: 16 srp 2013, 13:51
od Mysteria
No v cfg to klidně mít můžeš, ale cfg asi nebudeš mít rozmrskanej podle jednotlivejch tříd. Config si uděláš zvlášť soubor a pak na začátku tvýho projektu si ho includneš do hlavního souboru. A pak jenom zavoláš to $db = new Database(...,...,...,...), kde ty proměnný se vezmou z toho inculovaných souboru.

Co se týká $this, tak $this odkazuje na samo sebe, takže když jsi ve třídě a chceš získat obsah nějaké proměnný ve třídě, tak musíš uvést $this->nazev.

Prostě ve třídě máš proměnné takto:
public / protected / private $nazev;
A dostaneš se k nim přes $this->nazev;
Public je věřejná (dostaneš se k ní mimo třídu, protected znamená, že je veřejná jenom pro potomky - dědičnost) a private že je neveřejná, tzn nikde jinde se k ní nedostaneš mimo třídu.

Viz třeba příklad s tou DB, máš tu třídu jak jsem ti napsal a tam máme private $db, kde je uloženo připojení k MySQL. Máme to private, takže $this->db->cokoliv můžeš použít jenom v té třídě.
Ale nemůžeš udělat třeba $db = new Database(...,...,...,...); echo $db->db; To ti napíše, že $db je provátní proměnná třídy Database a nejde přečíst. Kdyby jsi dal public $db; tak by to šlo.

Ale v praxi platí, že co nejvíc proměnných ve třídě by mělo být private, public jenom ty, které opravdu být musí.

Re: PHP+OOP = Naschvály a hotové peklo

Napsal: 16 srp 2013, 13:58
od zdenda204
Tak to je mi ta třída pak nanic když k ní musím dávat údaje zvenčí >.<
Chtěl jsem ušetřit kód v té funkční části a aby se to přesunulo do tříd, ale takto to vyjde nastejno :(

Re: PHP+OOP = Naschvály a hotové peklo

Napsal: 16 srp 2013, 16:01
od Mysteria
Jak zevnitř? Pokud by jsi měl třeba třídu na MC RCON server, tak si nějaké konstanty nebo věci, co se nemění můžeš dát rovnou ve třídě natvrdo, ale zrovna u téhle databáze, to je špatnej přístup, protože změna údajů od databáze se rovná změně třídy. Třída musí fungovat sama o sebe, bez toho aby bylo nutné ji přepisovat, když ji použiješ jinde. Viz třeba můj banlist nebo webshop, zadáš údaje při instalaci, uloží se to do cfg a pak se to přes konstruktor jednou dostane do té třídy a je to. Pak už ji jenom prostě používáš. :)

Ono taky v tomhle případně je to moc nedává smysl, protože příst třídu Database am ít tam jenom připojení a pak alias ke ->query() je zbytečný pro to dělat třídu. V tom Database by sis měl udělat metody, který pak jenom voláš.

Viz třeba můj serverlist, kde mám momentálně asi 20 funkcí (ve třídě se jim říká metody), kterýma získává informace, pak jenom v kódu napíšu $db = new Database(...); a var_dump($db->getServers()); a mám pěkně v poli všechny údaje o všech serverech. O tohle totiž jde. Zpřehledňuje a upravuje kód. Věci z jednoho celku pěkně dáš do jedné třídy a tu pak jenom použiješ v hlavním souboru. Navíc ji můžeš použít kolikrát chceš a podobně. Stejně jako na dababázi si uděláš třídu na přihlašování a podobně.

Kód: Vybrat vše

<?php
namespace App
;
use Nette, Model, Nette/Database/Connection, Nette/Caching/Cache;
class Database extends Nette/Object {
    private $db;
    private $sf;
    private $cache;        
    private $itemsPerPage
;
        
    public function __construct
(Nette/Database/Connection $db, $itemsPerPage, $cache) {
        $this->db = $db;        
        $this
->sf = new Nette/Database/SelectionFactory($db);
        $this->cache = $cache;                
        $this
->itemsPerPage = $itemsPerPage;
    }    
    
    public function getServers
($sort = 'passivePoints', $order = 'DESC', $page = 1, $search = null, $filterString = null, $filterNumber = null) {
        $args = array();
        if (!empty($filterString)) $args['version_string'] = $filterString;
        if (!empty($filterNumber)) $args['version_number'] = $filterNumber;
        $args['sl_servers_live.status'] = 'Online';
        return $this->sf->table('sl_servers_live')
            ->select('*')
            ->where($args)
            ->where('sl_servers_live.name LIKE ? OR
                     sl_servers.full_ip LIKE ? OR
                     sl_servers_live.version_string LIKE ? OR
                     sl_servers_live.version_number LIKE ? OR
                     sl_servers_live.map LIKE ?'
, "%$search%", "%$search%", "%$search%", "%$search%", "%$search%")
            ->order($sort . ' ' . $order)
            ->page($page, $this->itemsPerPage)
            ->fetchAll();
    }
    
    public function getServersCount
($search = null, $filterString = null, $filterNumber = null) {
        ...
    }
    
    
... 
Tak mě pak ještě napadlo, třeba jak mám private $itemsPerPage; tak to je dobrej příklad pro tebe, co můžeš dát přímo ve třídě, normálně tam dáš private $itemsPerPage = 50; a hotovo. Nemusíš to tam zadávat při vytváření. A teď se mě určitě zeptáš, proč to teda tak nemám, co? :D Já to věděl.
No já to tak nemám, protože $itemsPerPage používám i na hodně dalších místech, takže kdybych to chtěl změnit, tak to musím přepsat na dalších 150 místech, takže to mám definovaný právě v cfg a do všech tříd, kde to používám to dávám přes konstruktor. Přepíšu v cfg a automaticky mám všude novou hodnotu a hlavně všude 100% stejnou. Ale pokud by jsi to používal jenom tady, tak to můžeš dát přímo na tvrdo, já to tak měl za začátku taky.