Univerzální přidání do databáze – PHP – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Univerzální přidání do databáze – PHP – Fórum – Programujte.comUniverzální přidání do databáze – PHP – Fórum – Programujte.com

 

fix0
Stálý člen
2. 3. 2020   #1
-
0
-

Ahoj všem,

potřebuji skript, který přidá z $_GET parametrů data  do databáze.

Jak byste to prosím řešili v případě, že počet argumentů funkce na přidání do databáze bude pokaždé jiný počet.

Vstup: /pridajDataDoDatabaze.php?tabulka=nesmysly&houba=hrib&ovoce=merunka&zelenina=paprika&a libovolný počet dalších....

Vystup: INSERT INTO nesmysly (houba, ovoce, zelenina, a libovolný počet dalších ...)
VALUES (hrib, merunka, paprika, a libovolný počet dalších ...);

Děkuji všem za tipy, zatím mám jen toto:

$i = 0;
foreach ($_GET as $key => $value) {
    $($key) = $value;
    $i++;
}

function insert($tabulka, $sloupce($houba, $ovoce, $zelenina, ...)) {
    echo "INSERT INTO $tabulka (".$sloupce[0].", ".$sloupce[1].", ".$sloupce[2].", ...)
VALUES (".$houba.", ".$ovoce.", ".$zelenina.", ...);"

Nahlásit jako SPAM
IP: 31.30.172.–
peter
~ Anonymní uživatel
3619 příspěvků
2. 3. 2020   #2
-
0
-

Kolik nabizis? Min 500 kc/h za kazdou zapocatou hodinu, kdy se budeme zabyvat tvym problemem. Evidentne tve zminene reseni neni ani zacatkem reseni, takze to znamena cely problem vypracovat za tebe. To neni rada, to je placena prace.

1. Ty tipy, co zatim mas, jsou spatne. Pro kazdou web-services musis mit presne definovane podminky, jinak ti program/databazi hackeri znici. coz zakaznik nema moc rad, kdyz prijde o data.
Cili, mel bys mit definovane pole, seznam atributu, ktere do sql prikazu muzou jit. Pak bys upravil ten prvni cyklus tak, aby prochazel toto pole a sestavoval sql prikaz podle nalezenech atributu.

cyklus(attr as key)
isset($_GET[$key]) ? $keys[] = escapeSqlKey(key); $values[] = escapeSqlValue($_GET[$key])

2. Klidne muzes pouzit I pole v html, ale vysledek bude pro php stejny, musis mit seznam povolenych atributu

<input name=data[houba]>
cyklus(attr as key)
isset($_GET['data'][$key]) ? $keys[] = escapeSqlKey(key); $values[] = escapeSqlValue($_GET['data'][$key])

Nahlásit jako SPAM
IP: 2001:718:2601:258:4dbc:3838:5a25:f2e0...–
Kit+14
Guru
2. 3. 2020   #3
-
0
-

#2 peter
Hlavně je blbost pro vkládání do databáze používat metodu GET. Dělá to dost problémů - občas se data ztrácí, občas duplikují. K ukládání dat slouží metoda POST.

Univerzální insert jsem si napsal a zdaleka není tak zranitelný, jak píšeš. Jen je třeba používat prepared statements, abys nedostal tu hrůzu jako nahoře.

Ve své podstatě ani moc nemusíš kontrolovat názvy sloupců - dobře navržená databáze neplatný vstup odmítne. Určitě k tomu není potřebný žádný cyklus, jde to udělat mnohem elegantněji.

Souhlasím však s tím, že by uživatel neměl určovat, do které tabulky zapsat data. To bych nechal na aplikaci.

Nahlásit jako SPAM
IP: 94.112.251.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
fix0
Stálý člen
3. 3. 2020   #4
-
0
-

Má to sloužit jako vkladač dat do databáze, do které není povolen vzdálený přístup. Tento vkladač hlavně bude fungovat automaticky a bez frontendu, takže žádné HTML formuláře a POST nepřipadají v úvahu. Co se týká možných duplicit, to je fuk, databáze duplicity bude odmítat. Program tabulku podle dat určovat neumí, resp uměl by, kdybych tam musel definovat aby podle sady sloupců definoval tabulku sám, ale existují tabulky, které jsou podobné a v tom případě by to nefungovalo, je potřeba tomu skriptu poradit do jaké tabulky data má dát už v tom požadavku.

Děkuji za tipy.

Už asi vím jak na to, zkusím využít toto:


<?php
function takes_array($input)
{
    echo "$input[0] + $input[1] = ", $input[0]+$input[1];
}
?>
 

případně takto:


<?php
function add_some_extra(&$string)
{
    $string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>
 

Nahlásit jako SPAM
IP: 178.238.41.–
ondrej39+1
Věrný člen
3. 3. 2020   #5
-
+1
-
Zajímavé
Kit +

#4 fix
To že použiješ POST HTTP metodu vůbec neznamená, že musíš mít frontend a formuláře. POST požadavek jsi schopen provést i z příkazové řádky, akorát vstup nedáváš do URL, ale do těla požadavku, které je k tomu mnohem lépe přizpůsobeno. Pak už je rovnou ke zvážení, zda jako tělo nepoužít např. JSON, namísto textového řetězce.

Nahlásit jako SPAM
IP: 195.39.55.–
Inject all the dependencies!
peter
~ Anonymní uživatel
3619 příspěvků
4. 3. 2020   #6
-
+1
-
Zajímavé
fix +

fix - GET, Kit narazi na to, ze v prvni zprave pouzivas $_GET. GET metoda ma radu omezeni, napr. limit dat. To POST nema. A jsou s ni spojene ruzne dalsi problemy. Kit nejspis ma dojem, ze ne se vsemi si hrave poradis nebo je budes ignorovat a zpusobis si celou radu problemu.
Neni problem pouzit ajax request jako post, ikdyz nechces formular. To je uz na tobe.
Ten dalsi kod, co jsi poslal, nechapu vubec.

Nahlásit jako SPAM
IP: 2001:718:2601:258:4dbc:3838:5a25:f2e0...–
fix0
Stálý člen
6. 3. 2020   #7
-
0
-

No myslel sem, že ten kod my pomůže, ale asi ne. Cílem z GET proměnných vygenerovat SQL insert, nic víc.

Chápu to tak, že prepared statements nemohu použít protože dle get zadání je cílem pokaždé jiná tabulka, jiný počet a název sloupců, nevím jistě jak to funguje, ale třeba by šlo i tyhle prepare statements mít předdefinované podle tabulky, kam se data mají nahrávat.

Co se týká GET omezení, na to sem už narazil no, kdy mi to vyfailovalo pro velké množství předávaných dat, nicméně to mi nevadí, potřebuji to prostě přes GET (jinou možnost nemám duplicity a atomičnost nebo konzistence je zajištěna), tak mi to už rok funguje, akorát s tím, že pro každou tabulku musím mít zvlášť soubor nebo switch  v kodu, chtěl bych to zobecnit na obecnou funkci, která vezme GET požadavky a vygeneruje z nich SQL insert, já si s tím nějak poradím.

Už vím proč sem poslal ten kod, umím už všechny GET proměnné šoupnout do array a tu array předat funkci, teď už jen formuluji nějaký mechanismus, který z toho pole vytvoří SQL insert.

Nahlásit jako SPAM
IP: 31.30.172.–
peter
~ Anonymní uživatel
3619 příspěvků
6. 3. 2020   #8
-
+1
-
Zajímavé
fix +

Hm, to je jiste uzasne, nicmene potrebujes mit seznam povolenych atributu, jinak ti to snadno hacker napadne. A vyloucis tim nezadouci nazvy. A pak z te array muzes sestavit i sql prikaz pro prepare statement.
A slo to napsat i takhle: 

foreach ($_GET as $key => $value) {
    $$key = $value;
}

Ale, to nema podle mne s problemem nic spolecneho. Stale cekame na nejaky kod, se kterym prijdes, ktery bude aspon trochu pripominat vytvareni dotazu. Neco takoveho...
google = dynamic columns sql query php pdo prepare statement
... hm, tak bude treba pouzit jina slova :) 

// google = php array keys to string
implode(", ", array_keys($array));

// google = php array values to string
implode(", ", array_values($array));
implode(", ", $array);
json_encode(array);
serialize(array);

Kazdopadne bys to mel osetrit, jak sql key, tak sql value nez to z implodujes.

 https://www.php.net/manual/en/pdo.prepare
Jestli to spravne chapu, tak muzes bindovat kazdy parametr zvlast, jen si musis vygenerovat z array_keys ten sql dotaz.

<?php
$var="User', email='test";
$a=new PDO("mysql:host=localhost;dbname=database;","root","");
$b=$a->prepare("UPDATE `users` SET user=:var");
$b->bindParam(":var",$var);
$b->execute();
?>

https://www.php.net/manual/en/pdostatement.bindparam

// Example #1 Execute a prepared statement with named placeholders

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>

Mozna bys mel zacit prohlizet i dokumentaci. Da se z ni vytahnout nekolik zajimavych konstrukci. Neni problem si dohledat v ni funkce, ktere neznas a podivat se na example, co ma funkce na vstupu a co s tim udela. Obcas to tam vypisuji. Ja osobne pouzivam to vlastni escapovani, jak jsem psal. Kit ti mohl to bind najit, on je na to expert, kdyz se mluvi o pdo.

Nahlásit jako SPAM
IP: 2001:718:2601:258:4dbc:3838:5a25:f2e0...–
fix0
Stálý člen
30. 4. 2020   #9
-
0
-

Já sem hold takový amatérský šmelař. Všechno mi nějak funguje, ale správnou cestou to určitě nikdy nedělám. :-D PDO obcházím, jak velkého vzteklého psa. Funguji stylem, nezahlcovat si hlavu novými věcmi, když to jde jednoduše špatnou cestou. Tím myslím i prepare statements, vím k čemu jsou dobré a v čem je jejich síla, ale nechápu jak v mém případě mohou fungovat, ale to je jedno, tohle je zrovna věc, kterou bych pořádně chtěl mít, jakmile budu mít čas, tak se s tím zkusím nějak poprat. Pokud jsou ale tvé myšlenky špatně nebo nefunkční, pochybuji, že to nějak dám do kupy pro můj případ. :-D Ale zkusím to při nejhorším to udělám styl nejvetsi noob /toDB.php?sloupec1nazev=id&sloupec1data=&sloupec2nazev=entita&sloupec2data=<nazev entity>&sloupec3nazev=element&sloupec3data=<nazev elementu> apod. :-Dsice to přidá trochu délku URL, ale nic závratného, ale věřím, že tvá kontrukce implode to array by použít šla, jen nevím či se mi podaří to PDO bindování a prepared statements, ale zkusím to. Zatím děkuji moc všem.

Nahlásit jako SPAM
IP: 92.240.177.–
ondrej39+1
Věrný člen
30. 4. 2020   #10
-
0
-

#9 fix
Spíš než ten formát, co jsi napsal, t.j. sloupec1nazev=id&sloupec1data=10 je mnohem lepší použít kombinaci kdy název query atributu určuje název sloupce a hodnota query atributu je hodnota kterou chceš vložit do daného sloupce. Takový zápis se ti pak krásně smrskne na id=10. :)

