ugrás a tartalomhoz

Php függvény többször fut le, mint kellene

Totti 1986 · 2010. Dec. 15. (Sze), 19.22
Sziasztok!

Van egy táblám, amiben azt tárolom, melyik tábla melyik sora változott, így nem kell annyit kiolvasnom, csak ami változott. Amikor változás van, akár egy update, akár egy delete, vagy insert, az érintett táblák nevét és sorait átadom egy függvénynek, ami beirja az említett táblába a változást.
Erre a következőt használom:

class DataBase {

	public $db_insert_cnt = 0;
	public $db_update_cnt = 0;
	public $db_delete_cnt = 0;

	function mysql_update($query, $tables = '', $rows = '') {
	
		mysql_query($query);
		$GLOBALS['db_update_cnt']++;
		
		if(!empty($tables)) {
			foreach($tables as $tblsKEY=>$tblsVALUE) {
				$insert_query = 'INSERT 
									INTO change_table 
									(CHL_TABLE, CHL_ROW, CHL_TIME) 
									VALUES 
									("'.$tblsVALUE.'","'.$rows[$tblsKEY].'","'.date('U').'")';
				$this->mysql_insert($insert_query);
			}
		}
	}

	function mysql_insert($query, $tables = '', $rows = '') {
	
		mysql_query($query);
		$GLOBALS['db_insert_cnt']++;
		
		if(!empty($tables)) {
			foreach($tables as $tblsKEY=>$tblsVALUE) {
				$insert_query = 'INSERT 
									INTO change_table 
									(CHL_TABLE, CHL_ROW, CHL_TIME) 
									VALUES 
									("'.$tblsVALUE.'","'.$rows[$tblsKEY].'","'.date('U').'")';
				$this->mysql_insert($insert_query);
			}
		}
	}

	function mysql_delete($query, $tables = '', $rows = '') {
	
		mysql_query($query);
		$GLOBALS['db_delete_cnt']++;
		
		if(!empty($tables)) {
			foreach($tables as $tblsKEY=>$tblsVALUE) {
				$insert_query = 'INSERT 
									INTO change_table 
									(CHL_TABLE, CHL_ROW, CHL_TIME) 
									VALUES 
									("'.$tblsVALUE.'","'.$rows[$tblsKEY].'","'.date('U').'")';
				$this->mysql_insert($insert_query);
			}
		}
	}
}
(Az emptyempty az persze csak empty!)

Vagyis átadom a query-t, amit végrehajt az adott függvény, majd megnézi, adtam-e át táblát és sort, amit ez a változás érintett.
Ha igen, akkor végigmegy a $tables és $rows tömbön (arra figyelek, hogy mindkettő ugyanannyi soros legyen), és létrehozza az insert query-t, az pedig átadott query-ként azt végrehajtja. Ott már nincs átadva $tables és $rows tömb, tehát a foreach nem fut le.

Egy próba query-t írtam, egy update-et, hogy lássam, működik-e.
A query a következő:

// PROBA UPDATE
$cs = new DataBase;
$tmp['update_tables'] = array('password');
$tmp['update_rows'] = array('1');
$cs->mysql_update('UPDATE password 
							SET PASS="password" 
							WHERE ADMIN_ID="1"', 
						$tmp['update_tables'], 
						$tmp['update_rows']);

A probléma az, hogy ez most egy lefrissítéskor 18szor fut le. Ennyi sort ad hozzá a táblámhoz. Fogalmam sincs, hogy hol lehet a hiba, de az a legfurcsább, hogy amikor kiiratom a $db_insert_cnt változót, azt írja, egyetlen insert futott le. Az oldal nem fut le 18szor, csak az insert, és azt sem számolja. Nem tudok mire gondolni.
 
1

Biztos?

Poetro · 2010. Dec. 15. (Sze), 19.36
Honnan tudod, hogy az insert 18-szor futott le? És miért használsz globális változókat a számlálókhoz, miért nem az objektum saját tulajdonságait? Mondjuk annak az előnyét sem látom, hogy miért lenne ez hasznosabb, mint tárolni magukban a táblákban az utolsó frissítés állapotát, és ezzel azokat a lekérdezéseket tennéd sokkal gyorsabbá, ráadásul valószínűleg nem kellene rengeteg JOIN illetve dupla lekérdezés.

