PHP a pochopení OOP – PHP – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

PHP a pochopení OOP – PHP – Fórum – Programujte.comPHP a pochopení OOP – PHP – Fórum – Programujte.com

 
Hledat
Moderní platforma pro vytvoření vašeho nového webu – Wix.com.
Nyní už můžete mít web zdarma.
Vybavení pro Laser Game
Spuštěn Filmový magazín
Laser Game Brno

Spuštěný nový filmový web Filmožrouti.cz — vše o Avengers, Pacific Rim, Thor, Star Wars…
šnek
~ Anonymní uživatel
21 příspěvků
3. 10. 2018   #1
-
0
-

Zdravím přátelé. Snažím se pochopit oop v php, jak se používá, k čemu je dobré. Zkusil jsem si udělat jednoduchý login, chci znát vaše názory, rady, jak to dělat jinak a podobně.

<?php
class login {
    public $id;
    
    public function __construct() {
        if(isset($_SESSION["loginId"])) $this->id = $_SESSION["loginId"]; //pokud sme jiz prihlaseni, tak to rovnou ulozime
    }
    
    function isLogged() {
        if(isset($_SESSION["loginId"])) {
            return true;
        } else {
            return false;
        }
    }
    public function setId(int $id) {
        $this->id = $id;
        $_SESSION["loginId"] = 100;
    }
    public function login($user, $pass) {
        if($user == "jakub" && $pass == "petr") { 
            $this->setId(100);
            return true;
        } else {
            return false;
        }
    }
    
    function logout() {
        unset($_SESSION["loginId"]);
    }
    
    
}

Pokaždé v hlavičce udělám $login = new login(); - pokud už jsem přihlášený, měl bych mít možnost používat na stránkách $login->isLogged(), případně pak dopsání fukce na získání ID kdo je přihlášený a pod.

pokud není přihlášen, mohu to umožnit pomocí $login->login("jméno","heslo"); což vrátí true/false podle toho, zda je kombinace správná...

Je toto správně? Díky za rady

Nahlásit jako SPAM
IP: 185.193.86.–
Kit+14
Guru
3. 10. 2018   #2
-
0
-

#1 šnek
Pro začátek to nevypadá špatně. Zkusím to rozebrat.

Jméno třídy by mělo začínat velkým písmenem. Je to sice jen formalita, ale každý vývojář ti to omlátí o hlavu.

Atribut $id by měl být private. Ovšem připadá mi tak trochu zbytečný - můžeš místo něj uvnitř třídy používat $_SESSION["loginId"]. Třída se tím zpřehlední. S tím souvisí i poslání třídy - je to vlastně obálka (proxy) nad touto superglobální položkou.

Metoda setId() by také neměla být public. Používáš ji přece jen uvnitř třídy.

Return true nebo false je velkým nešvarem ve zdrojácích, čitelnosti to nepomáhá. Metoda isLogged() se dá elegantně zkrátit:

public function isLogged() {
    return isset($_SESSION["loginId"]);
}

Všimni si, že jsem uvedl "public", což je totéž, jako kdyby tam nebylo nic. Používej to u všech veřejných metod nebo u žádné, ať to má řád.

Místo metody $login->isLogged() by mohlo být praktičtější $login->getId(); Až pochopíš výjimky, tak zjistíš, že metoda $login->isLogged() bude zpravidla zbytečná.

Drž se pravidla, že název třídy a instance by měl být podstatným jménem, název metody slovesem. Pak se ti nebude stávat, že budeš mít ve zdrojáku ošklivé $login->login(). Zkus se zamyslet, zdali by nebylo lepší ten objekt pojmenovat třeba $user. Názvy metod na to budou krásně sedět.

Metoda logout() ti nezlikviduje atribut $id. O důvod víc, proč ho nemít.

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnek
~ Anonymní uživatel
21 příspěvků
3. 10. 2018   #3
-
0
-

Super, díky za postřehy.

Měl bych další otázku - jak implementovat cizí třídu?respektive, dejme tomu, chci mít další třídu messages s funkcema succes a error, principielne messages->succes("vše ok"); a opačně při chybě. Aby se to dalo jednoduše stylovat... Používá se na tohle vůbec třída? protože když funkce, která tě přihlásí nic nemá vracet, jak by o fungovalo? Kdo se má postarat o vypsání chyby, že bylo zadáno špatné jméno/heslo? Třída nebo skript, co volá třídu?