Nahlásit jako SPAM
IP: 78.45.199.–
Inject all the dependencies!
fix0
Stálý člen
30. 4. 2020   #11
-
0
-

Jo už blbnu, však sem si to už udělal, aby to tak fungovalo to je to:

foreach ($_GET as $key => $value) {
    $$key = $value;
}

Prepared statements, jestli dobře chápu, tak použít v mém případě nelze. Zabezpečit nějak by to asi chtělo, ale podle mě inijection by jít nemuselo, případně ty vstupy můžu asi ošetřit obalením nějaké příslušné funkce, podle mě tím nebudu posílat taková data, aby to tomu nějak vadilo. Navíc, aby to hacker mohl napadnout, tak by hádám potřeboval znát název databáze, jinak bude zpracování dotazu failovat.

No zatím mám toto, což funguje:

Vstup: ?tabulka=tablename&test=data&test2=data2&test3=data3

Výstup: INSERT INTO test (test,test2,test3,) VALUES (data,data2,data3,)

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

/*$keys=array();
$values=array();*/

$totalKeys = "";
$totalValues = "";

$i = 0;	
foreach ($_GET as $key => $value) {
    $$key = $value;

	if($i > 0) {
		$totalKeys .= $key . ",";
		$totalValues .= $value . ",";
	}
	
	$i++;
	/*array_push($keys,$key);
	array_push($values,$value);*/
}

