Nette Documentation Preview

syntax
Nette Database
**************

.[perex]
Nette Database è un livello di accesso al database per PHP potente ed elegante, concentrato sulla semplicità e su funzionalità intelligenti. Offre due modi di lavorare con il database: l'[Explorer |explorer] per uno sviluppo rapido delle applicazioni, oppure l'[approccio SQL |SQL way] per il controllo diretto delle query.

<div class="grid gap-3">
<div>


[Approccio SQL|sql-way]
=======================
- Query sicure e parametrizzate
- Controllo preciso sulla struttura della query SQL
- Quando scrivete query complesse con funzioni avanzate
- Ottimizzate le prestazioni con funzioni SQL specifiche

</div>

<div>


[Explorer |explorer]
====================
- Sviluppate rapidamente senza scrivere SQL
- Gestione intuitiva delle relazioni tra le tabelle
- Approfittate dell'ottimizzazione automatica delle query
- Adatto a un lavoro rapido e comodo con il database

</div>

</div>


Installazione
=============

La libreria si scarica e si installa con [Composer|best-practices:composer]:

```shell
composer require nette/database
```


Database supportati
===================

Nette Database supporta questi database:

|* Server di database   |* Nome DSN    |* Supporto Explorer
|-----------------------|--------------|-----------------------|
| MySQL (>= 5.1)        | mysql        | SÌ                    |
| PostgreSQL (>= 9.0)   | pgsql        | SÌ                    |
| SQLite 3 (>= 3.8)     | sqlite       | SÌ                    |
| Oracle                | oci          | NO                    |
| MS SQL (PDO_SQLSRV)   | sqlsrv       | SÌ                    |
| MS SQL (PDO_DBLIB)    | mssql        | NO                    |
| ODBC                  | odbc         | NO                    |


Due approcci al lavoro con il database
======================================

Nette Database vi lascia scegliere: potete scrivere le query SQL direttamente (approccio SQL), oppure lasciare che vengano generate automaticamente (Explorer). Vediamo come i due approcci risolvono gli stessi compiti:

[Approccio SQL|sql-way] - query SQL

```php
// inserimento di un record
$database->query('INSERT INTO books', [
	'author_id' => $authorId,
	'title' => $bookData->title,
	'published_at' => new DateTime,
]);

// ottenimento dei record: autori dei libri
$result = $database->query('
	SELECT authors.*, COUNT(books.id) AS books_count
	FROM authors
	LEFT JOIN books ON authors.id = books.author_id
	WHERE authors.active = 1
	GROUP BY authors.id
');

// visualizzazione (non ottimale, genera N query aggiuntive)
foreach ($result as $author) {
	$books = $database->query('
		SELECT * FROM books
		WHERE author_id = ?
		ORDER BY published_at DESC
	', $author->id);

	echo "L'autore $author->name ha scritto $author->books_count libri:\n";

	foreach ($books as $book) {
		echo "- $book->title\n";
	}
}
```

[Approccio Explorer|explorer] - generazione automatica dell'SQL

```php
// inserimento di un record
$database->table('books')->insert([
	'author_id' => $authorId,
	'title' => $bookData->title,
	'published_at' => new DateTime,
]);

// ottenimento dei record: autori dei libri
$authors = $database->table('authors')
	->where('active', 1);

// visualizzazione (genera automaticamente solo 2 query ottimizzate)
foreach ($authors as $author) {
	$books = $author->related('books')
		->order('published_at DESC');

	echo "L'autore $author->name ha scritto {$books->count()} libri:\n";

	foreach ($books as $book) {
		echo "- $book->title\n";
	}
}
```

L'approccio Explorer genera e ottimizza le query SQL automaticamente. Nell'esempio sopra l'approccio SQL genera N+1 query (una per gli autori e poi una per i libri di ogni autore), mentre Explorer ottimizza automaticamente le query ed esegue solo due: una per gli autori e una per tutti i loro libri.

I due approcci si possono combinare liberamente nella vostra applicazione secondo le necessità.


Connessione e configurazione
============================

Per connettervi al database basta creare un'istanza della classe [api:Nette\Database\Connection]:

```php
$database = new Nette\Database\Connection($dsn, $user, $password);
```