Nahlásit jako SPAM
IP: 185.193.86.–
šnek
~ Anonymní uživatel
21 příspěvků
4. 10. 2018   #4
-
0
-

Další otázka... Pokud správně chápu, třída by měla být nezávislá jiným třídám, jak řešit tahání z DB, když chci používat pdo?

Můžete mi tu prosím udělat příklad jak pomocí PDO udělám funkci na vytáhnutí username z mysql když znám id?

    function getUsername($id) {
        
    }


Jde mi o to, jestli každé volání funkce vytvářet novou instanci s pdo, nebo v hlavičce webu v indexu vytvořit

$db = new pdo(user, pass, db....);

A pak celý projekt používat ve všech třídách pomocí globals $db? přijde mi to jako prasárna...

Případně vytvořit jednu solo třídu, která bude obsluhovat DB? vkládat/tahat data z db? Já vím že tímhle se už dost provokuje MVC, ale potřebuju nejdřív pochopit základy a standarty OOP

Nahlásit jako SPAM
IP: 93.99.138.–
šnek
~ Anonymní uživatel
21 příspěvků
4. 10. 2018   #5
-
0
-

Teď si tu tak trošku píšu sám, omlouvám se :D

napaldo mě tohle řešení, kdy tu instanci předám pomocí konstruktoru do třídy...

    private $id;
    private $_db;
    function __construct(PDO $db) {
        if(isset($_SESSION["loginId"])) $this->id = $_SESSION["loginId"]; //pokud sme jiz prihlaseni, tak to rovnou ulozime
        $this->$_db = $db;
    }
    function isRegister() {
        $sql = 'SELECT username FROM users LIMIT 1';
        if($this->_db->query($sql)->rowCount() > 0) return true;
        return false;   
    }    
    function isLogged() {
        return isset($_SESSION["loginId"]);
    }


Co myslíte?

Nahlásit jako SPAM
IP: 93.99.138.–
gna
~ Anonymní uživatel
746 příspěvků
4. 10. 2018   #6
-
0
-

#5 šnek
JJ, v pohodě.

Nahlásit jako SPAM
IP: 213.211.51.–
šnekr0
Newbie
4. 10. 2018   #7
-
0
-

Mno trošku bojuju....

index: 