/*echo "Klíče: " . $totalKeys;
echo "<br>Values: " . $totalValues;*/

/*print_r($keys);
print_r($values);*/

$keys = explode(",", $totalKeys);
$table = $keys[0];

$sql = "INSERT INTO $table ($totalKeys)
VALUES ($totalValues)";

/*
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} 

if ($conn->query($sql) === TRUE) {
    echo "New record created successfully";
} else {
    echo "Error: " . $sql . "<br>" . $conn->error;
}

$conn->close();
*/

?>




Nahlásit jako SPAM
IP: 92.240.177.–
Kit+14
Guru
1. 5. 2020   #12
-
0
-

#11 fix
Blbneš. Nevkládej data přes GET, nebo se z toho zblázníš.

Prepared statements můžeš použít kdykoli. Ovšem pouze na data.

Nahlásit jako SPAM
IP: 213.175.43.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
peter
~ Anonymní uživatel
3619 příspěvků
1. 5. 2020   #13
-
0
-

Tady pouziva jakysi pdo wrapper, cili nejakou pomocnou class, kde nesejde formatuje pole na serii sloupec=value pro insert i update, takze asi to jde, co tvrdis, ze nejde ve tvem pripade

https://www.itnetwork.cz/programovani/sql/diskuzni-forum-sql-mysql-mssql-postgresql-sqlite-databaze/odpojeni-od-databaze-a-pripojeni-k-druhe-5ea7e57ed84d6

