PHP SQL volání databaze z funkce

PHP SQL volání databaze z funkce
« kdy: 03. 11. 2020, 15:59:02 »
Mam subor core kde je nieco taketo
Kód: [Vybrat]
$mysqli = new mysqli("localhost","root","vertrigo","project");
ak spravim include v inom subore tak mi v pohode funguje
Kód: [Vybrat]
$sql = "SELECT * FROM `test_db`";
$result = $mysqli->query($sql);
ale preco mi to nefunguje pre funkciu?
Kód: [Vybrat]
function calculate($lineID){
 
    $query = "SELECT * FROM `test_db` where id=$lineID";
    $result = $mysqli->query($query) or die(mysql_error());
    $row = $result->fetch_assoc();
    ...
vypisuje Undefined variable: mysqli in ....
co robim zle? to musim pre kazdu funkciu pridavat $mysqli = new mysqli("localhost","root","vertrigo","project");?
« Poslední změna: 03. 11. 2020, 16:05:04 od Petr Krčmář »


McFly

  • *****
  • 560
    • Zobrazit profil
    • E-mail
Re:PHP SQL volání databaze z funkce
« Odpověď #1 kdy: 03. 11. 2020, 16:11:56 »
Pred radek $query =... bych dal radek global $mysqli;

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:PHP SQL volání databaze z funkce
« Odpověď #2 kdy: 03. 11. 2020, 16:24:18 »
Pred radek $query =... bych dal radek global $mysqli;

Global? Fuj!

Je třeba předat $mysqli té funkci v parametrech.

Re:PHP SQL volání databaze z funkce
« Odpověď #3 kdy: 03. 11. 2020, 19:15:56 »
to bude mrzení.
Děkuji za možnost editace příspěvku.

Re:PHP SQL volání databaze z funkce
« Odpověď #4 kdy: 04. 11. 2020, 09:18:09 »
uz je rok 2020, OOP zvlada aj php.


Re:PHP SQL volání databaze z funkce
« Odpověď #5 kdy: 04. 11. 2020, 21:19:39 »
Osobně radši používám PDO než mysqli, ale obojí je možné.
https://www.php.net/manual/en/book.pdo.php

Z hlediska bezpečnosti bys měl používat předpřipravené SQL příkazy, jinak ti to někdo lehce může hacknout a vytáhnout data nebo ti smazat databázi.
https://www.w3schools.com/sql/sql_injection.asp
https://www.w3schools.com/php/php_mysql_prepared_statements.asp

A jinak PHP je OOP, tak zkus víc zapojit třídy. Třeba DB wrapper. Něco pro inspiraci:
https://www.itnetwork.cz/php/mvc/objektovy-mvc-redakcni-system-v-php-pdo-crud-wrapped

pak třeba napíšeš:
Kód: [Vybrat]
$db = new Db();
$result = $db->select("SELECT * FROM `test_db` where id=:id",array(":id" => $lineID));

Nevím co píšeš za projekt, ale taky jedna možnost je všechno směřovat zkrz centrální index.php a dynamicky přikládat další php soubory dle potřeby.
A taky používat autoloader tříd (viz spl_autoload_register):
https://www.php.net/manual/en/function.spl-autoload-register.php

Pak nemusíš všude dávat např. include (cesta_k_php_třídě);, ale rovnou vytvoříš nový objekt,např: $db = new DB(); a autoloader ten include udělá sám.

Sice to není přímo odpověď na tvůj dotaz, ale můžeš se tím inspirovat. :-)

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:PHP SQL volání databaze z funkce
« Odpověď #6 kdy: 04. 11. 2020, 23:03:10 »
Kód: [Vybrat]
$db = new Db();
$result = $db->select("SELECT * FROM `test_db` where id=:id",array(":id" => $lineID));

Mně se takový wrapper jeví jako nešikovný. Raději si to napíši jako poctivé 3-4 řádky
Kód: [Vybrat]
$db = new PDO(...);
$sql = "SELECT * FROM `test_db` where id=:id";
$select = $db->prepare($sql);
$select->execute(array("id" => $id));
$result = $select->fetchAll();
A důvod? Každá z těch metod má mnoho volitelných parametrů, pomocí kterých se dá nahradit mnoho vlastností, na které se často používá ORM. Snažit se to natřískat do jednoho wrapperu je cestou do pekel. Navíc se takový prepared statement dá použít opakovaně, což ten wrapper neumí.