<?php
 ini_set("display_errors", 1);
    session_start();
    define('SQL_HOST', 'localhost');
    define('SQL_DBNAME', 'oop');
    define('SQL_USERNAME', 'root');
    define('SQL_PASSWORD', '');

    $dsn = 'mysql:dbname=' . SQL_DBNAME . ';host=' . SQL_HOST . '';
    try {
        $_db = new PDO($dsn, SQL_USERNAME, SQL_PASSWORD);
        $_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch (PDOException $e) {
        die('Connection failed: ' . $e->getMessage());
    }

    include "class/login.php";
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <?php
            $user = new User($_db);
            
            if(isset($_POST["user"])) {
                $user = $_POST["user"];
                $pass = $_POST["pass"];
                $user->login($user, $pass);    
            }

            //$user->login("jakub", "petr");
            //$user->logout();
            if($user->isLogged())  {
                echo "Test OK!";
            } else {
                echo "<form method=\"post\" action=\"\" > ";
                   echo "Jmeno: <input type=\"text\" name=\"user\"  ><br>";
                   echo "Heslo: <input type=\"text\" name=\"pass\"  ><br>";
                   echo "<input type=\"submit\" name=\"btn\"  ><br>";
                echo "</form>";
            }
            
            echo "<br>";
            
            
        ?>
    </body>
</html>

login.php (přejmenuju na users.php)

<?php
include "messages.php";

class User  extends Messages {
    private $id;
    private $_db;
    
    function __construct(PDO $db) {
        if(isset($_SESSION["loginId"])) $this->id = $_SESSION["loginId"]; //pokud sme jiz prihlaseni, tak to rovnou ulozime
        $this->_db = $db;
    }
    function isRegister() {
        $sql = 'SELECT username FROM users LIMIT 1';
        if($this->_db->query($sql)->rowCount() > 0) return true;
        return false;   
    }    
    function isLogged() {
        return isset($_SESSION["loginId"]);
    }
    
    function setId(int $id) {
        $this->id = $id;
        $_SESSION["loginId"] = 100;
    }
    
    function login($user, $pass) {
        $pass = MD5($pass);
        
        $dotaz = $this->_db->prepare("SELECT id FROM user WHERE username = ?, password = ?");
        $dotaz->execute(array($user,$pass));
        
        if($dotaz->rowCount() > 0) {    //Vyfusnem min. 1 řádek, takze zadal login v poradku 
            $data = $dotaz->fetch();
            $this->setId($data["id"]);
            $this->writeSucces("Přihlášeno!");
        } else {
            $this->writeError("Chybně zadané údaje!");
        }
    }
    
    function logout() {
        unset($_SESSION["loginId"]);
        unset($this->id);
    }  
}

Stránka vrací:

Fatal error: Uncaught Error: Call to a member function login() on string in C:\xampp\htdocs\ooplogin\index.php:32 Stack trace: #0 {main} thrown in C:\xampp\htdocs\ooplogin\index.php on line 32

Co mu vadí? K db připojený jsem...

Nahlásit jako SPAM
IP: 93.99.138.–
MilanL+1
Věrný člen
4. 10. 2018   #8
-
+1
-
Zajímavé

#7 šnekr
řekl bych, že mu vadí ty stejný názvy $user

Edit: myšleno v index.php nejdřív definuješ $user jako objekt User a pak do něj přiřazuješ $_POST["user"]

takže když to dojde na řádek 32 máš v $user ten string z POSTu a ten nemá metodu login

viz. ta chyba

Nahlásit jako SPAM
IP: 91.139.9.–
šnekr0
Newbie
4. 10. 2018   #9
-
0
-

#8 MilanL
No jo, taková triviální chyba... boha jeho     

Nahlásit jako SPAM
IP: 93.99.138.–
Kit+14
Guru
4. 10. 2018   #10
-
0
-

#7 šnekr
Vyhýbej se globálním proměnným a konstantám. Tedy i define(). 

$host = 'localhost';
$dbname = 'oop';
$charset = 'utf8';
$username = 'root';
$password = '';
$dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
$options = array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
);
$db = new PDO($dsn, $username, $password, $options);
Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:500e:7140:8f68:cd4f...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr0
Newbie
4. 10. 2018   #11
-
0
-

#10 Kit
Z jakého důvodu? Zrovna údaje k DB jsou předem danné a nemění se...

Jen mimo OOP - je nějaký velký rozdíl mezi echo a print?:D

Nahlásit jako SPAM
IP: 93.99.138.–
Kit+14
Guru
4. 10. 2018   #12
-
0
-

#11 šnekr
Zrovna přihlašovací údaje nechci mít roztahána po celé aplikaci, aby k nim měl přístup i ten, kdo třeba dopíše nějaký plugin. Navíc mi to znemožňuje mít otevřených více databází. Podstatné však je, že tyhle konstanty nikde jinde nepotřebuji, pouze v tom jednom místě. Není tedy ani důvod je mít globální.

Mezi echo a print není rozdíl. Je však zvyklostí používat echo.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:500e:7140:8f68:cd4f...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr
~ Anonymní uživatel
19 příspěvků
4. 10. 2018   #13
-
0
-

Díky za vysvětlení, pravda...