<?php

/**
 *             __          __                __
 *        ____/ /__ _   __/ /_  ____  ____  / /__ _________
 *       / __  / _ \ | / / __ \/ __ \/ __ \/ //_// ___/_  /
 *      / /_/ /  __/ |/ / /_/ / /_/ / /_/ / ,< _/ /__  / /_
 *      \__,_/\___/|___/_.___/\____/\____/_/|_(_)___/ /___/
 *
 *
 *      TUTORIÁLY  <>  DISKUZE  <>  KOMUNITA  <>  SOFTWARE
 *
 *      Tento zdrojový kód je součástí tutoriálů na programátorské
 *      sociální síti WWW.DEVBOOK.CZ
 *
 *      Kód můžete upravovat jak chcete, jen zmiňte odkaz
 *      na www.devbook.cz :-)
 *
 *  Jednoduchý databázový wrapper nad PDO
 */
class Db
{
        /**
         * @var PDO Databázové spojení
         */
        private static $connection;

        /**
         * @var array Výchozí nastavení ovladače
         */
        private static $options = array(
                PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
                PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
                PDO::ATTR_EMULATE_PREPARES => false,
        );

        /**
         * Připojí se k databázi pomocí daných údajů
         * @param string $host Název hostitele
         * @param string $database Název databáze
         * @param string $user Uživatelské jméno
         * @param string $password Heslo
         */
        public static function connect($host, $database, $user, $password)
        {
                if (!isset(self::$connection)) {
                        $dsn = "mysql:host=$host;dbname=$database";
                        self::$connection = new PDO($dsn, $user, $password, self::$options);
                }
        }

        /**
         * Spustí dotaz a vrátí PDO statement
         * @param array $params Pole, kde je prvním prvkem dotaz a dalšími jsou parametry
         * @return \PDOStatement PDO statement
         */
        private static function executeStatement($params)
        {
                $query = array_shift($params);
                $statement = self::$connection->prepare($query);
                $statement->execute($params);
                return $statement;
        }

        /**
         * Spustí dotaz a vrátí počet ovlivněných řádků. Dále se předá libovolný počet dalších parametrů.
         * @param string $query Dotaz
         * @return int Počet ovlivněných řádků
         */
        public static function query($query) {
                $statement = self::executeStatement(func_get_args());
                return $statement->rowCount();
        }

