Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: wyrażenia regularne - parsowanie zapytan mysql'a
Forum PHP.pl > Forum > PHP
ppp
witam,
potrzebowałbym jakiejs sugestii jak sparsować dowolne (no może nie do końca dowolne bo selecta) zapytanie do mysqla tak zeby móc do niego dolozyc jakis warunek dodatkowy.
Powiedzmy ze mam takie zapytania
  1. <?php
  2. $sql = "select * from table where field1 = 'value'";
  3. $sql2 = "select * from table left join table2 on table.id=table2.table_id";
  4. $sql3 = "select * from table order by field1 desc";
  5. $sql4 = "select * from table where (field1 = 'value1' or field2 = 'value2) group by field3";
  6. ?>

i do wszystkich chcialbym dolozyc warunek field3='value3' zeby bylo
  1. <?php
  2. $sql = "select * from table where field1 = 'value' and field3='value3'";
  3. $sql2 = "select * from table left join table2 on table.id=table2.table_id where fiel
    d3='value3'"
    ;
  4. $sql3 = "select * from table where field3='value3' order by field1 desc";
  5. $sql4 = "select * from table where (field1 = 'value1' or field2 = 'value2) and field3='value3' group by field3";
  6. ?>

mam nadzieje ze wiadomo o co chodzi.
vtuner
Najlepiej napisz sobie funkcje np.

  1. <?php
  2. function db_select($jakiePola, $tabela, $where=NULL, $order=NULL, $group=NULL, $limit=NULL)
  3. {
  4. return 'select ' . $jakiePola . ' from ' . $tabela . ' ' . ((!is_null($where)) ? 'WHERE ' . $where : '') . ' ' . ((!is_null($order)) ? 'ORDER BY ' . $order : '') . ' ' . ((!is_null($group)) ? 'GROUP BY ' . $group : '') . ' ' . ((!is_null($limit)) ? 'LIMIT ' . $limit : '') . 
  5. }
  6. ?>


Oczywiście to jest przykład bardzo prostej, ale masz możliwość dowolnej manipulacji różnych wartości w zapytaniu.

PS: Pisane z głowy więc mogą być błędy.
ppp
Dzieki za pomoc ale to mi raczej nie pomoże. Może napisz dokładniej o co chodzi. Cały system połaczeń i obsługi bazy danych mam już zrobiony (przerabiam sklep internetowy na opencart oparty) i gdybym chciał dołożyć taka fukcje to musialby bym sie niezle napocic przy przepisywaniu tego kodu. Dlatego wydaje mi sie ze najprostszym rozwiazaniem byloby w jakis sposob sparsowac te zapytania i podokladac ten warunek tam gdzie jest mi potrzebny.
vtuner
A czy obsługujesz bazę danych przez własną klasę czy wbudowane funkcje PHP?
ppp
baza danych obslugiwana jest przez osobna klase tyle ze zapytania w tej klasie nie sa obslugiwane w sposob o ktorym pisales poprzednio ale w calosci sa wysylane do metody ktora je wywoluje
  1. <?php
  2. function query($sql) {
  3. // addScope to jest funkcja ktora ma dolozyc dodatkowy warunek na kazde zapytanie  
  4. $sql = $this->addScope($sql);
  5. $this->result = mysql_query($sql); 
  6. if (!$this->result) {
  7. exit('Error: ' . mysql_error() . '<br />Error No: ' . mysql_errno() . '<br />' . $sql);
  8. } else {
  9. return $this->result;
  10. }
  11. }
  12. ?>