Ještě jsem se ptal - když se přihlašuju, kdo má psát chybové hlášky? Ta čáíst, co volá funkci třídy, třída, nebo tak jak to mám externí třídou na výpis hlášek? (messages->writeSucces(), messages->writeError()?

Dále jsem narazil na problém... Proč nemůžu použít extends na více tříd? mám třídu Messages na informační zprávy a pak bych chtěl mít solo třídu na hesla? Nebo ty hesla mám nechat zabalený v tříděš s loginem?

Další otázka OOP na příkladu loginu/registrace - udělat pro registraci solo třídu, nebo ji vmísit do téhle třídy login? Nemusí se jednat vždy o veřejnou klasickou registraci, ale i třeba o správu uživatelů administrace....

Nahlásit jako SPAM
IP: 185.193.86.–
Kit+14
Guru
4. 10. 2018   #14
-
0
-

#13 šnekr
Nejlépe pokud třída žádné chybové hlášky nevypisuje, ale jen vyhodí výjimku. Tu pak na vhodném místě mimo třídu zachytíš a zpracuješ.

K čemu potřebuješ více extends? V uvedeném případě nedává smysl ani jeden.

Registrace, login a administrace jsou odlišné činnosti. Zaslouží si samostatné třídy. Mohou však používat společnou třídu pro práci s databází uživatelů. Ani zde dědičnost nevyužiješ.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:500e:7140:8f68:cd4f...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr
~ Anonymní uživatel
19 příspěvků
4. 10. 2018   #15
-
0
-

#14 Kit
A jak ve třídě vytvořím vyjímku? Nšjak se mi to u php7 nedaří dohledat...

Nahlásit jako SPAM
IP: 185.193.86.–
Kit+14
Guru
4. 10. 2018   #16
-
0
-

#15 šnekr
Na vytvoření výjimky je nejen v PHP příkaz: 

throw new Exception("Chybová hláška");

Je to hodně variabilní. Můžeš si definovat vlastní výjimky třeba takto: 

class MyException extends Exception {
}

Můžeš doplnit i další nepovinné parametetry volání: Kód chyby a zřetězenou výjimku. Pro začátek se bez nich obejdeš.

Vše je popsáno v manuálu:

Výhodou výjimky je, že z ní můžeš vytáhnout hodně informací o tom, co a kde se stalo:

  • jméno výjimky
  • chybová hláška
  • jméno souboru, ve kterém k tomu došlo
  • číslo řádku
  • zřetězené výjimky
  • cokoliv, co si do toho doděláš. Třeba objekt s daty.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:6535:1ca6:118a:9001...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr
~ Anonymní uživatel
19 příspěvků
4. 10. 2018   #17
-
0
-

#16 Kit
No já nevim, není mi to moc sypatický :D

Nahlásit jako SPAM
IP: 185.193.86.–
Kit+14
Guru
4. 10. 2018   #18
-
0
-

#17 šnekr
Výjimky máš i ve svém příkladu. Hlavně tím oddělíš místo ošetření chyby od místa jejího vzniku. Systematické používání výjimek vede k tomu, že chyby zpracováváš mnohem důkladněji, než kdybys to měl přímo v toku programu. Práce s výjimkami je velmi pohodlná a hlavně nikdy nezapomeneš ošetřit chybový stav.

A ještě něco: Blok try..catch tam vůbec dávat nemusíš. Řádky 

    try {


    } catch (PDOException $e) {
        die('Connection failed: ' . $e->getMessage());
    }

můžeš vyhodit a ponechat jen ty dva uvnitř.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:65bc:4f8d:c2d2:385b...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr0
Newbie
5. 10. 2018   #19
-
0
-

#18 Kit
Takže principielně:

    function login($user, $pass) {
        $dotaz = $this->_db->prepare("SELECT id FROM users WHERE username = ? AND password = ?");
        $dotaz->execute(array($user, $this->hashPwd($pass)));
        
        if($dotaz->rowCount() > 0) {    //Vyfusnem min. 1 řádek, takze zadal login v poradku 
            $data = $dotaz->fetch();
            $this->setId($data["id"]);
        } else {
           //$this->writeError("Chybně zadané údaje!");
           throw new Exception("Chybne udaje!");
       
        }
    }
            if(isset($_POST["user"])) {
                $f_user = $_POST["user"];
                $f_pass = $_POST["pass"];
                try {
                    $user->login($f_user, $f_pass);    
                } catch (Exception $e){
                    echo $e->getMessage();
                }        
            }

je to v pořádku?

Funguje to, spíš mě zajímá, jestli se to takhle dělá i v praxi...

Nahlásit jako SPAM
IP: 93.99.138.–
peter
~ Anonymní uživatel
3414 příspěvků
12. 10. 2018   #20
-
0
-

Hele, session nebo post dej to jako parametr, treba do construct nebo promenne. Ale urcite s tim nepracuj uvnitr.

function ... (...)
{
if(isset($_POST["user"]))
}

vs
function ... (..., $post) // nebo jeste pouzivam $form, protoze vstupem mam formular z html
{
if(isset($post["user"]))
}

Nahlásit jako SPAM
IP: 2001:718:2601:258:39f6:5914:e731:14df...–
Kit+14
Guru
12. 10. 2018   #21
-
0
-

#19 šnekr
Dá se to napsat mnohem jednodušeji se stejným výsledkem: 

<?php
function login($user, $pass) {
    $dotaz = $this->_db->prepare("SELECT id FROM users WHERE username = ? AND password = ?");
    $dotaz->execute(array($user, $this->hashPwd($pass)));
    if ($dotaz->rowCount() == 0) {
        throw new Exception("Chybne udaje!");
    }
    $data = $dotaz->fetch();
    $this->setId($data["id"]);
}

if (isset($_POST["login"])) {
    $user->login($_POST["user"], $_POST["pass"]);    
}

Když budeš používat obrácené podmínky, tak ti zmizí spousta zbytečných "else". Všimni si, že jsem nepoužil isset() na políčko "user", ale na tlačítko "login". To ti umožní používání více tlačítek na jednom formuláři a také více funkcí pro stejný typ vstupů.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:7116:e8b9:1364:29bc...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr0
Newbie
15. 10. 2018   #22
-
0
-

#21 Kit
Jasný chápu - proč nepoužíváš try {} catch {}? Potom to vypíše tu vyjímku celou, vč souborua  podbně.... Já chci aby se zobrazila jen ta samotná hláška :-)