Arról most inkább nem is írok, hogy nincsen semmilyen ellenőrzés berakva az oszlopok típusára nézve, illetve nincsennek escape-elve az adatbázisnak átadott adatok.
2

igen

Totti 1986 · 2010. Dec. 15. (Sze), 19.46
18 sorral bővült a táblám, pedig csak 1 udpate-et hajtottam végre.
A számlálókhoz nem tudtam mit használjak.
Nem az egész tábla utolsó frissítése érdekel, hanem az, hogy egy adott sora (egy adott emberhez vagy tartalomhoz tartozó mező) változott-e. Így nem kell az adott sort kiolvasnom ha nem muszáj.

Escapelni még bőven az adatbázisba irás előtt szoktam, pont a query-k összerakása előtt.

Igazából ezzel épp a lekérdezéseket akartam meggyorsitani, vagyis azt, hogy ne kelljen, ha nem muszáj.
3

Kicsit átírtam, hogy ne

Poetro · 2010. Dec. 15. (Sze), 19.54
Kicsit átírtam, hogy ne kelljen hozzá MySQL hogy tesztelni lehessen:

function query($s) {
  echo $s, "\n--\n";
}

class DataBase {
  public $db_insert_cnt = 0;
  public $db_update_cnt = 0;
  public $db_delete_cnt = 0;

  function mysql_update($query, $tables = '', $rows = '') {
    query($query);
    $this->db_update_cnt++;

    if (!empty($tables)) {
      foreach ($tables as $tblsKEY => $tblsVALUE) {
        $insert_query = 'INSERT
                          INTO change_table
                          (CHL_TABLE, CHL_ROW, CHL_TIME)
                          VALUES
                          ("' . $tblsVALUE . '","' . $rows[$tblsKEY] . '","' . date('U') . '")';
        $this->mysql_insert($insert_query);
      }
    }
  }

  function mysql_insert($query, $tables = '', $rows = '') {

    query($query);
    $this->db_insert_cnt++;

    if (!empty($tables)) {
      foreach ($tables as $tblsKEY => $tblsVALUE) {
        $insert_query = 'INSERT
                          INTO change_table
                          (CHL_TABLE, CHL_ROW, CHL_TIME)
                          VALUES
                          ("' . $tblsVALUE . '","' . $rows[$tblsKEY] . '","' . date('U') . '")';
        $this->mysql_insert($insert_query);
      }
    }
  }