        /**
         * Spustí dotaz a vrátí z něj první sloupec prvního řádku. Dále se předá libovolný počet dalších parametrů.
         * @param string $query Dotaz
         * @return mixed Hodnota prvního sloupce z prvního řádku
         */
        public static function querySingle($query) {
                $statement = self::executeStatement(func_get_args());
                $data = $statement->fetch();
                return $data[0];
        }

        /**
         * Spustí dotaz a vrátí z něj první řádek. Dále se předá libovolný počet dalších parametrů.
         * @param string $query Dotaz
         * @return mixed Pole výsledků nebo false při neúspěchu
         */
        public static function queryOne($query) {
                $statement = self::executeStatement(func_get_args());
                return $statement->fetch(PDO::FETCH_ASSOC);
        }

        /**
         * Spustí dotaz a vrátí všechny jeho řádky jako pole asociativních polí. Dále se předá libovolný počet dalších parametrů.
         * @param string $query Dotaz
         * @return mixed Pole řádků enbo false při neúspěchu
         */
        public static function queryAll($query) {
                $statement = self::executeStatement(func_get_args());
                return $statement->fetchAll(PDO::FETCH_ASSOC);
        }

        /**
         * Umožňuje snadné vložení záznamu do databáze pomocí asociativního pole
         * @param string $table Název tabulky
         * @param array $data Asociativní pole, kde jsou klíče sloupce a hodnoty hodnoty
         * @return int Počet ovlivněných řádků
         */
        public static function insert($table, $data) {
                $keys = array_keys($data);
                self::checkIdentifiers(array($table) + $keys);
                $query = "
                        INSERT INTO `$table` (`" . implode('`, `', $keys) . "`)
                        VALUES (" . str_repeat('?,', count($data) - 1) . "?)
                ";
                $params = array_merge(array($query), array_values($data));
                $statement = self::executeStatement($params);
                return $statement->rowCount();
        }

        /**
         * Umožňuje snadnou modifikaci záznamu v databázi pomocí asociativního pole
         * @param string $table Název tabulky
         * @param array $data Asociativní pole, kde jsou klíče sloupce a hodnoty hodnoty
         * @param string $condition Řetězec s SQL podmínkou (WHERE)
         * @return mixed
         */
        public static function update($table, $data, $condition) {
                $keys = array_keys($data);
                self::checkIdentifiers(array($table) + $keys);
                $query = "
                        UPDATE `$table` SET `".
                        implode('` = ?, `', array_keys($data)) . "` = ?
                        $condition
                ";
                $params = array_merge(array($query), array_values($data), array_slice(func_get_args(), 3));
                $statement = self::executeStatement($params);
                return $statement->rowCount();
        }

        /**
         * Vrátí poslední ID posledního záznamu vloženého pomocí INSERT
         * @return mixed Id posledního záznamu
         */
        public static function getLastId()
        {
                return self::$connection->lastInsertId();
        }

        /**
         * Ošetří string proti SQL injekci
         * @param string $string Řetězec
         * @return mixed Ošetřený řetězec
         */
        public static function quote($string)
        {
                return self::$connection->quote($string);
        }

        /**
         * Zkontroluje, zda identifikátory odpovídají formátu identifikátorů
         * @param array $identifiers Pole identifikátorů
         * @throws \Exception
         */
        private static function checkIdentifiers($identifiers)
        {
                foreach ($identifiers as $identifier)
                {
                        if (!preg_match('/^[a-zA-Z0-9\_\-]+$/u', $identifier))
                                throw new Exception('Dangerous identifier in SQL query');
                }
        }
}
Nahlásit jako SPAM
IP: 193.84.197.–
Kit+14
Guru
1. 5. 2020   #14
-
0
-

#13 peter
Problém je v tom, že ta třída je z velké části blbě a přitom úplně zbytečně. Začal bych odstraněním všech "static", neboť tohle slovo dokáže z každé třídy udělat paskvil.

Nahlásit jako SPAM
IP: 46.135.31.–
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

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×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, 22 hostů

 

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