#20 peter
Npoužívám globální proměnné uvnitř...

Nahlásit jako SPAM
IP: 46.135.30.–
Kit+14
Guru
15. 10. 2018   #23
-
0
-

#22 šnekr
try .. catch používám. Začátečníci si však často stěžují, že jim to připadá nepřehledné a že starý způsob je jednodušší. Proto jim radím, ať to zkusí bez toho. Výsledek je podobný die(), ale je mnohem popisnější. Všimni si, že jsi vůbec netestoval, zda se správně provedlo připojení k databázi nebo zda SQL dotaz neselhal. Výjimky to udělaly za tebe. U prototypů bývá lepší, když je neošetříš - poskytne ti to cenné informace pro ladění.

V ostré aplikaci je naopak vhodné výjimky ošetřit.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:c01e:f95b:bfb6:90fa...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr0
Newbie
15. 10. 2018   #24
-
0
-

#23 Kit
s tím douhlasím, ale zrovna tam, kde chci vracet reálnou chybu (ne programovou) tak chci vypsat jen chybu - jako například, když se někdo registruje a je již zaregistrovaný mail...

Nahlásit jako SPAM
IP: 185.193.86.–
Kit+14
Guru
16. 10. 2018   #25
-
0
-

#24 šnekr
Však to už máš vyřešeno odchycením a vypsáním výjimky. Stačí jen místo "echo" zalogovat vně objektu třídy User.

Pokud bys chtěl logovat uvnitř, tak objekt $log injektuješ. Beze změny třídy User tak budeš moct definovat, zda a kam se bude logovat.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:4c36:7341:9518:4435...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr0
Newbie
24. 10. 2018   #26
-
0
-

Super, je to fajn, docela dobře se s tim pracuje, fakt dobrý! Souhlasim s každym kdo řekl že před oop to byla nuda :D

Mam další dotaz.... Řekněme třída, která spravuje firemní klienty, který řešení je lepší a proč? Přistupovat k údajům napřímo, nebo si dělat jednotlivé fukce set/get?

class Clients {
	private $_db;
	private $id;
	public $nazev;
	public $adresa;

	function __construct(PDO $_db, $id = 0) {
		$this->_db = $_db;
		if($id != 0) {
                  $this->id = $id;
		  $this->load();
                }
	}

	function load() {
		//funkce ktera natahne data z db a ulozi do nazev, adresa
	}

        function create() {
                //funkce vezme promenee adresa, nazev a ulozi do mysql jako novy row
        }
}

$klient = new Clients($db, $id);
echo $klient->nazev;
echo $klient->adresa;

$nk = new Clients($db);
$nk->nazev = "aaaa";
$nk->adresa = "bbbb";
$nk->create();


A nebo:

class Clients {
	private $_db;
	private $id;
	private $nazev;
	private $adresa;

	function __construct(PDO $_db, $id = 0) {
		$this->_db = $_db;
		if($id != 0) {
                  $this->id = $id;
		  $this->load();
                }
	}

	function load() {
		//funkce ktera natahne data z db a ulozi do nazev, adresa
	}

        function create() {
                //funkce vezme promenee adresa, nazev a ulozi do mysql jako novy row
        }
	function setNazev($s) {
		$this->nazev = $s;
	}
	function setAdresa($s) {
		$this->adresa = $s;
	}
	function getNazev() {
		return $this->nazev;
	}
	function getAdresa() {
		return $this->adresa;
	}
}