  function mysql_delete($query, $tables = '', $rows = '') {

    query($query);
    $this->db_delete_cnt++;

    if (!empty($tables)) {
      foreach ($tables as $tblsKEY => $tblsVALUE) {
        $insert_query = 'INSERT
                          INTO change_table
                          (CHL_TABLE, CHL_ROW, CHL_TIME)
                          VALUES
                          ("' . $tblsVALUE . '","' . $rows[$tblsKEY] . '","' . date('U') . '")';
        $this->mysql_insert($insert_query);
      }
    }
  }
}
// PROBA UPDATE
$cs = new DataBase;
$tmp['update_tables'] = array(
  'password'
);
$tmp['update_rows'] = array(
  '1'
);
$cs->mysql_update('UPDATE password
                    SET PASS="password"
                    WHERE ADMIN_ID="1"', $tmp['update_tables'], $tmp['update_rows']);
print $cs->db_insert_cnt;
Kimenet:
UPDATE password
                    SET PASS="password"
                    WHERE ADMIN_ID="1"
--
INSERT
                          INTO change_table
                          (CHL_TABLE, CHL_ROW, CHL_TIME)
                          VALUES
                          ("password","1","1292435418")
--
1
Én ebből úgy látom, hogy pontosan egy UDPATE és egy INSERT futott le.
4

Van, hogy nekem is csak

Totti 1986 · 2010. Dec. 15. (Sze), 20.10
Van, hogy nekem is csak egyszer fut le.
Pontosabban igyekeztem kiiktatni minden zavaró tényezőt, include-olt fájlokat, és amikor 2 fájlt kiszedtem, akkor nekem se futott le 18-szor, csak 1-szer. De ezek az include-olt fájlok nem tartalmaznak szinte semmit. Mindkét fájlban van 1-1 select, de semmi olyat nem találtam, ami ehhez kapcsolódna. Ezért gondoltam, hogy rosszul írtam meg a függvényeket.
Ráadásul, ha nincs változás az ellenőrző táblában azokhoz a táblákhoz kapcsolódóan, akkor azok a selectek sem futnak le.
5

Optimalizálás

Poetro · 2010. Dec. 15. (Sze), 20.11
function query($s) {
  echo $s, "\n--\n";
}

class DataBase {
  public $db_insert_cnt = 0;
  public $db_update_cnt = 0;
  public $db_delete_cnt = 0;

  function _insert($key, $value) {
    $insert_query = 'INSERT
                      INTO change_table
                      (CHL_TABLE, CHL_ROW, CHL_TIME)
                      VALUES
                      ("' . $value . '","' . $key . '","' . date('U') . '")';
    $this->mysql_insert($insert_query);
  }

  function _multi_insert($tables, $rows) {
    if (!empty($tables)) {
      foreach ($tables as $tblsKEY => $tblsVALUE) {
        $this->_insert($rows[$tblsKEY], $tblsVALUE);
      }
    }
  }

  function mysql_update($query, $tables = '', $rows = '') {
    query($query);
    $this->db_update_cnt++;
    $this->_multi_insert($tables, $rows);
  }

  function mysql_insert($query, $tables = '', $rows = '') {
    query($query);
    $this->db_insert_cnt++;
    $this->_multi_insert($tables, $rows);
  }

  function mysql_delete($query, $tables = '', $rows = '') {
    query($query);
    $this->db_delete_cnt++;
    $this->_multi_insert($tables, $rows);
  }
}
// PROBA UPDATE
$cs = new DataBase;
$tmp['update_tables'] = array(
  'password'
);
$tmp['update_rows'] = array(
  '1'
);
$cs->mysql_update('UPDATE password
                    SET PASS="password"
                    WHERE ADMIN_ID="1"', $tmp['update_tables'], $tmp['update_rows']);
print $cs->db_insert_cnt;
Mivel nem tudom, mi van a többi fájlodban, és azok nem használnak-e
DataBase::mysql_update, DataBase::mysql_delete illetve DataBase::mysql_insert függvényeket, így nehéz bármit is mondani. Mindenesetre a fenti kóddal nem tudom reprodukálni a 18 beszúrást.
6

local

Totti 1986 · 2010. Dec. 15. (Sze), 20.58
Közben lemásoltam mindent localhostra, és megnéztem, ott mi van.
Localban minden oké, egyszer fut csak le, még akkor is, ha az említett 2 fájl is hozzá van csapva.
A tárhelyen viszont jelen pillanatban frissítésenként 12szer fut le az insert.
Amúgy azért tettem globalba a számlálókat, mert máshogy nem tudom kiolvasni az értéküket. Most ahogy az optimalizálásod alapján átalakítottam a függvényeket, nem tudom kiolvasni a számlálók értékét.
7

Nem tudod kiolvasni?

Poetro · 2010. Dec. 15. (Sze), 21.09
Miért, szerinted a
print $cs->db_insert_cnt;
mit csinál?
8

oké

Totti 1986 · 2010. Dec. 15. (Sze), 21.12
Jól van na, nem tudtam.
Egyelőre írtam a tárhelynek, hogy náluk van-e a probléma. Mert még az is lehet. Localban minden rendben zajlik le.
9

Szerintem rossz az elv

rimo86 · 2011. Feb. 10. (Cs), 14.23
Amit te leprogramoztál, annak a haszna egyenértékű a view-al ( http://dev.mysql.com/doc/refman/5.0/en/create-view.html ). Egy adathalmazt kirak egy másik táblába, így abból gyorsabb lesz a lekérdezés. De mi van, ha 1000-n akarják megnézni, 5-en pedig szerkeszteni az adatokat... Szerintem akkor az algoritmusod megadja magát, illetve nagy látogatottságú oldalaknál ezért nem tanácsolják a view-t.