jak na razie udalo mi sie uzyskac to co chcialem uzywajac preg_split po slowach kluczowych MySQL'a (where, order by, group by etc.) i skladajac to pozniej do kupy juz po swojemu, wyglada to tak
  1. <?php
  2. function addScope($sql) {
  3. $value = "someValue"; //wartosc dodatkowego warunku
  4. // sprawdza czy zapytanie to select i wybiera nazwe przeszukiwanej tabeli i jej al
    iasu, poki co zakladam ze to jest zapis bez 'AS' i ma 1 do 3 znakow
  5. if (preg_match('/^select.*froms+(S+)(s+S{1,3}s)?.*$/',trim($sql),$table)) {
  6. $query = preg_split('/(where|group by|order by|limit)/',$sql,-1,PREG_SPLIT_DELIM_CAPTURE);
  7. $sql = "";
  8. $updated = false; //czy juz dolozony jest warunek
  9. $closePar = false; //czy nawias zostal zamkniety
  10. foreach ($query as $queryPiece) {
  11. //$this->sqlKeywords - zawiera slowa kluczowe MySQL'a po ktorych robie splita
  12. if (in_array($queryPiece,$this->sqlKeywords)) {
  13. if ($updated) {
  14. $sql .= (($closePar) ? ") " : "").$queryPiece;
  15. $closePar = false;
  16. } else {
  17. $sql .= " where ".(isset($table[2]) ? trim($table[2])."." : "")."field3 = '".$value."' ";
  18. $sql .= ($queryPiece == 'where') ? " and (" : $queryPiece;
  19. $closePar = ($queryPiece == 'where') ? true : false;
  20. }
  21. $updated = true;
  22. } else {
  23. $sql .= $queryPiece;
  24. }
  25. }
  26. if ($closePar) {
  27. $sql .= ")";
  28. }
  29. if (!$updated) {
  30. $sql .= " where ".$table[1].".field3 = '".$value."' ";
  31. }
  32. }
  33. }
  34. ?>

moze ktos ma jakis pomysl jak to zrobic lepiej czy jasniej bo sam kod specjalnie czytelny mi sie nie wydaje. Przykladowo da takiego zapytania:
select distinct ug.permission from user u left join user_group ug on u.user_group_id = ug.user_group_id where u.user_id = '3'

dostaje:
select distinct ug.permission from user u left join user_group ug on u.user_group_id = ug.user_group_id where u.field3 = 'someValue' and ( u.user_id = '3')
Kicok
1. Szukasz" /\\swhere\\s/i przy pomocy preg_match" title="Zobacz w manualu PHP" target="_manual
- Jeśli znalazłeś, to dodajesz zaraz za nim: " ( field3 = 'value3' ) AND "

2. Jeśli nie znalazłeś, to szukasz pierwszego wystąpienia tego wzorca: /\\s(group|order|limit)\\s/i. Wstaw sobie tutaj wszystkie słowa kluczowe jakie mogą wystąpić PO WHERE. Listę oraz KOLEJNOŚĆ (ważne!) znajdziesz w manualu na mysql.com
- Jeśli znalazłeś, to dodajesz zaraz przed tym: " WHERE ( field3 = 'value3' ) "

3. Jeśli nie znalazłeś, to dodajesz na końcu zapytania: " WHERE ( field3 = 'value3' )"



Żeby rozwiązanie było w pełni profesjonalne, to trzeba by jeszcze odsiać wystąpienia WHERE, GROUP, ORDER,... w podzapytaniach, komentarzach, apostrofach, odwróconych apostrofach i byćmoże cudzysłowu. Jednak myślę, że na twoje potrzeby wystarczy to co jest powyżej ;]
ppp
dzieki za pomoc, powinno wystarczyc. Problem jest tylko z punktem pierwszym.
Cytat
1. Szukasz" /\\swhere\\s/i przy pomocy [manual\]preg_match\[/manual\]
- Jeśli znalazłeś, to dodajesz zaraz za nim: " ( field3 = 'value3' ) AND "

dokladanie warunkow w ten sposob powoduje ze jezeli w dalszej czesci zapytania jest np: "field1 = 'value1' OR field2 = 'value2'" to ten dodatkowy warunek nie ma zadnego znaczenia. Dlatego dokladam nawiasy na te warunki ktore juz mam w zapytaniu.
co do rekurencji w zapytaniach zeby przeszukac ewentualne selecty w nim zawarte, to jak na razie nie jest mi potrzebne, a jak bedzie to sie bede wtedy meczyl smile.gif.
w kazdym razie dzieki.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.