2016-05-13 13 views
9

My SQL wygląda mniej więcej tak:Doctrine - jak powiązać tablicę z SQL?

$sql = "select * from user where id in (:userId) and status = :status"; 

$em = $this->getEntityManager(); 
$stmt = $em->getConnection()->prepare($sql); 
$stmt->bindValue(':userId', $accounts, \Doctrine\DBAL\Connection::PARAM_INT_ARRAY); 
$stmt->bindValue(':status', 'declined'); 
$stmt->execute(); 

$result = $stmt->fetchAll(); 

ale zwraca:

An exception occurred while executing (...)

with params [[1,2,3,4,5,6,7,8,11,12,13,14], "declined"]

Notice: Array to string conversion

nie mogę użytkownik queryBuilder ponieważ moje prawdziwe SQL jest bardziej skomplikowana (ex zawiera dołączył select, związków i tak dalej).

+0

Czy można użyć foreach? 'foreach ($ accounts jako $ key => $ val) {$ stmt-> bindValue (': userId', $ val); } ' – pes502

Odpowiedz

8

Nie można użyć przygotowanych sprawozdań z tablicami po prostu dlatego, że sam sql nie obsługuje macierze. Co jest prawdziwym wstydem. Gdzieś wzdłuż linii rzeczywiście musisz ustalić, czy twoje dane zawierają trzy rzeczy i emitują IN (?,?,?). Menedżer encji Doctrine ORM robi to automatycznie.

Na szczęście DBAL obejmuje Cię. Po prostu nie używaj wiązania lub nie przygotuj się. Instrukcja ma przykład: http://doctrine-orm.readthedocs.io/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion

w twoim przypadku to będzie wyglądać mniej więcej tak:

$sql = "select * from user where id in (?) and status = ?"; 
$values = [$accounts,'declined']; 
$types = [Connection::PARAM_INT_ARRAY, \PDO::PARAM_STRING]; 
$stmt = $conn->executeQuery($sql,$values,$types); 
$result = $stmt->fetchAll(); 

Powyższy kod jest niesprawdzone, ale powinien dostać ten pomysł.

+0

ok, ale w tej sytuacji muszę uważać, aby powiązać dane w odpowiedniej kolejności :(To jest" niezbyt fajne ": \ – breq

+0

Rozumiem, że obawy i nazwane parametry są ładne ale pomyśl o tym, masz tylko dwa parametry, które nie są trudne do utrzymania w porządku.Przy zajmowaniu się zapytaniami z większą liczbą parametrów, używam dbal buildera zapytań do generowania sql i w zasadzie dodawania wartości do mojej tablicy wartości $ I tak nie jest tak źle, gdy już się do tego przyzwyczajasz, a to nie pozwala ci zdecydować, jakie parametry powinny być nazywane na pierwszym miejscu.Nazwanie jest zawsze trudne – Cerad

+0

Ale mu prawdziwy SQL jest bardziej skomplikowany http: // pastebin.com/1JiRHFdc, wszelkie pomysły, jak to zrobić "dobrze"? Będzie zawierał także więcej zmiennych i gdzie clausure, jeśli użytkownik zdecyduje się na dalsze filtrowanie wyników – breq

-1

trzeba owinąć je w tablicy

$stmt->bindValue(':userId', array($accounts), array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY)); 

http://doctrine-dbal.readthedocs.io/en/latest/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion

edit

Powinienem był opracowany więcej. Nie możesz powiązać takiej tablicy, nie przygotowuj sql execute bezpośrednio jako przykład w dokumentach.

$stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?)', 
array(array(1, 2, 3, 4, 5, 6)), 
array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY)); 

You cannot bind an array of values into a single prepared statement parameter

+1

Nie sądzę ... Ostrzeżenie: PDOStatement :: bindValue() oczekuje, że parametr 3 będzie liczbą całkowitą, tablica given'. Używam metody "prepare", a nie 'executeQuery' – breq

0

Jeśli chcesz trzymać się składni :param gdzie kolejność nie ma znaczenia, trzeba zrobić trochę dodatkowej pracy, ale pokażę ci łatwiejszy sposób wiązania parametry:

// store all your parameters in one array 
$params = array(
    ':status' => 'declined' 
); 

// then, using your arbitrary array of id's ... 
$array_of_ids = array(5, 6, 12, 14); 

// ... we're going to build an array of corresponding parameter names 
$id_params = array(); 
foreach ($array_of_ids as $i => $id) { 
    // generate a unique name for this parameter 
    $name = ":id_$i"; // ":id_0", ":id_1", etc. 

    // set the value 
    $params[$name] = $id; 

    // and keep track of the name 
    $id_params[] = $name; 
} 

// next prepare the parameter names for placement in the query string 
$id_params = implode(',', $id_params); // ":id_0,:id_1,..." 
$sql = "select * from user where id in ($id_params) and status = :status"; 

w tym przypadku możemy skończyć z: "select * from user where id in (:id_0,:id_1,:id_2,:id_3) and status = :status"

// now prepare your statement like before... 
$stmt = $em->getConnection()->prepare($sql); 

// ...bind all the params in one go... 
$stmt->execute($params); 

// ...and get your results! 
$result = $stmt->fetchAll(); 

takie podejście będzie także współpracować z tablicą ciągów.