V neposlední řadě se to i dobře testuje.

Je ale fakt, že několik wrapperů používám, např.
Kód: [Vybrat]
$db = new MyPDO($config);
$id = $db->insert('User', ['name' => "Kit", 'type' => "admin"]);
Ovšem jak je vidět, tvorba SQL je už zcela ukryta uvnitř. Pokud bych chtěl wrapper na uvedený případ, vypadal by asi takto:
Kód: [Vybrat]
$data = $db->select('test_db', ['id' => $id]);
Ovšem má to spoustu much - například chybí seznam sloupců, jejich přejmenování, není z toho patrné, zda chci pole, dict, anonymní objekt nebo objekt nějaké třídy - prostě to není ono. Pokud bych to chtěl podchytit všechno, bude ovládání složitější, než napsání SQL a stejně to bude umět jen jednoduché dotazy.

Re:PHP SQL volání databaze z funkce
« Odpověď #7 kdy: 05. 11. 2020, 09:50:29 »
Asi jsem dal špatný příklad na ten wrapper, radši jsem to měl vypsat sám. Myslel jsem to jako třídu, kde máš obecné funkce. Nezadáváš tam natvrdo SQL příkazy, jen obaluješ funkcionalitu.

Takže budeš mít např:
Kód: [Vybrat]
class Db {
protected $pdo;
protected $statement;
        protected $error;
   
public function __construct() {
try{
$this->pdo = new PDO(DB_DSN . ";dbname=" . DB_NAME .";charset=utf8", DB_USER, DB_PASS));
} catch(Exception $ex){
die("Nelze se spojit s databází!");
}
}

public function select($query,$data) {
try {
$this->statement = $this->pdo->prepare($query);
if ($this->statement->execute($data)) {
return $this->statement->fetchAll();
}
} catch (Exception $e) {
$this->error = $e->getMessage();
}
return null;
}
}

Pak pomocí $db = new Db(); vytvoříš nové spojení s databází
a dotaz provedeš jako $db->select("select * from X where id = :id",array(":id" => $id));
Tedy můžeš vkládat jakkoliv složité sql dotazy a data k nim, není to nijak omezené.

Výhoda je, že nemusíš všude vypisovat to připravování dotazů, jen zavoláš příslušnou funkci. Těch funkcí si tam dáš kolik potřebuješ...minimálně jednu další pro insert/update.
« Poslední změna: 05. 11. 2020, 09:52:12 od frantaN49 »

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:PHP SQL volání databaze z funkce
« Odpověď #8 kdy: 05. 11. 2020, 15:36:09 »
K čemu tam máš try...catch? Výjimky nechávám probublat výš právě proto, abych nemusel použít die(). Pokud něco zachytávat, tak PDOException, ale co s ním chceš dělat v takto obecné metodě, kde se ta chyba ani nedá sémanticky popsat? Jedině zanořit do řetězené výjimky.

Nechápu ten return null; na konci. To jako fakt? Na výstupu nečekám null, ale data.

