Ciao a tutti, spero che questa sia la sezione giusta :P Ho finalmente deciso di passare al magico mondo della programmazione ad oggetti, nello specifico in php, tuttavia sto avendo qualche difficoltà. Più che altro ho difficoltà a capire quali sono le buone e cattive pratiche, come gestire le dipendenze degli oggetti, e più in generale come "pensare" un'applicazione web ad oggetti. Dopo un po' di tempo passato a studiare, mi sono deciso a passare a un proggettino pratico. L'idea è creare un blog con una semplice gestione utenti. In pratica tutti possono visualizzare gli articoli del post e i commenti(compreso chi non è loggato), un utente loggato normale può scrivere commenti e un utente loggato come Admin può inserire/cancellare/modificare i post e i commenti.
Ora io ho scritto un po' di codice che dovrebbe far capire la struttura di quello che ho in mente, è incompleto, non sono gestiti gli errori ecc, quindi prendetelo con le pinze, siamo ancora in fase di "proggettazione" :P. Posto il codice e poi pongo le domande + specifiche.
Classi.php
Codice PHP:
<?
require_once("config.php");
Class Database{
private $db;
public function __constructor(){
$this->Connect();
}
public function Connect(){
$con = mysql_connect($config['host'],$config['user'],$config['password']);
if($con){
//salvo la risorsa
$this->db = $con;
//seleziono il db
if(mysql_select_db($config['db_name'], $this->db))
return true;
}
return false;
}
public function Disconnect(){
if(mysql_close($this->db)
return true;
return false;
}
public function Query($query){
//se sono connesso, procedo con la query
$result = mysql_query($query);
if(!$result)
return false;
return $result;
}
public function NumRows($result){
return mysql_num_rows($result);
}
}//fine classe database
//semplice classe per gestire le sessioni
Class Session {
public function __constructor(){
session_start();
}
public function SetVal($key, $val){
if( empty($key) || empty($val) ){
return false;
}
$_SESSION[$key] = $val;
}
public function GetVal($key){
if(isset($_SESSION[$key]))
return $_SESSION[$key];
return false;
}
public function DelVal($key){
unset($_SESSION[$key]);
}
public function CloseSession(){
$_SESSION = array();
session_destroy();
}
}//fine class session
//Gestisce login e informazioni sull'utente loggato
//Utilizza la classe Database e la classe Session
Class User{
private $db;
private $session;
private $is_logged;
private $is_admin;
private $username;
public function __constructor(Database $db, Session $session){
$this->db = $db;
$this->session = $session;
//Come istanzio la classe Utente
//voglio sapere se l'utente è già loggato (controllo sessione)
//in tal caso popolo gli attributi dell'utente
if($session->GetVal('Login')){
$this->is_logged = $session->GetVal('Login');
$this->username = $session->GetVal('Username');
$this->is_admin = $session->GetVal('Admin');
}
}
public function Login($user,$password){
//confronto i dati nel database
//
//preparo la sessione
$session->SetVal('Login',true);
$session->SetVal('Username',$user);
$session->SetVal('Admin',true);
}
public function IsLogged(){
if(isset($this->is_logged))
return $this->is_logged;
return false;
}
public function IsAdmin(){
if(isset($this->is_admin))
return $this->is_admin;
return false;
}
public function GetUsername(){
if(isset($this->username))
return $this->username;
return false;
}
}//fine class utente
Class Post{
private $title;
private $text;
private $posted_by;
public function __constructor($title, $text, $posted_by){
if(isset($title,$text,$posted_by))
$this->title = $title;
$this->text = $text ;
$this->posted_by = $posted_by ;
//altrimenti se uno dei valori è null, lancio un eccezzione per impedire
// che venga istanziato un post non valido
}
public function GetTitle(){
return $this->title;
}
public function GetText(){
return $this->text;
}
public function GetAuthor(){
return $this->posted_by;
}
}//fine class post
//Gestisce le operazioni che si possono fare con i post (inserimento,
//cancellazione, modifica.
Class PostHandler{
private $db;
private $user;
public function __constructor(Database $db){
$this->title = $title;
$this->post = $post ;
}
//inserisce nuovo post
public function SetPost(Post $post){
$title = $post->GetTitle();
$text = $post->GetText();
$user = $post->GetAuthor();
$result = $db->Query("INSERT INTO Posts VALUE (null,'$title','$text','$user')");
return $result;
}
public function DelPost($id){
}
public function ModPost(Post $post_modificato,$id){
}
//restituisce un array di oggetti Post, prendendo i dati dal db
public function FetchAllPosts(){
}
}//fine Classe PostHandler
?>
Ora, ho fatto una pagina di esempio per vedere come utilizzare le classi. Ho preparato quella che dovrebbe essere la pagina per inserire un nuovo post. Se ci sono dati tramite POST, procede con l'inserimento del post(bisogna anche essere loggati come admin) , altrimenti visualizza il form per la creazione del post.
newpost.php
Codice PHP:
<?php
include("classi.php");
$db = new Database();
$session = new Session();
$user = new User($db,$session)
if($user->IsLogged()){
if($user->IsAdmin()){
//controllo se mi è stato inviato un post da aggiungere
if(isset($_POST['title'],$_POST['text'])){
//pulisco i dati in arrivo e creo l'oggetto post
$user = $user->GetUsername();
$title = mysql_real_escape_string($_POST['title']);
$text = mysql_real_escape_string($_POST['text']);
//il costruttore di post lancia un eccezzione nel caso
//vengano passati dei parametri nulli per prevenire la creazione
//di un post non valido
$post = new Post($title,$text,$user);
//se sono arrivato quì, tutto è andato bene, quindi instanzio
//il PostHandler e procedo con l'inserimento del post nel database
$post_handler = new PostHandler($db);
if($post_handler->SetPost($post) != false)
echo "Post inserito con successo";
else
echo "Si è verificato un errore nell'inserimento del post"
}
else{
//se non sono stati ricevuti dei dati tramite post
//mostro il form per inviare il post da aggiunger
/*
<form action="newpost.php" method="post">
* ........
* </form>
*/
}
}
else
echo "Devi essere un Admin per visualizzare questa pagina";
}
else
echo "Effettua il login per visualizzare questa pagina."
?>
Ora ecco le domande nello specifico:
1) Sono gestite bene le dipendenze? In pratica le classi Database e Session non dipendono da nessuno, alla Classe User invece viene inniettato tramite costruttore un oggetto Database e un oggetto Session, la classe post non dipende da nessuno, e la classe PostHandler ha bisogno del Database.
2) Un post può essere inserito solo da un admin, nel mio caso si occupa lo scrip (newpost.php) a controllare se l'utente è admin o no. E' giusto così o dovrebbe occuparsene la classe stessa di verificare le credenziali dell'utente? quindi nella classe PostHandler, nel metodo SetPost(), dovrei controllare lì che l'utente sia loggato e admin prima di inserire veramente il post nel database? In quel caso però dovrei passargli anche l'oggetto User, cambiando un po' le cose.
3)Lo scopo è di creare codice facilmente modificabile e sopratutto riutilizzabile (per esempio le classi database, session e user), sto procedendo nel modo giusto? C'è qualche approccio migliore al mio progetto?
Non ho ancora pensato ai commenti, ma credo che seguirò lo stesso principio di Post e PostHandler.
Grazie a chiunque si vorrà cimentare in una risposta e chiarirmi un po' le idee su come affrontare questo nuovo (almeno per me) modo di pensare! :)