Pagina 1 di 1

Domanda teorica

Inviato: 28/07/2010, 1:06
da BMercer
Ok, allora mettiamo di avere una classe per il database che contiene soltando la funzione di costruct di destruct, di query personalizzata, di fetch dei risultati e di liberamento di risultati con free_result.
Il tutto va alquanto bene, dentro la funzione di destruct creiamo la connessione che poi gestiamo con le altre funzioni.

Ma arriva il momento in cui quella classe deve essere espansa per permettere la gestione degli utenti (a cui dedichiamo una tabella nel database) solo con le funzioni. E' ovvio che ci servono le nostre funzioni all'interno della classe del database quindi scriviamo

Codice: Seleziona tutto

class user extends database
ora però abbiamo bisogno di una funzione di costruct anche qui che ci permetta di gestire un utente alla volta.
Creaimo una funzione che ricavi tutte le informazioni dell'utente dal database con una select e che le stampi chiamata get_info().

Perfetto, quindi apriamo una nuova pagina e scriviamo:

Codice: Seleziona tutto

include('database.php'); // dove c'è la classe database
include('users.php'); // dove c'è la classe per gli utenti

$db = new database('localhost', 'username', 'password', 'database');
$u = new user(1); // nel costruct passiamo come variabile sempre l'id dell'utente
$u = get_info();
unset($u);
unset($db);
Però sorge un problema. Sembra, anzi è quasi sicuro che sorgano dei conflitti con i due costruct, poichè sembra che il primo costruct della classe database venga ignorato, infatti quello creava il link (come descritto ufficialmente da php.net che dice che sarebbe buona cosa associare la connessione ad un link che poi viene usato come secondo parametro per esempio nelle query mysql_query($sql, $link)) e l'errore mi dice che non è settato alcun link.

Mettiamo il caso che il costruct per la classe user è di obbligo cosa mi consigliate di fare?
Mettendo invece il caso che la funzione costruct della classe user possa venir eliminata, secondo voi potrebbe funzionare come sistema di gestione utenti? Ve ne sono di migliori?

Per favore rispondete ad entrambe le mie ultime 2 domande.
Grazie :)

Re: Domanda teorica

Inviato: 28/07/2010, 21:34
da Carlo
Credo che il conflitto sia qui:

Codice: Seleziona tutto

$db = new database('localhost', 'username', 'password', 'database');
$u = new user(1); // nel costruct passiamo come variabile sempre l'id dell'utente
Prima crei l'oggetto $db per la classe database, e poi crei un nuovo oggetto per la classe user che a sua volta contiene le funzioni della classe database? A quale scopo? Hai solo delle "doppie" funzioni.
Per utilizzare le funzioni della classe database all'interno di user basta che utilizzi l'oggetto $db.

Poi un'altra cosa: mi puoi riportare la funzione della classe database per connetterti al database, e poi la funzione get_info, che presumo sia della classe user?
BMercer ha scritto:Mettiamo il caso che il costruct per la classe user è di obbligo cosa mi consigliate di fare?
Mettendo invece il caso che la funzione costruct della classe user possa venir eliminata, secondo voi potrebbe funzionare come sistema di gestione utenti? Ve ne sono di migliori?
Per queste due domande puoi spiegarti meglio? Non mi sono ben chiare.

Re: Domanda teorica

Inviato: 28/07/2010, 22:37
da BMercer
La mia intenzione era separare bene le classi del database, quella principale chiamata database, poi quella per gestire i topic chiamata topic, quella per gestire i post, quella per gestire i forum, quella per gestire gli utenti.
Tutte quante figlie della classe database che come detto contiene le funzioni per connessione (con __costruct), per l'eseguezione delle query, per il fetch dei risultati e per la liberazione mediante mysql_free_result() delle query giganti. Tutte funzioni che in determinati perti del mio cms vorrei non fossero disponibili, quindi in quelle parti utilizzo solo le subclassi figlie in modo che al limite il massimo che si può fare è eseguire comandi preimpostati che quindi limitano di gran lunga i rischi. Alla fine ho deciso di togliere il costruct della classe figlia e mi aveva dato un altro errore che ora come ora non ricordo, non relativo alle parentele comunque. Ti farò sapere domani.

Re: Domanda teorica

Inviato: 29/07/2010, 19:01
da BMercer
Allora ho provato così:
Ho creato la classe del database come già detto con le funzioni che verranno utilizzate dalle classi figlie.
Ho creato dentro la classe del database il costruct e decostruct che rispettivamente apre e chiude la connessione senza il passaggio di alcun parametro, quindi semplicemente così:

Codice: Seleziona tutto

$db = new database;
Poi ho creato le subclassi utenti, forum, topic, post e ho scoperto con mio grande stupore e felicità che senza istanziare la classe database (che quindi a questo punto credo trasformerò in astratta o cose simili, o no?) ma istanziando solo una subclasse, ad esempio così:

Codice: Seleziona tutto

$u = new users;
$u->create_new($username, $password, $email, $avatar, ecc...);
unset($u);
viene richiamato il costruct della classe database.
Quindi le 3 linee sopra automaticamente aprono la connession non appena è istanziata, eseguono la funzione per creare un nuovo utente e disconnettono dal database. E' una cosa che a mio parere oltre che essere molto funzionale è anche molto sicura. Ti basta istanziare una classe alla volta e ogni volta che istanzi una subclasse si connette al database.
Esempio totale:
Classe database

Codice: Seleziona tutto

class database 
{
private $link;

protected function __costruct()
{
$link = mysql_connect(parametri...);
$this->link = link;
mysql_db_select(nome database);
}

protected function __destruct()
{
mysql_close($this->link);
}

// lista funzioni
protected function query($sql)
{
mysql_query($sql, $this->link);
}

ecccc....

}

Classe utenti

Codice: Seleziona tutto

class user extends database
{

public function create_new($username, $password)
{
$this->query('
      INSERT INTO utenti blablablbal
');
}

}
Ora facendo così:

Codice: Seleziona tutto

$u = new user; // qui viene richiamata la funzione __ costruct
$u->create_new($_POST['username'], $_POST['password']); // qui esegue la funzione che devi eseguire
unset($u); // richiama la funzione __destruct
Poichè creare 2 subclassi diverse senza chiuderne una provoca un errore di collisione ti verrà sempre in mente di attuare le modifiche al database e poi chiudere la connessione dietro di te.

Non so, non riesco a vedere le falle di questo ragionamento o non ci sono?

Re: Domanda teorica

Inviato: 29/07/2010, 21:47
da Carlo
BMercer ha scritto:Poichè creare 2 subclassi diverse senza chiuderne una provoca un errore di collisione ti verrà sempre in mente di attuare le modifiche al database e poi chiudere la connessione dietro di te.

Non so, non riesco a vedere le falle di questo ragionamento o non ci sono?
Non ti seguo più. :/

Re: Domanda teorica

Inviato: 30/07/2010, 0:47
da BMercer
Va bè, òascia stare le ultime due righe non sono importanti.
Secondo te potrebbe funzionare come sistema?

Re: Domanda teorica

Inviato: 30/07/2010, 8:43
da Carlo
Però io dico, a che serve "estendere" (per così dire) la classe "database" nella nuova classe "user"?

Una volta che hai creato gli oggetti per entrambe le classi:

Codice: Seleziona tutto

$db = new database;
$user = new user;
all'interno della classe classe "user", poi puoi utilizzare, nelle funzioni, la variabile globale $db per accedere alle funzioni della classe "database".

E quindi se vuoi estrarre dei dati dal database, fai così: mysql_query($sql, $db->link);

Ultima cosa. Io non "distruggo" mai gli oggetti a fine script. E' possibile, caso mai, per connettersi o chiudere una connessione al database, creare una funzione apposita.

Re: Domanda teorica

Inviato: 30/07/2010, 14:48
da BMercer
Mi potresti illuminare un pò di più riguardo al porre la classe db come globale? Credo che sia anche il sistema che usa phpbb o no?

Re: Domanda teorica

Inviato: 30/07/2010, 16:47
da Carlo
Sì. Devi semplicemente aggiungere in ogni funzione della classe "user", prima che richiami le funzioni dell'oggetto "database", questo:

Codice: Seleziona tutto

global $db;
che ti permetterà di usufruire al suo interno delle funzioni della classe "database".

Re: Domanda teorica

Inviato: 30/07/2010, 17:01
da BMercer
Ho letto in giro che la keyword global è il diavolo. C'è chi dice che è poco sicuro, c'è chi dice che se la inserisci si crea un buco nero ecc.
Alla fine ho risolto con un sistema molto pratico e nativo solo da php5 : il class chaining.
Ovvero dentro il costruttore della classe user inserisco l'istanza della classe così:

Codice: Seleziona tutto

class user
{
private $db;
public function __construct()
{
$this->db = new database;
}
}
e poi all'interno posso utilizzare le funzioni di tale classe con

Codice: Seleziona tutto

$this->db->query():
Grazie mille come sempre.