$klient = new Clients($db, $id);
echo $klient->getNazev();
echo $klient->getadresa();

$newklient = new Clients($db);
$newklient->setNazev = "aaaaa";
$newklient->setAdresa = "bbbb";
$newklient->create();
Nahlásit jako SPAM
IP: 46.135.14.–
Kit+14
Guru
24. 10. 2018   #27
-
0
-

#26 šnekr
První varianta je sice kratší, ale s tou bys neobstál. Druhá je sice delší, ale je používána. Jenže máš chybu v návrhu. $id nemá v konstruktoru co pohledávat, neboť tato třída se stará o práci s daty v databázi, nikoli o samotná data. Tvůj přístup se dá pojmenovat jako Active Record.

Pro práci s databází je však obvykle výhodnější Data Mapper, který tyto dvě role odděluje. Pro daný účel bych použil tohle: 

<?php

class Clients {
    private $db;

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

    function load($id) {
        // metoda, která natáhne data z db
        return (object) $data;
    }

    function create($newClient) {
        // metoda vezme proměnné adresa a nazev z $newClient a
        // uloží do MySQL jako nový záznam
    }
}

$clients = new Clients($db);
$data = $clients->load($id);
echo $data->nazev;
echo $data->adresa;

$newClient = array(
    'nazev' => "aaaa",
    'adresa' => "bbbb",
);
$clients->create($newClient);

Místo array bys mohl použít třídu stdClass, ale musel bys počítat s možným vedlejším účinkem. Data v $newClient jsou uvnitř metody create() chráněna, zatímco objekt třídy stdClass by chráněn nebyl.

Všimni si, že jsem objekt $clients použil dvakrát, nemusel jsem ho vytvářet znovu.

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Panda380
Newbie
24. 10. 2018   #28
-
0
-

#26 šnekr
Pozor chybka:

$newklient->setNazev = "aaaaa";
$newklient->setAdresa = "bbbb";

-->

$newklient->setNazev("aaaaa");
$newklient->setAdresa("bbbb");
Nahlásit jako SPAM
IP: 94.113.242.–
šnekr0
Newbie
24. 10. 2018   #29
-
0
-

#27 Kit
Dobře to s id dává smysl, chtěl jsem jen docílit toho, že se mi automaticky načtou data při volání třídy, když vím, že chci číst data podle id....

Takže rozumím li tomu správně, nemám si vytvářet proměnné jednotlivých dat uvnitř třídy ale přistupovat napřímo  pokud chci vkládat volat rovnou funkci na insert, pokud chci číst, čtu danné id... Mě se v tomhle ztrácí logika, na tohle přece nepotřebuju třídy a stačej mi obyčejné statické funkce?

Nahlásit jako SPAM
IP: 93.99.138.–
Kit+14
Guru
24. 10. 2018   #30
-
0
-

#29 šnekr
Kdysi jsem to zkoušel tak, jak popisuješ. Vedlo to k dlouhým a nepřehledným třídám. Jak víš, že budeš chtít číst a nebudeš chtít zapisovat? Navíc u tvého způsobu může dojít k nekonzistenci objektu, což je stav silně nežádoucí.

Jak bys toto chtěl řešit se statickými funkcemi? To by nebylo moc rozumné. Možná se statickými metodami, ale stejně bys musel pokaždé dávat databázi jako další parametr. Poněkud nepraktické. Takhle si voláním konstruktoru vytvoříš objekt s databází a druhým voláním provedeš operaci s daty. Nekonzistence se nekoná.

Uvnitř objektů se samozřejmě ukládají data, ale měla by spolu souviset. Databáze s uživatelem nesouvisí, proto by tyto objekty měly být oddělené. Viz SRP ze SOLID.

Nepleť si třídy s objekty a funkce s metodami. Jsou to rozdílné pojmy.

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Snekr
~ Anonymní uživatel
19 příspěvků
24. 10. 2018   #31
-
0
-

A co upravovani dat? Nactu si liadem ve do formulare tak zase poslat pole s datama? A co kdyz nechci dostat jeden radek z db ale vsechny? Jak se tohle resi?

Nahlásit jako SPAM
IP: 46.135.13.–
Kit+14
Guru
24. 10. 2018   #32
-
0
-

