Het selecteren van gegevens met behulp van JDatabase
From Joomla! Documentation
Let op dat veel online voorbeelden $db->query() gebruiken in plaats van $db->execute(). Dit was de oude methode in Joomla 1.5 en 2.5 en zal deprecated (verouderd) berichten geven in Joomla 3.0+.
Deze handleiding is opgesplitst in twee aparte delen:
- Invoegen, bijwerken en verwijderen van gegevens in de database.
- Selecteren van gegevens uit één of meer tabellen en het ophalen op diverse verschillende formaten.
Dit gedeelte van de documentatie kijkt naar het selecteren van gegevens uit een database tabel en het ophalen in verschillende formaten. Klik hier voor om het andere deel te lezen.
Inleiding
Joomla biedt een geavanceerde database abstractie laag om het gebruik door externe ontwikkelaars te vereenvoudigen. Nieuwe versies van de Joomla Platform API bieden extra functionaliteit welke de database laag verder uitbreidt en bevat functies zoals koppelingen naar een groot aantal database servers en de query-koppeling om de leesbaarheid te vergroten van verbindingscode an het vereenvoudigen van het coderen van SQL.
Joomla kan verschillende soorten SQL database systemen gebruiken en draaien op diverse omgevingen met verschillende tabel-voorvoegsels. Naast deze functies maakt de class automatisch de database verbinding aan. Naast het instantiëren van het object heeft u slechts twee regels code nodig om het resultaat uit de database te krijgen in een verscheidenheid aan formaten. Het gebruik van de Joomla database laag garandeert een maximum aan compatibiliteit en flexibiliteit voor uw extensie.
De query
Joomla's database querying veranderd met de introductie van Joomla 1.6. De aanbevolen manier van het bouwen van database queries is met behulp van "query chaining" (hoewel string queries nog wel worden ondersteund).
Query chaining verwijst naar de methode van koppelen van een aantal methodes, de één na de ander waarbij ieder methode een object terug geeft die de volgende methode kan ondersteunen, waardoor de leesbaarheid verbeterd wordt en de code vereenvoudigd.
Om een nieuwe instantie van de JDatabaseQuery class te verkrijgen gebruiken we de JDatabaseDriver getQuery methode:
$db = JFactory::getDbo();
$query = $db->getQuery(true);
De JDatabaseDriver::getQuery neemt een optioneel argument, $new, welke 'waar' of 'niet waar' kunnen zijn (de standaard is 'niet waar').
Om onze data source te bevragen kunnen we een aantal JDatabaseQuery methodes aanroepen; deze methodes kapselen de gegevens source's query-taal (in de meeste gevallen SQL) in, verbergen query-specifieke syntaxis voor de ontwikkelaar en verhogen de overdraagbaarheid van de broncode van de ontwikkelaar.
Enkele van de meest gebruikte methodes omvatten; select, from, join, where en order. Er zijn ook methodes zoals insert, update en delete voor het wijzigen van de gegevensopslag. Door het koppelen van deze en andere methodes aanroepen, kunt u bijna iedere query maken ten opzichte van uw database zonder afbreuk te doen aan de overdraagbaarheid van uw code..
Selecteren van gegevens uit een enkele tabel
Hieronder staat een voorbeeld hoe je een database query aanmaakt met behulp van de JDatabaseQuery klasse. Met gebruik van de select, from, where en order methodes, kunnen we queries maken die flexibel, makkelijke leesbaar en draagbaar zijn.
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
// Select all records from the user profile table where key begins with "custom.".
// Order it by the ordering field.
$query->select($db->quoteName(array('user_id', 'profile_key', 'profile_value', 'ordering')));
$query->from($db->quoteName('#__user_profiles'));
$query->where($db->quoteName('profile_key') . ' LIKE '. $db->quote('\'custom.%\''));
$query->order('ordering ASC');
// Reset the query using our newly populated query object.
$db->setQuery($query);
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$results = $db->loadObjectList();
De query kan ook geschakeld worden om het volgende te vereenvoudigen:
$query
->select($db->quoteName(array('user_id', 'profile_key', 'profile_value', 'ordering')))
->from($db->quoteName('#__user_profiles'))
->where($db->quoteName('profile_key') . ' LIKE '. $db->quote('\'custom.%\''))
->order('ordering ASC');
Chaining kan handig zijn wanneer queries langer en complex worden.
Groeperen werkt ook simpel. De volgende query telt het aantal artikelen in iedere categorie.
$query
->select( array('catid', 'COUNT(*)') )
->from($db->quoteName('#__content'))
->group($db->quoteName('catid'));
Een limiet kan worden ingesteld op een query met behulp van "setLimit". Bijvoorbeeld in de volgende query, die zou teruggebracht worden naar 10 records.
$query
->select($db->quoteName(array('user_id', 'profile_key', 'profile_value', 'ordering')))
->from($db->quoteName('#__user_profiles'))
->setLimit('10');
Selecteren van gegevens uit meerdere tabellen
Met behulp van de JDatabaseQuery's join methodes, kunnen we gegevens selecteren van meerdere gerelateerde tabellen. De algemene "join" methode heeft twee argumenten; het join "type" (binnen, buiten, links, rechts) en de join voorwaarden. In het volgende voorbeeld zul je merken dat we alle zoekwoorden kunnen gebruiken die we normaal gesproken gebruiken als we een SQL query zouden schrijven, inclusief het 'Als' zoekwoord voor alias tabellen en het 'Aan' zoekwoord om relaties tussen de tabellen te maken. Let op dat de tabel alias wordt gebruikt in alle methodes die verwijzen naar tabel kolommen (I.e. select, where, order).
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
// Select all articles for users who have a username which starts with 'a'.
// Order it by the created date.
// Note by putting 'a' as a second parameter will generate `#__content` AS `a`
$query
->select(array('a.*', 'b.username', 'b.name'))
->from($db->quoteName('#__content', 'a'))
->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
->where($db->quoteName('b.username') . ' LIKE \'a%\'')
->order($db->quoteName('a.created') . ' DESC');
// Reset the query using our newly populated query object.
$db->setQuery($query);
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$results = $db->loadObjectList();
De join methode hierboven stelt ons in staat om zowel op inhoud als gebruikerstabellen te doorzoeken, artikelen ophalend met de autheur details. Er zijn ook gemakkelijke methodes voor joins:
We kunnen meerdere joins gebruiken voor een query van meer dan twee tabellen:
$query
->select(array('a.*', 'b.username', 'b.name', 'c.*', 'd.*'))
->from($db->quoteName('#__content', 'a'))
->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
->join('LEFT', $db->quoteName('#__user_profiles', 'c') . ' ON (' . $db->quoteName('b.id') . ' = ' . $db->quoteName('c.user_id') . ')')
->join('RIGHT', $db->quoteName('#__categories', 'd') . ' ON (' . $db->quoteName('a.catid') . ' = ' . $db->quoteName('d.id') . ')')
->where($db->quoteName('b.username') . ' LIKE \'a%\'')
->order($db->quoteName('a.created') . ' DESC');
Let op hoe chaining de broncode veel leesbaarder maakt voor deze langere query's.
Soms, heb je ook de 'als' clausule nodig als je items selecteert om conflicten met kolomnamen te vermijden. In dit geval, kunnen meerdere select-punten worden ge-chained in combinatie met het gebruik van de tweede parameter van $db->quoteName.
$query
->select('a.*')
->select($db->quoteName('b.username', 'username'))
->select($db->quoteName('b.name', 'name'))
->from($db->quoteName('#__content', 'a'))
->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
->where($db->quoteName('b.username') . ' LIKE \'a%\'')
->order($db->quoteName('a.created') . ' DESC');
Een tweede reeks kan ook gebruikt worden als de tweede parameter van de select punten om de waarden te vullen van de 'als' clausule. Vergeet niet om de nullen toe te voegen in de tweede reeks om te verwijzen naar kolommen in de eerste reeks waar je de 'als' clausule niet voor wilt gebruiken.
$query
->select(array('a.*'))
->select($db->quoteName(array('b.username', 'b.name'), array('username', 'name')))
->from($db->quoteName('#__content', 'a'))
->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
->where($db->quoteName('b.username') . ' LIKE \'a%\'')
->order($db->quoteName('a.created') . ' DESC');
De resultaten van de query
De database klasse bevat vele methodes voor het werken met een query resultaat.
Single Value Result
loadResult()
Use loadResult() when you expect just a single value back from your database query.
| id | name | username | |
|---|---|---|---|
| 1 | John Smith | johnsmith@domain.example | johnsmith |
| 2 | Magda Hellman | magda_h@domain.example | magdah |
| 3 | Yvonne de Gaulle | ydg@domain.example | ydegaulle |
This is often the result of a 'count' query to get a number of records:
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('COUNT(*)');
$query->from($db->quoteName('#__my_table'));
$query->where($db->quoteName('name')." = ".$db->quote($value));
// Reset the query using our newly populated query object.
$db->setQuery($query);
$count = $db->loadResult();
or where you are just looking for a single field from a single row of the table (or possibly a single field from the first row returned).
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('field_name');
$query->from($db->quoteName('#__my_table'));
$query->where($db->quoteName('some_name')." = ".$db->quote($some_value));
$db->setQuery($query);
$result = $db->loadResult();
Single Row Results
Each of these results functions will return a single record from the database even though there may be several records that meet the criteria that you have set. To get more records you need to call the function again.
| id | name | username | |
|---|---|---|---|
| 1 | John Smith | johnsmith@domain.example | johnsmith |
| 2 | Magda Hellman | magda_h@domain.example | magdah |
| 3 | Yvonne de Gaulle | ydg@domain.example | ydegaulle |
loadRow()
loadRow() returns an indexed array from a single record in the table:
. . .
$db->setQuery($query);
$row = $db->loadRow();
print_r($row);
will give:
Array ( [0] => 1, [1] => John Smith, [2] => johnsmith@domain.example, [3] => johnsmith )
You can access the individual values by using:
$row['index'] // e.g. $row['2']
Notes:
- The array indices are numeric starting from zero.
- Whilst you can repeat the call to get further rows, one of the functions that returns multiple rows might be more useful.
loadAssoc()
loadAssoc() returns an associated array from a single record in the table:
. . .
$db->setQuery($query);
$row = $db->loadAssoc();
print_r($row);
will give:
Array ( [id] => 1, [name] => John Smith, [email] => johnsmith@domain.example, [username] => johnsmith )
You can access the individual values by using:
$row['name'] // e.g. $row['email']
Notes:
- Whilst you can repeat the call to get further rows, one of the functions that returns multiple rows might be more useful.
loadObject()
loadObject returns a PHP object from a single record in the table:
. . .
$db->setQuery($query);
$result = $db->loadObject();
print_r($result);
will give:
stdClass Object ( [id] => 1, [name] => John Smith, [email] => johnsmith@domain.example, [username] => johnsmith )
You can access the individual values by using:
$result->index // e.g. $result->email
Notes:
- Whilst you can repeat the call to get further rows, one of the functions that returns multiple rows might be more useful.
Single Column Results
Each of these results functions will return a single column from the database.
| id | name | username | |
|---|---|---|---|
| 1 | John Smith | johnsmith@domain.example | johnsmith |
| 2 | Magda Hellman | magda_h@domain.example | magdah |
| 3 | Yvonne de Gaulle | ydg@domain.example | ydegaulle |
loadColumn()
loadColumn() returns an indexed array from a single column in the table:
$query->select('name'));
->from . . .";
. . .
$db->setQuery($query);
$column= $db->loadColumn();
print_r($column);
will give:
Array ( [0] => John Smith, [1] => Magda Hellman, [2] => Yvonne de Gaulle )
You can access the individual values by using:
$column['index'] // e.g. $column['2']
Notes:
- The array indices are numeric starting from zero.
- loadColumn() is equivalent to loadColumn(0).
loadColumn($index)
loadColumn($index) returns an indexed array from a single column in the table:
$query->select(array('name', 'email', 'username'));
->from . . .";
. . .
$db->setQuery($query);
$column= $db->loadColumn(1);
print_r($column);
will give:
Array ( [0] => johnsmith@domain.example, [1] => magda_h@domain.example, [2] => ydg@domain.example )
You can access the individual values by using:
$column['index'] // e.g. $column['2']
loadColumn($index) allows you to iterate through a series of columns in the results
. . .
$db->setQuery($query);
for ( $i = 0; $i <= 2; $i++ ) {
$column= $db->loadColumn($i);
print_r($column);
}
will give:
Array ( [0] => John Smith, [1] => Magda Hellman, [2] => Yvonne de Gaulle ), Array ( [0] => johnsmith@domain.example, [1] => magda_h@domain.example, [2] => ydg@domain.example ), Array ( [0] => johnsmith, [1] => magdah, [2] => ydegaulle )
Notes:
- The array indices are numeric starting from zero.
Multi-Row Results
Each of these results functions will return multiple records from the database.
| id | name | username | |
|---|---|---|---|
| 1 | John Smith | johnsmith@domain.example | johnsmith |
| 2 | Magda Hellman | magda_h@domain.example | magdah |
| 3 | Yvonne de Gaulle | ydg@domain.example | ydegaulle |
loadRowList()
loadRowList() returns an indexed array of indexed arrays from the table records returned by the query:
. . .
$db->setQuery($query);
$row = $db->loadRowList();
print_r($row);
will give (with line breaks added for clarity):
Array ( [0] => Array ( [0] => 1, [1] => John Smith, [2] => johnsmith@domain.example, [3] => johnsmith ), [1] => Array ( [0] => 2, [1] => Magda Hellman, [2] => magda_h@domain.example, [3] => magdah ), [2] => Array ( [0] => 3, [1] => Yvonne de Gaulle, [2] => ydg@domain.example, [3] => ydegaulle ) )
You can access the individual rows by using:
$row['index'] // e.g. $row['2']
and you can access the individual values by using:
$row['index']['index'] // e.g. $row['2']['3']
Notes:
- The array indices are numeric starting from zero.
loadAssocList()
loadAssocList() returns an indexed array of associated arrays from the table records returned by the query:
. . .
$db->setQuery($query);
$row = $db->loadAssocList();
print_r($row);
will give (with line breaks added for clarity):
Array ( [0] => Array ( [id] => 1, [name] => John Smith, [email] => johnsmith@domain.example, [username] => johnsmith ), [1] => Array ( [id] => 2, [name] => Magda Hellman, [email] => magda_h@domain.example, [username] => magdah ), [2] => Array ( [id] => 3, [name] => Yvonne de Gaulle, [email] => ydg@domain.example, [username] => ydegaulle ) )
You can access the individual rows by using:
$row['index'] // e.g. $row['2']
and you can access the individual values by using:
$row['index']['column_name'] // e.g. $row['2']['email']
loadAssocList($key)
loadAssocList('key') returns an associated array - indexed on 'key' - of associated arrays from the table records returned by the query:
. . .
$db->setQuery($query);
$row = $db->loadAssocList('username');
print_r($row);
will give (with line breaks added for clarity):
Array ( [johnsmith] => Array ( [id] => 1, [name] => John Smith, [email] => johnsmith@domain.example, [username] => johnsmith ), [magdah] => Array ( [id] => 2, [name] => Magda Hellman, [email] => magda_h@domain.example, [username] => magdah ), [ydegaulle] => Array ( [id] => 3, [name] => Yvonne de Gaulle, [email] => ydg@domain.example, [username] => ydegaulle ) )
You can access the individual rows by using:
$row['key_value'] // e.g. $row['johnsmith']
and you can access the individual values by using:
$row['key_value']['column_name'] // e.g. $row['johnsmith']['email']
Note: Key must be a valid column name from the table; it does not have to be an Index or a Primary Key. But if it does not have a unique value you may not be able to retrieve results reliably.
loadAssocList($key, $column)
loadAssocList('key', 'column') returns an associative array, indexed on 'key', of values from the column named 'column' returned by the query:
. . .
$db->setQuery($query);
$row = $db->loadAssocList('id', 'username');
print_r($row);
will give (with line breaks added for clarity):
Array ( [1] => John Smith, [2] => Magda Hellman, [3] => Yvonne de Gaulle, )
Note: Key must be a valid column name from the table; it does not have to be an Index or a Primary Key. But if it does not have a unique value you may not be able to retrieve results reliably.
loadObjectList()
loadObjectList() returns an indexed array of PHP objects from the table records returned by the query:
. . .
$db->setQuery($query);
$row = $db->loadObjectList();
print_r($row);
will give (with line breaks added for clarity):
Array (
[0] => stdClass Object ( [id] => 1, [name] => John Smith,
[email] => johnsmith@domain.example, [username] => johnsmith ),
[1] => stdClass Object ( [id] => 2, [name] => Magda Hellman,
[email] => magda_h@domain.example, [username] => magdah ),
[2] => stdClass Object ( [id] => 3, [name] => Yvonne de Gaulle,
[email] => ydg@domain.example, [username] => ydegaulle )
)You can access the individual rows by using:
$row['index'] // e.g. $row['2']
and you can access the individual values by using:
$row['index']->name // e.g. $row['2']->email
loadObjectList($key)
loadObjectList('key') returns an associated array - indexed on 'key' - of objects from the table records returned by the query:
. . .
$db->setQuery($query);
$row = $db->loadObjectList('username');
print_r($row);
will give (with line breaks added for clarity):
Array (
[johnsmith] => stdClass Object ( [id] => 1, [name] => John Smith,
[email] => johnsmith@domain.example, [username] => johnsmith ),
[magdah] => stdClass Object ( [id] => 2, [name] => Magda Hellman,
[email] => magda_h@domain.example, [username] => magdah ),
[ydegaulle] => stdClass Object ( [id] => 3, [name] => Yvonne de Gaulle,
[email] => ydg@domain.example, [username] => ydegaulle )
)You can access the individual rows by using:
$row['key_value'] // e.g. $row['johnsmith']
and you can access the individual values by using:
$row['key_value']->column_name // e.g. $row['johnsmith']->email
Note: Key must be a valid column name from the table; it does not have to be an Index or a Primary Key. But if it does not have a unique value you may not be able to retrieve results reliably.
Miscellaneous Result Set Methods
getNumRows()
getNumRows() will return the number of result rows found by the last SELECT or SHOW query and waiting to be read. To get a result from getNumRows() you have to run it after the query and before you have retrieved any results. To retrieve the number of rows affected by a INSERT, UPDATE, REPLACE or DELETE query, use getAffectedRows().
. . .
$db->setQuery($query);
$db->execute();
$num_rows = $db->getNumRows();
print_r($num_rows);
$result = $db->loadRowList();
will return
3
Note: getNumRows() is only valid for statements like SELECT or SHOW that return an actual result set. If you run getNumRows() after loadRowList() - or any other retrieval method - you will get a PHP Warning:
Warning: mysql_num_rows(): 80 is not a valid MySQL result resource in libraries\joomla\database\database\mysql.php on line 344