Array uitlezen
voor mijn querybuilder ben ik een functie aan het schrijven voor de where-clause. Mijn functie moet zorgen voor een array met parameters en een string met de where-clause. De input moet op deze manier binnenkomen:
De code die ik gebruik is de volgende:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function setWhere()
{
$values = array('id' => 1, 'name' => 'test'); // input
if(count($values) > 0)
{
$where = 'WHERE ';
foreach($values as $key => $value)
{
$where .= $key . ' = :' . $key . ' AND ';
$values[':' . $key] = $value;
unset($values[$key]);
}
$where = substr($where, 0, -5);
echo $where; // WHERE id = :id AND name = :name
}
}
{
$values = array('id' => 1, 'name' => 'test'); // input
if(count($values) > 0)
{
$where = 'WHERE ';
foreach($values as $key => $value)
{
$where .= $key . ' = :' . $key . ' AND ';
$values[':' . $key] = $value;
unset($values[$key]);
}
$where = substr($where, 0, -5);
echo $where; // WHERE id = :id AND name = :name
}
}
Nu vind ik die code eigenlijk vrij omslachtig dus ik vroeg me af of die niet beter kon? Hoe zouden jullie zoiets aanpakken?
Alvast bedankt,
Jasper
Waarom doe je dit:
$values[':' . $key] = $value;
unset($values[$key]);
Ik ben ook wel eens zo bezig geweest om functies te maken om een query te bouwen. Ik weet echter niet of ik het nu weer zo ga doen, aangezien het zeer omslachtig is allemaal. Je kunt een query op zoveel manieren opbouwen dat het eigenlijk niet te doen is om dat allemaal in functies te verpakken.
En wat als het OR of iets anders moet zijn in plaats van AND?
Quote:
$values[':' . $key] = $value;
unset($values[$key]);
unset($values[$key]);
zodat $values kan gebruikt worden als PDO parameter bij de execute. De keys komen dan overeen met de prepared statements. De oude keys zijn niet meer nodig dus die doe ik weg.
@mark, het gaat over de functionaliteit. In de praktijk zal de functie idd returnen en komt $values binnen. Dit is een voorbeeld.
Voor OR of end kan er vrij makkelijk een parameter worden toegevoegd denk ik.
Nog even uitleggen waarom ik het niet op de doctrine manier wil doen. Ik wil dat er via mijn builder alleen data binnen komt dus niet zoals doctrine "id = :id AND name = :name" want dat is SQL.
Gewijzigd op 21/02/2013 20:56:35 door Jasper DS
Code (php)
Gewijzigd op 21/02/2013 21:47:30 door Jan Koehoorn
NOgmaals Jasper, goed nadenken of je dit allemaal wel wil. Ik was er ook ooit heel enthousiast over... totdat ik tot de ontdekking kwam dat queries gruwelijk lang en gecompliceerd kunnen worden. Dat krijg je nooit allemaal in functies gestopt.
Jan, bedankt! Ziet er beter uit mits enige aanpassingen. Zo is het beter niet?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
if(count($columns) > 0)
{
$wheres = array();
foreach ($columns as $key => $column )
{
$wheres[':' . $key] = $key . '= :' . $key;
}
echo 'WHERE ' . implode ( ' AND ', $wheres );
var_dump($wheres);
}
{
$wheres = array();
foreach ($columns as $key => $column )
{
$wheres[':' . $key] = $key . '= :' . $key;
}
echo 'WHERE ' . implode ( ' AND ', $wheres );
var_dump($wheres);
}
Gewijzigd op 21/02/2013 22:18:57 door Jasper DS
Is het niet veel makkelijker om op de plek waar je nu al die functies aan gaat roepen om de SELECT, FROM, WHERE, ORDER BY, GROUP BY, LIMIT etc clausules op te bouwen, gewoon een string met de query en (eventueel) een array met parameters door geeft. Veel flexibeler dan dat kan het niet.... En in je code uiteindelijk een stuk korter.
Code (php)
1
2
3
2
3
$storage = new Storage('SELECT', 'users'); // action en from zijn verplicht
$storage->setFields(array('id', 'name', 'email')); // niet verplicht -> standaard *
$storage->setWhere(array('id' => 1, 'name' => 'Jasper')); // field -> value
$storage->setFields(array('id', 'name', 'email')); // niet verplicht -> standaard *
$storage->setWhere(array('id' => 1, 'name' => 'Jasper')); // field -> value
Die dataholder gaat dan naar de adapter, dat kan een PDOAdaptor zijn, txtAdaptor, MysqlAdaptor. In de PDO en in de MysqlAdaptor word sql gegenereerd met behulp van de data van de Storage classe. De sql in de Mysql en de PDO adaptor is niet hetzelfde want PDO werkt met prepared statements en Mysql niet.
M.a.w. ik wil een adaptor kunnen opbouwen met de functies uit de Storage(builder) de storage builder word opgebouwd in mijn model want ik wil geen SQL in mijn model zodat ik daar niet van afhankelijk ben.
Gewijzigd op 22/02/2013 10:01:14 door Jasper DS
Anyway, ik ga je verder niet proberen over te halen. Doe wat je moet doen, maar ik voorspel nu dat je binnen een half jaar er weer vanaf stapt omdat het vele malen complexer is dan je nu denkt, uitermate inflexibel is (ik geef je een maand voor je je eerste query vindt die je er met geen mogelijkheid in krijgt) en het kost je veel te veel werk voor iets dat veel sneller en simpeler kan.
Erwin H op 22/02/2013 10:08:41:
Waarom zou je in godsnaam MySQL en (of) PDO gebruiken? Allebij werken ze met mysql databases. Normaal gesproken gebruik je een andere adapter omdat je een andere database gebruikt. Een andere adapter gebruiken om maar een andere adapter te kunnen gebruiken is een beetje nutteloos. Ook omdat je het nu al in een abstractie laag gaat verwerken.
MysqlAdaptor en PDOAdaptor was idd een slecht voorbeeld in de praktijk maar het is wel nodig voor no-SQL databases. PDOAdaptor voor alle SQL database en andere Adaptors voor no-sql databases.
Dit wil ik bereiken:
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
public function findById($id)
{
$sb = new StorageBuilder('SELECT', 'gebruikers');
$sb->setFields(array('id,', 'name'));
$sb->setWhere(array('id' => $id));
$result = $this->getStorage()->execute($sb);
$this->populate($result);
}
{
$sb = new StorageBuilder('SELECT', 'gebruikers');
$sb->setFields(array('id,', 'name'));
$sb->setWhere(array('id' => $id));
$result = $this->getStorage()->execute($sb);
$this->populate($result);
}
Gewijzigd op 22/02/2013 11:06:54 door Jasper DS