Existuje záznam v databázi?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
buffus
Člen | 101
+
0
-

PHP 5.3.3, Nette Framework 2.0.8 pro PHP 5.3 nebo 5.4
Prosím o radu. Potřebuji opakovaně ukládat data z proměnného xml souboru např.

<cats>
  <cat>
      <name>Jack</name>
      <age>2</age>
      <color>grey</color>
  </cat>
  <cat>
      <name>Maxwell</name>
      <age>12</age>
      <color>orange</color>
  </cat>
</cats>

do MySQL tabulky (sloupce name, age, color) s podmínkou, že sloupec name bude primární klíč a pokud se v novém xml souboru vyskytne jméno, které již sloupec name obsahuje, celý řádek (tag cat) se nezapíše, ale ostatní ano. Nemám zkušenost s návrhem modelu a vycházím z quickstartu. V modelu dědím z nezměněného repozitáře Repository do CatRepository:

<?php
namespace Todo;
use Nette;

class CatRepository extends Repository
{
		public function findName($p)
		{
				return $this->findBy(array('name' => $p));
		}

}

V config.neon mám zaregistrovanou službu catrepository.

	services:
		catrepository: Todo\CatRepository

V CatPresenteru bych rád akci zápisu xml do tabulky realizoval. Představa je nějak zapsat v Nette kód 550 „Existuje záznam?“ z knihy Jakuba Vrány 1001 tipů a triků pro PHP

$exists = mysql_num_rows(mysql_query("
	SELECT 1
	FROM user
	WHERE email = 'test@example.com'
	LIMIT 1
"));

jako vylučující podmínku pro zápis do tabulky, ale nevím jak. Předem díky za radu.

nanuqcz
Člen | 822
+
0
-

Ahoj,
nevím, jestli jsem přesně pochopil dotaz. Ale metoda v modelu, která zapíše jen dosud ne-existující záznam, by mohla vypadat třeba takto (pokud používáš Nette\Database):

namespace Todo;
use Nette;

class CatRepository extends Repository
{
	public function create($values)
	{
		if ($this->db->table('cats')->where('name', $values['name'])->count() == 0) {  // Pokud dosud neexistuje záznam s daným jménem
			return $this->db->table('cats')->insert($values);  // ulož ho
		} else {
			return NULL;
		}
	}
}
hrach
Člen | 1838
+
0
-

Používat spíš count(‚*‘), který spustí patřičný počítací dotaz v db.

thorewi
Člen | 84
+
0
-

No, pokud už tam je záznam se stejným jménem a má tedy v DB nastavený PRIMARY nebo UNIQUE, tak při vkládání to vyhodí PDOException, takže řešení by mohlo být také uzavřít to do try.

namespace Todo;
use Nette;

class CatRepository extends Repository
{
  public function create($values)
  {
    try {
      return $this->db->table('cats')->insert($values);  // ulož ho
    } catch(\PDOException $e) {
      if($e->getCode() == '23000') {
        // duplicita
      } else {
        // jina chyba
        echo $e->getMessage();
      }
      return NULL;
    }
  }
}

Editoval thorewi (24. 1. 2013 10:09)

buffus
Člen | 101
+
0
-

Použil jsem první řešení od nanuqcz. Díky! Funguje bez problémů. PDOException při existujících jménech nevyhazuje. Zkoušel jsem to na této tabulce:

SET NAMES utf8;

DROP TABLE IF EXISTS `cats`;
CREATE TABLE `cats` (
  `name` varchar(12) DEFAULT NULL,
  `age` varchar(12) DEFAULT NULL,
  `color` varchar(12) DEFAULT NULL,
  PRIMARY KEY (`name`),
  KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Díky všem.