Re:PHP SQL volání databaze z funkce
« Odpověď #9 kdy: 05. 11. 2020, 19:01:36 »
Dobre skusme na to ist easy.
Takze mam jeden file kde chcem volat dbconnector.php donho som napchal toto a potom tam napcham query,select,ect..
Kód: [Vybrat]
class DbConnectors extends SystemComponent {
    function DbConnector(){

        // Load settings from parent class
        $settings = SystemComponent::getSettings();

        // Get the main settings from the array we've just loaded
        $host = 'localhost';
        $db   = 'T';
        $user = 'x';
        $pass = 'y';
        $conninfo = array('Database'=>$db,'UID'=>$user,'PWD'=>$pass, 'CharacterSet'=>"UTF-8",'ReturnDatesAsStrings'=>true);
        $connectionInfo = array( "Database"=>$db, "UID"=>$user, "PWD"=>$pass);
        // Connect to the database
        $link = sqlsrv_connect($host, $conninfo);
       
        //register_shutdown_function(array(&$this, 'close'));
    }
potom mam subor funkcia kde chcem napriklad volat funkciu
Kód: [Vybrat]
<?php
//Include
require_once('DbConnector.php');
function 
select_test(){
    
$connector = new DbConnectors();
    
$sql "SELECT TOP 10 [data] FROM [test].[dbo].[report] WHERE [Station]= 'xyz' ";

    
$stmt sqlsrv_query$connector$sql );
ale to mi nefunguje. Preco? Ako by som mal korektne volat spojenie na db?

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:PHP SQL volání databaze z funkce
« Odpověď #10 kdy: 05. 11. 2020, 19:14:12 »
Co znamená "nefunguje"? Nějaké chybové hlášení by nebylo?

Re:PHP SQL volání databaze z funkce
« Odpověď #11 kdy: 05. 11. 2020, 20:47:11 »
Kód: [Vybrat]
Array ( [0] => Array ( [0] => IMSSP [SQLSTATE] => IMSSP [1] => -14 [code] => -14 [2] => An invalid parameter was passed to sqlsrv_query. [message] => An invalid parameter was passed to sqlsrv_query. ) )resp.
Kód: [Vybrat]
Warning: sqlsrv_query() expects parameter 1 to be resource, object givenpritom ten isty kod mam inom subore kde je rovno s connectom a tam to funguje ok
« Poslední změna: 05. 11. 2020, 20:50:02 od Wangarad »

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:PHP SQL volání databaze z funkce
« Odpověď #12 kdy: 05. 11. 2020, 21:07:44 »
To bude asi tím, že v $connector nemáš DB resource, ale objekt třídy DbConnector.

Místo toho posledního řádku bych dal
Kód: [Vybrat]
$stmt = $connector->query($sql);

a do třídy DbConnector dopsal metodu
Kód: [Vybrat]
function query($sql) {
    return sqlsrv_query($this->link, $sql);
}

Konstruktor DbConnector přejmenuj na __construct a poslední řádek v něm nahraď
Kód: [Vybrat]
$this->link = sqlsrv_connect($host, $conninfo);

Re:PHP SQL volání databaze z funkce
« Odpověď #13 kdy: 06. 11. 2020, 11:04:28 »
K čemu tam máš try...catch? Výjimky nechávám probublat výš právě proto, abych nemusel použít die()...
Tak udělat to jde různě. Nechci se s vyjímkama zabývat dále, tak chybu zachytím tady a chybu zapíšu do proměné $error, či do nějakého logu. U funkce pro update se navíc udělá rollback.

Null se vrací pokud došlo k té zachycené chybě, aby bylo jasné, že došlo k chybě (jinak by se provedl ten první return a vrátily se data).
Někde dál v kódu tak můžu mít:
if (!empty($result)) { zobraz data } else { napiš uživateli že došlo k chybě, ať někoho zavolá... } nebo podobně (if result not null...).

Try, catch a die v konstruktoru mám proto, že pokud nepůjde databáze, tak uživatel v mé aplikaci nic neudělá a můžu si dovolit to takhle celé zaříznout. Nejspíš by pak bylo potřeba restartovat celý server.

Je to příklad pro inspiraci. Každý ať si to dělá tak, jak mu to pro daný projekt vyhovuje.

Kit

  • *****
  • 704
    • Zobrazit profil
    • E-mail
Re:PHP SQL volání databaze z funkce
« Odpověď #14 kdy: 06. 11. 2020, 11:46:55 »
Někde dál v kódu tak můžu mít:
if (!empty($result)) { zobraz data } else { napiš uživateli že došlo k chybě, ať někoho zavolá... } nebo podobně (if result not null...).

Takový kód už nepotřebuji právě proto, že výjimka to přeskočí a if by bylo zbytečné, včetně else. Právě zde najde využití blok try...catch.
Kód: [Vybrat]
try {
    $result = $db->select($sql);
    // zobraz data
} catch (Exception $e) {
    // napiš uživateli že došlo k chybě $e, ať někoho zavolá
}
Všimni si, že v $e mám stále kompletní popis chyby i s uvedením místa, kde vznikla. Samozřejmě takové hlášení nepatří uživateli, ale do logu.