Il parametro `$dsn` (Data Source Name) è lo stesso [usato da PDO |https://www.php.net/manual/en/pdo.construct.php#refsect1-pdo.construct-parameters], per esempio `host=127.0.0.1;dbname=test`. In caso di fallimento lancia una `Nette\Database\ConnectionException`.

Un modo più comodo lo offre però la [configurazione dell'applicazione |configuration], dove basta aggiungere la sezione `database`. Vengono così creati gli oggetti necessari e anche il pannello del database nella barra di [Tracy |tracy:].

```neon
database:
	dsn: 'mysql:host=127.0.0.1;dbname=test'
	user: root
	password: password
```

L'oggetto della connessione si può poi [ottenere come servizio dal container DI |dependency-injection:passing-dependencies], per esempio:

```php
class Model
{
	public function __construct(
		// oppure Nette\Database\Explorer
		private Nette\Database\Connection $database,
	) {
	}
}
```

Maggiori informazioni sulla [configurazione del database|configuration].


Creazione manuale dell'Explorer
-------------------------------

Se non usate il container DI di Nette, potete creare a mano un'istanza di `Nette\Database\Explorer`:

```php
// connessione al database
$connection = new Nette\Database\Connection('mysql:host=127.0.0.1;dbname=mydatabase', 'user', 'password');
// storage della cache, implementa Nette\Caching\Storage, per esempio:
$storage = new Nette\Caching\Storages\FileStorage('/percorso/verso/temp/dir');
// si occupa della reflection della struttura del database
$structure = new Nette\Database\Structure($connection, $storage);
// definisce le regole per mappare nomi di tabelle, colonne e chiavi esterne
$conventions = new Nette\Database\Conventions\DiscoveredConventions($structure);
$explorer = new Nette\Database\Explorer($connection, $structure, $conventions, $storage);
```


Gestione della connessione
==========================

Quando si crea l'oggetto `Connection`, la connessione viene stabilita automaticamente. Se volete rimandare la connessione, usate la modalità lazy: attivatela nella [configurazione|configuration] impostando `lazy`, oppure così:

```php
$database = new Nette\Database\Connection($dsn, $user, $password, ['lazy' => true]);
```

Per gestire la connessione usate i metodi `connect()`, `disconnect()` e `reconnect()`.
- `connect()` crea la connessione se non esiste già e può lanciare una `Nette\Database\ConnectionException`.
- `disconnect()` chiude la connessione corrente al database.
- `reconnect()` esegue la disconnessione e la successiva riconnessione al database. Anche questo metodo può lanciare una `Nette\Database\ConnectionException`.

Potete inoltre seguire gli eventi legati alla connessione con l'evento `onConnect`, che è un array di callback richiamati dopo che la connessione al database è stata stabilita.

```php
// viene eseguito dopo la connessione al database
$database->onConnect[] = function($database) {
	echo "Connesso al database";
};
```

In modo analogo funziona l'evento `onQuery`: è un array di callback richiamati dopo ogni query eseguita (e quando una query fallisce), utile per il logging o il profiling.


Tracy Debug Bar
===============

Se usate [Tracy |tracy:], il pannello Database nella Debug Bar si attiva automaticamente. Mostra tutte le query eseguite, i loro parametri, il tempo di esecuzione e il punto del codice da cui sono state richiamate.

[* db-panel.webp *]

Nette Database

Nette Database è un livello di accesso al database per PHP potente ed elegante, concentrato sulla semplicità e su funzionalità intelligenti. Offre due modi di lavorare con il database: l'Explorer per uno sviluppo rapido delle applicazioni, oppure l'approccio SQL per il controllo diretto delle query.

Approccio SQL

  • Query sicure e parametrizzate
  • Controllo preciso sulla struttura della query SQL
  • Quando scrivete query complesse con funzioni avanzate
  • Ottimizzate le prestazioni con funzioni SQL specifiche

Explorer

  • Sviluppate rapidamente senza scrivere SQL
  • Gestione intuitiva delle relazioni tra le tabelle
  • Approfittate dell'ottimizzazione automatica delle query
  • Adatto a un lavoro rapido e comodo con il database

Installazione

La libreria si scarica e si installa con Composer:

composer require nette/database

Database supportati

Nette Database supporta questi database:

Server di database Nome DSN Supporto Explorer
MySQL (>= 5.1) mysql
PostgreSQL (>= 9.0) pgsql
SQLite 3 (>= 3.8) sqlite
Oracle oci NO
MS SQL (PDO_SQLSRV) sqlsrv
MS SQL (PDO_DBLIB) mssql NO
ODBC odbc NO

Due approcci al lavoro con il database

Nette Database vi lascia scegliere: potete scrivere le query SQL direttamente (approccio SQL), oppure lasciare che vengano generate automaticamente (Explorer). Vediamo come i due approcci risolvono gli stessi compiti:

Approccio SQL – query SQL

// inserimento di un record
$database->query('INSERT INTO books', [
	'author_id' => $authorId,
	'title' => $bookData->title,
	'published_at' => new DateTime,
]);

// ottenimento dei record: autori dei libri
$result = $database->query('
	SELECT authors.*, COUNT(books.id) AS books_count
	FROM authors
	LEFT JOIN books ON authors.id = books.author_id
	WHERE authors.active = 1
	GROUP BY authors.id
');

// visualizzazione (non ottimale, genera N query aggiuntive)
foreach ($result as $author) {
	$books = $database->query('
		SELECT * FROM books
		WHERE author_id = ?
		ORDER BY published_at DESC
	', $author->id);

	echo "L'autore $author->name ha scritto $author->books_count libri:\n";

	foreach ($books as $book) {
		echo "- $book->title\n";
	}
}

Approccio Explorer – generazione automatica dell'SQL

// inserimento di un record
$database->table('books')->insert([
	'author_id' => $authorId,
	'title' => $bookData->title,
	'published_at' => new DateTime,
]);

// ottenimento dei record: autori dei libri
$authors = $database->table('authors')
	->where('active', 1);

// visualizzazione (genera automaticamente solo 2 query ottimizzate)
foreach ($authors as $author) {
	$books = $author->related('books')
		->order('published_at DESC');

	echo "L'autore $author->name ha scritto {$books->count()} libri:\n";

	foreach ($books as $book) {
		echo "- $book->title\n";
	}
}

L'approccio Explorer genera e ottimizza le query SQL automaticamente. Nell'esempio sopra l'approccio SQL genera N+1 query (una per gli autori e poi una per i libri di ogni autore), mentre Explorer ottimizza automaticamente le query ed esegue solo due: una per gli autori e una per tutti i loro libri.

I due approcci si possono combinare liberamente nella vostra applicazione secondo le necessità.

Connessione e configurazione

Per connettervi al database basta creare un'istanza della classe Nette\Database\Connection:

$database = new Nette\Database\Connection($dsn, $user, $password);

Il parametro $dsn (Data Source Name) è lo stesso usato da PDO, per esempio host=127.0.0.1;dbname=test. In caso di fallimento lancia una Nette\Database\ConnectionException.

Un modo più comodo lo offre però la configurazione dell'applicazione, dove basta aggiungere la sezione database. Vengono così creati gli oggetti necessari e anche il pannello del database nella barra di Tracy.

database:
	dsn: 'mysql:host=127.0.0.1;dbname=test'
	user: root
	password: password

L'oggetto della connessione si può poi ottenere come servizio dal container DI, per esempio:

class Model
{
	public function __construct(
		// oppure Nette\Database\Explorer
		private Nette\Database\Connection $database,
	) {
	}
}

Maggiori informazioni sulla configurazione del database.

Creazione manuale dell'Explorer

Se non usate il container DI di Nette, potete creare a mano un'istanza di Nette\Database\Explorer:

// connessione al database
$connection = new Nette\Database\Connection('mysql:host=127.0.0.1;dbname=mydatabase', 'user', 'password');
// storage della cache, implementa Nette\Caching\Storage, per esempio:
$storage = new Nette\Caching\Storages\FileStorage('/percorso/verso/temp/dir');
// si occupa della reflection della struttura del database
$structure = new Nette\Database\Structure($connection, $storage);
// definisce le regole per mappare nomi di tabelle, colonne e chiavi esterne
$conventions = new Nette\Database\Conventions\DiscoveredConventions($structure);
$explorer = new Nette\Database\Explorer($connection, $structure, $conventions, $storage);

Gestione della connessione

Quando si crea l'oggetto Connection, la connessione viene stabilita automaticamente. Se volete rimandare la connessione, usate la modalità lazy: attivatela nella configurazione impostando lazy, oppure così:

$database = new Nette\Database\Connection($dsn, $user, $password, ['lazy' => true]);

Per gestire la connessione usate i metodi connect(), disconnect() e reconnect().

  • connect() crea la connessione se non esiste già e può lanciare una Nette\Database\ConnectionException.
  • disconnect() chiude la connessione corrente al database.
  • reconnect() esegue la disconnessione e la successiva riconnessione al database. Anche questo metodo può lanciare una Nette\Database\ConnectionException.

Potete inoltre seguire gli eventi legati alla connessione con l'evento onConnect, che è un array di callback richiamati dopo che la connessione al database è stata stabilita.

// viene eseguito dopo la connessione al database
$database->onConnect[] = function($database) {
	echo "Connesso al database";
};

In modo analogo funziona l'evento onQuery: è un array di callback richiamati dopo ogni query eseguita (e quando una query fallisce), utile per il logging o il profiling.

Tracy Debug Bar

Se usate Tracy, il pannello Database nella Debug Bar si attiva automaticamente. Mostra tutte le query eseguite, i loro parametri, il tempo di esecuzione e il punto del codice da cui sono state richiamate.