#31 Snekr

Nemusí to být tak složité, jak si možná myslíš. Přidání uživatele z formuláře? Trochu jsem upravil, zpracování, které běžně používám:

$clients = new Clients($db);
if (isset($_POST['Create'])) {
    $clients->create($_POST);
    header('Location: /Clients/');
    exit;
}
if (isset($_POST['Update'])) {
    $clients->update($_POST);
    header('Location: /Clients/');
    exit;
}
if (isset($_GET['List'])) {
    $data = $clients->list($_GET);
    echo $data;
    exit;
}
if (isset($_GET['Load'])) {
    $data = $clients->load($_GET);
    echo $data;
    exit;
}
Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr
~ Anonymní uživatel
19 příspěvků
25. 10. 2018   #33
-
0
-

#32 Kit
Tomu rozumím, mě spíš zajímá metoda jako taková... Ja vycucat víc řídků a předat to... Pole samotný? A pak to pres foreach vytáhnout?

Nahlásit jako SPAM
IP: 185.193.86.–
Kit+14
Guru
25. 10. 2018   #34
-
0
-

#33 šnekr
Jasně, máš přece metodu $select->fetchAll(); Přece to nebudeš tahat z databáze po jednom řádku.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:f576:4047:9d8d:2d02...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr0
Newbie
27. 10. 2018   #35
-
0
-

Díky moc Kite! Je to fajn, vážně je to příjemější práce :-)

Ještě prosím poradit - Když vracím z metody objekt fetchAll z pdo, jak si pak mám udělat vhodně cyklus na výpis? Nebo to mám raději vracet jako pole rovnou?

Nahlásit jako SPAM
IP: 185.193.86.–
Kit+14
Guru
27. 10. 2018   #36
-
0
-

#35 šnekr
Vracej to jako pole, protože zpracovat ho můžeš nejen přes foreach, ale také přes funkce array_*() nebo rovnou json_encode().

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
peter
~ Anonymní uživatel
3414 příspěvků
31. 10. 2018   #37
-
0
-

#22 šnekr
isset($_SESSION["loginId"]) - a to je co, kdyz ne globalni promenna? :)

Nahlásit jako SPAM
IP: 193.84.207.–
Kit+14
Guru
31. 10. 2018   #38
-
0
-

#37 peter
Tady to má jen pro ukázku. Supeglobální proměnné si také injektuji do objektů přes parametry.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:58f4:f44a:e18f:cb2d...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr0
Newbie
7. 11. 2018   #39
-
0
-

Přesně tak :)

Mám další otázku... Vynechme MVC, v tom momentálně dělat nechci. Je takopvý zápis v pořádku?

Třída:

class CalendarEvent {
    private $_db;
    function __construct(PDO $_db) {
        $this->_db = $_db;
    }
    
    function addEvent($name, $start, $end, $user, $text, $klient = 0) {
        $insertSql = "INSERT INTO calendar (nazev, start, end, user, klient, text) VALUES (?, STR_TO_DATE(?,'%d.%m.%Y-%H-%i'), STR_TO_DATE(?,'%d.%m.%Y-%H-%i'), ?, ?, ?)";
        $insert = $this->_db->prepare($insertSql);
        $insert->execute([$name, $start, $end, $user, $klient, $text]);
    }
    
    
    function getAll($user = null, $order = "id desc") {
        if($user) $where = "WHERE `user` = $user";
        else $where = "";
        
        $sqlSelect = "SELECT * FROM calendar $where order by $order";
        $select = $this->_db->prepare($sqlSelect);
        $select->execute();
        return $select->fetchAll();
    }
    
    function getEvent($id) {
        $sqlLoad = "SELECT * FROM calendar WHERE id = ?";
        $loadResult = $this->_db->prepare($sqlLoad);
        $loadResult->execute([$id]);
        $data = $loadResult->fetch();
        
        return (object) $data;        
    }
    
    function updateEvent($data, $id) {
        $sqlLoad = "UPDATE calendar SET nazev = ?, start = STR_TO_DATE(?,'%d.%m.%Y-%H-%i'), end = STR_TO_DATE(?,'%d.%m.%Y-%H-%i'), klient = ?, text = ? WHERE id = ?";
        $loadResult = $this->_db->prepare($sqlLoad);
        $loadResult->execute([$data["nazev"],$data["start"],$data["end"],$data["klient"],$data["text"],$id]);      
    }

