mirror of
https://github.com/nextcloud/documentation.git
synced 2026-01-03 10:20:02 +07:00
added database examples
This commit is contained in:
@@ -359,27 +359,11 @@ and to the classloader
|
||||
Database Access
|
||||
---------------
|
||||
|
||||
.. note:: The advanced apptemplate doesn't feature a recommended way of doing database queries. We hope this will change with the introduction of the Doctrine ORM.
|
||||
.. note:: This will likely change with the introduction of an ORM
|
||||
|
||||
ownCloud uses a database abstraction layer on top of either MDB2 or PDO, depending on the availability of PDO on the server.
|
||||
|
||||
Apps should always use prepared statements when accessing the database as seen in the following example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$userId = 'tom';
|
||||
$query = \OC_DB::prepare("SELECT * FROM *PREFIX*mytable WHERE user = ?");
|
||||
$result = $query->execute(array($userId));
|
||||
$data = $result->fetchAll();
|
||||
?>
|
||||
|
||||
|
||||
'*PREFIX*' in the query string will be replaced by the configured database table prefix while preparing the query. Arguments for the prepared statement are denoted by a '?' in the query string and passed during execution in an array.
|
||||
|
||||
For more information about MDB2 style prepared statements, please see the `official MDB2 documentation <http://pear.php.net/package/MDB2/docs>`_
|
||||
|
||||
If an app requires additional tables in the database they can be automatically created and updated by specifying them inside :file:`appinfo/database.xml` using MDB2's xml scheme notation where the placeholders '*dbprefix*' and '*dbname*' can be used for the configured database table prefix and database name.
|
||||
Your database schema will be inside :file:`appinfo/database.xml` in MDB2's XML scheme notation where the placeholders '*dbprefix*' and '*dbname*' can be used for the configured database table prefix and database name.
|
||||
|
||||
An example database XML file would look like this:
|
||||
|
||||
@@ -387,46 +371,241 @@ An example database XML file would look like this:
|
||||
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<database>
|
||||
<name>*dbname*</name>
|
||||
<create>true</create>
|
||||
<overwrite>false</overwrite>
|
||||
<charset>utf8</charset>
|
||||
<table>
|
||||
<name>*dbprefix*yourapp_items</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>item_id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
<length>4</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>uid_owner</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>item_name</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>100</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>item_path</name>
|
||||
<type>clob</type>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<name>*dbname*</name>
|
||||
<create>true</create>
|
||||
<overwrite>false</overwrite>
|
||||
<charset>utf8</charset>
|
||||
<table>
|
||||
<name>*dbprefix*yourapp_items</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
<length>4</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>user</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>name</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>100</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>path</name>
|
||||
<type>clob</type>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
</database>
|
||||
|
||||
|
||||
To update the tables used by the app, simply adjust the database.xml file and increase the app version number in :file:`appinfo/version` to trigger an update.
|
||||
|
||||
|
||||
Your database layer should go into the **database/** folder. It's recommended to split your data entities from your database queries. You can do that by creating a very simple PHP object with getters and setters:
|
||||
|
||||
:file:`database/item.php`
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
class Item {
|
||||
|
||||
private $id;
|
||||
private $name;
|
||||
private $path;
|
||||
private $user;
|
||||
|
||||
public function __construct($fromRow=null){
|
||||
if($fromRow){
|
||||
$this->fromRow($fromRow);
|
||||
}
|
||||
}
|
||||
|
||||
public function fromRow($row){
|
||||
$this->id = $row['id'];
|
||||
$this->name = $row['name'];
|
||||
$this->path = $row['path'];
|
||||
$this->user = $row['user'];
|
||||
}
|
||||
|
||||
|
||||
public function getId(){
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getUser(){
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function getPath(){
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
|
||||
public function setId($id){
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function setName($name){
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function setUser($user){
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function setPath($path){
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
All database queries for that object should be put into a wrapper class. The wrapper class could look like this (more method examples are in the advanced_apptemplate):
|
||||
|
||||
:file:`item.wrapper.php`
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
class ItemMapper extends Mapper {
|
||||
|
||||
|
||||
private $tableName;
|
||||
|
||||
/**
|
||||
* @param API $api: Instance of the API abstraction layer
|
||||
*/
|
||||
public function __construct($api){
|
||||
parent::__construct($api);
|
||||
$this->tableName = '*PREFIX*apptemplate_advanced_items';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds an item by id
|
||||
* @throws DoesNotExistException: if the item does not exist
|
||||
* @return the item
|
||||
*/
|
||||
public function find($id){
|
||||
$row = $this->findQuery($this->tableName, $id);
|
||||
return new Item($row);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds an item by user id
|
||||
* @param string $userId: the id of the user that we want to find
|
||||
* @throws DoesNotExistException: if the item does not exist
|
||||
* @return the item
|
||||
*/
|
||||
public function findByUserId($userId){
|
||||
$sql = 'SELECT * FROM ' . $this->tableName . ' WHERE user = ?';
|
||||
$params = array($userId);
|
||||
|
||||
$result = $this->execute($sql, $params)->fetchRow();
|
||||
if($result){
|
||||
return new Item($result);
|
||||
} else {
|
||||
throw new DoesNotExistException('Item with user id ' . $userId . ' does not exist!');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves an item into the database
|
||||
* @param Item $item: the item to be saved
|
||||
* @return the item with the filled in id
|
||||
*/
|
||||
public function save($item){
|
||||
$sql = 'INSERT INTO '. $this->tableName . '(name, user, path)'.
|
||||
' VALUES(?, ?, ?)';
|
||||
|
||||
$params = array(
|
||||
$item->getName(),
|
||||
$item->getUser(),
|
||||
$item->getPath()
|
||||
);
|
||||
|
||||
$this->execute($sql, $params);
|
||||
|
||||
$item->setId($this->api->getInsertId());
|
||||
return $item;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates an item
|
||||
* @param Item $item: the item to be updated
|
||||
*/
|
||||
public function update($item){
|
||||
$sql = 'UPDATE '. $this->tableName . ' SET
|
||||
name = ?,
|
||||
user = ?,
|
||||
path = ?
|
||||
WHERE id = ?';
|
||||
|
||||
$params = array(
|
||||
$item->getName(),
|
||||
$item->getUser(),
|
||||
$item->getPath(),
|
||||
$item->getId()
|
||||
);
|
||||
|
||||
$this->execute($sql, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an item
|
||||
* @param int $id: the id of the item
|
||||
*/
|
||||
public function delete($id){
|
||||
$this->deleteQuery($this->tableName, $id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.. note:: Always use **?** to mark placeholders for arguments in SQL queries and pass the arguments as a second parameter to the execute function to prevent `SQL Injection <http://php.net/manual/en/security.database.sql-injection.php>`_
|
||||
|
||||
**DONT**:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$sql = 'SELECT * FROM ' . $this->tableName . ' WHERE user = ' . $user;
|
||||
$result = $this->execute($sql);
|
||||
|
||||
|
||||
**DO**:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$sql = 'SELECT * FROM ' . $this->tableName . ' WHERE user = ?';
|
||||
$params = array($userId);
|
||||
|
||||
$result = $this->execute($sql, $params);
|
||||
|
||||
For more information about MDB2 style prepared statements, please see the `official MDB2 documentation <http://pear.php.net/package/MDB2/docs>`_
|
||||
|
||||
|
||||
|
||||
Templates
|
||||
---------
|
||||
ownCloud uses its own templating system. Templates reside in the **template/** folder. In every template file you can easily access the template functions listed in :doc:`templates`
|
||||
|
||||
Reference in New Issue
Block a user