    function removeEvent($id) {
        $sqlLoad = "DELETE from calendar WHERE id = ?";
        $loadResult = $this->_db->prepare($sqlLoad);
        $loadResult->execute([$id]);              
    }
}

Ten zápis metody add a edit je naschvál - zajímá mě, jestli je mezi tim v praxi rozdíl? Příjde mi totiž přehlednější to mít rovnou v deklaraci proměnných než to posílat jako pole (netbeans mi ukaze, jaky jsou dulezity parametry u metody, kdyz predavam pole, tak ne)

Add.php:

if(isset($_POST["calendar_add"])) {
    try {
        $calendar = new CalendarEvent($_db);
        $start = $_POST["start"]."-".$_POST["start_hh"]."-".$_POST["start_mm"];
        $end = $_POST["end"]."-".$_POST["end_hh"]."-".$_POST["end_mm"];
        
        $calendar->addEvent($_POST["name"], $start, $end, $_SESSION["loginId"], $_POST["text"] ,$_POST["klient"]);
        Messages::writeSucces("Done...", "index.php"]);
    } catch (Exception $ex) {
        Messages::writeError($ex->getMessage());
    }
}
FORM()....

Třídu messages neřešte, to je moje pomocná třída, která filtruje hlášky a případně vrací na index...

Vypis vsech eventů:

$calendar = new CalendarEvent($_db);
$calendarData = $calendar->getAll();

foreach($calendarData as $event) {
    echo $event["id"]." - ". $event["nazev"].....
    
}

1) Moje otázka je zase správnost zápisu

2) chci zeptat, nechci MVC - věci jako foreach ktery vypisujou mam delat rovnou tak kde se to zobrazuje, nebo si to nekde pripravit a v html pak jen <?= $vygenerovaneHTML ?>

3) Kdyz je to foreachAll(), jde docílit z toho aby každej row v cyklu byl jako objekt a né pole?

Nahlásit jako SPAM
IP: 185.193.86.–
Kit+14
Guru
8. 11. 2018   #40
-
0
-

#39 šnekr

  1. V podstatě to máš správně. Ještě to chce vytunit pojmenovávání objektů.
  2. Pokud používáš nějaký šablonovací systém, tak to umí vypsat.
  3. return $select->fetchAll(PDO::FETCH_OBJ);
  4. Ten "else" bych nahradil ternárním operátorem.
  5. Podtržítky bych šetřil. Maďarská notace je nešvar.

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
šnekr0
Newbie
8. 11. 2018   #41
-
0
-

#40 Kit
Díky,takže IF{} else{} za


if($user) $where = "WHERE `user` = $user" : $where = null;
 

Podívej se prosím ještě na metody add a edit, jsou tam odlišné zápisy předávání proměnných a psal jsem:

Ten zápis metody add a edit je naschvál - zajímá mě, jestli je mezi tim v praxi rozdíl? Příjde mi totiž přehlednější to mít rovnou v deklaraci proměnných než to posílat jako pole (netbeans mi ukaze, jaky jsou dulezity parametry u metody, kdyz predavam pole, tak ne)

Nahlásit jako SPAM
IP: 93.99.138.–
Kit+14
Guru
8. 11. 2018   #42
-
+1
-
Zajímavé

#41 šnekr
Těsně vedle 

$where = isset($user) ? "WHERE `user` = :user" : "";
  1. add...() - použil bych jeden parametr typu array. Netrápí mě, že to některá IDE nezvládají. Další možností je použití objektu, ale je to dost práce navíc a srozumitelnost kódu klesá. U objektu je ještě problém, že data nechrání před modifikací. Array předaný přes parametr je immutable.
  2. edit...() - kde tu metodu máš? Pokud máš na mysli update...(), tak tam také používám jediný parametr typu array. Klíč "id" do WHERE, ostatní položky jako data k modifikaci. Místo opisování názvů sloupců je jen filtruji a případně sanuji.

Nahlásit jako SPAM
IP: 2a00:1028:83a0:37a6:c84f:eaf:d3b7:8850...–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Zjistit počet nových příspěvků

Přidej příspěvek

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 176 hostů

Podobná vlákna

PHP OOP — založil Neony

PHP OOP začátečník — založil th

Mé dotazy na OOP v PHP — založil polonium

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032018 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý