2009-06-28 8 views
0

J'ai donc une classe d'article comme suit:Extension objet PHP Question

 

class Item 
{ 
    private $db; 
    private $data = array(
     'AltItem1' => null, 
     'AltItem2' => null, 
     'BaseUOM' => null, 
     'Category1' => null, 
     'Category2' => null, 
     'Category3' => null, 
     'Category4' => null, 
     'Iden' => null, 
     'IsHCS' => null, 
     'ItemDesc' => null, 
     'ItemNmbr' => null, 
     'ItemType' => null, 
     'MSDS' => null, 
     'NoteText' => null, 
     'NonStock' => null, 
     'PrcLevel' => null, 
     'TipPrice' => null, 
     'DTM_UpdType' => null, 
     'DTM_UpdDateTime' => null, 
     'DTM_DownloadDateTime' => null, 
     'DTM_UploadDateTime' => null 
    ); 

    public function __construct(mysqli $db, $id = null){ 
     $this->db = $db; 

     if(!empty($id)){ 
      $id = (int)$id; 
      $this->populate($id); 
     } 
    } 

    public function __get($key) 
    { 
     if(array_key_exists($key, $this->data)){ 
      return $this->data[$key]; 
     } 
     error_log("Invalid key '$key'"); 
     return null; 
    } 

    public function __set($key, $value) 
    { 
     if(array_key_exists($key, $this->data)){ 
      $this->data[$key] = $value; 
      return true; 
     } 
     return false; 
    } 

    public function populate($id) 
    { 
     $sql = sprintf(
      "SELECT %s FROM ItemMaster WHERE id = ?", 
      implode(", ", array_keys($this->data)) 
     ); 

     $stmt = $this->db->stmt_init(); 
     $stmt->prepare($sql) or die ("Could not prepare statement:" . $stmt->error); 
     $stmt->bind_param('i', $id); 
     $stmt->execute() or die('exec'); 
     $stmt->store_result(); 
     if($stmt->num_rows == 1) 
     { 
      $params = array(); 
      foreach($this->data as $key => $val){ 
       $params[] = &$this->data[$key]; 
      } 

      call_user_func_array(array($stmt, 'bind_result'), $params); 
      $stmt->fetch(); 
      $return = true; 
     } 
     else{ 
      user_error("No rows returned for id '$id'"); 
      $return = false; 
     } 
     return $return; 
    } 
    public function insert() 
    { 
     $params = $this->data; 
     $values = array(); 

     foreach($params as $param){ 
      $values[] = "?"; 
     } 

     $sql = sprintf(
      "INSERT INTO recurrence (%s) VALUES (%s)", 
      implode(", ", array_keys($params)), 
      implode(", ", $values) 
     ); 

     $stmt = $this->db->stmt_init(); 
     $stmt->prepare($sql) or die ("Could not prepare statement:" . $stmt->error); 

     $types = str_repeat("s", count($params)); 
     array_unshift($params, $types); 
     call_user_func_array(array($stmt, "bind_param"), $params); 

     $stmt->execute(); 

     $stmt->store_result(); 
     $result = $stmt->result_metadata(); 
    } 
    public function update() 
    { 
     $sql = "UPDATE recurrence SET "; 
     $params = array(); 
     foreach($this->data as $key => $value){ 
      $params[] = "$key = ?"; 
     } 
     $sql .= implode(", ", $params) . " WHERE id = ?"; 

     $stmt = $this->db->stmt_init(); 
     $stmt->prepare($sql) or die ("Could not prepare statement:" . $stmt->error); 

     $params = $this->data; 
     $params[] = $this->data['id']; 
     $types = str_repeat("s", count($params)); 
     array_unshift($params, $types); 
     call_user_func_array(array($stmt, "bind_param"), $params); 

     $stmt->execute(); 

     $stmt->store_result(); 
     $result = $stmt->result_metadata(); 
    } 

    } 

Ma question est quelle serait la meilleure façon d'étendre cette classe avec la structure de données comme je l'ai? Je veux essentiellement une autre classe pour un article dans un panier. Donc, certains champs supplémentaires seraient la quantité, l'id du panier, etc. Ou y a-t-il une meilleure façon de le faire sans allonger la classe? Sur une autre note, disons que j'ai une autre variable $ price qui n'est pas stockée directement dans la base de données. Donc, je fais une variable publique, mais je devrais faire des méthodes d'assistance pour y accéder, n'est-ce pas? Si c'est le cas, mon tableau $ data est-il la meilleure solution pour ce type d'article?

Merci d'avance.

Répondre

1

Je ne suis pas 100% sûr de ce type d'utilisation de la variable $data privée que vous pourriez faire, alors ma tendance serait ici d'adopter une approche légèrement différente.

Au lieu de regrouper tous vos champs de données dans une variable privée unique de l'objet, je ferais chaque champ une variable privée elle-même, à savoir:

class Item 
{ 
    private $db; 
    private $AltItem1; 
    private $AltItem2; 
... 
etc. 

Cela immédiatement résoudre votre problème d'avoir des données publiques disponibles champs, vous pouvez simplement déclarer ces champs en tant que membre public. Les membres publics ne nécessitent pas de getter et de setter, donc vous ne devriez pas vous en préoccuper ... vous pouvez simplement y accéder via $this->price (en interne), ou $item->price (en externe). Vous sauve du code. Et ce serait une modification rapide de votre fonction populate() pour définir toutes vos nouvelles propriétés, car tout ce que vous auriez à faire serait de définir $this->$$key au lieu de $this->data[$key]. Maintenant, avec votre utilisation de __set() et __get(), il semble que vous voulez être en mesure d'accéder au membre privé $data même de l'extérieur de l'objet. Il n'y a aucune raison que vous ne puissiez pas continuer en déclarant chaque champ séparément aussi privé. __set() et __get() fonctionnera exactement de la même façon, vous auriez juste besoin d'un ajustement mineur, à savoir:

public function __get($varname) 
{ 
    if ($this->$varname !== null) return $this->varname; 
    error_log("Invalid key '$key'"); 
    return null; 
} 

En prime finale, l'extension de la classe devient plus facile, parce que vous n'avez pas redéclarer tous les champs dans leur intégralité si vous souhaitez remplacer la propriété $data.Vous ajoutez simplement les nouveaux champs de vos enfants en tant que nouveaux membres privés. Donc, je ne suis pas sûr si cela vous facilite la vie, mais je pense que ce serait mon approche.

+0

J'aime cette idée, le seul problème est l'insertion et les méthodes de mise à jour que je viens d'ajouter à la question d'origine. Ils sont un peu bizarres, mais ils rendent les quires bien plus faciles. Est-il possible de lier dans votre méthode d'enregistrement des variables avec mes méthodes d'insertion et de mise à jour. Accordé je pourrais faire une longue requête énorme pour inclure chaque variable mais de cette manière mes méthodes d'insertion et de mise à jour fonctionnent à travers le conseil pour toutes mes classes tant qu'elles ont cette variable de données de $. Qu'est-ce que tu penses? – MackDaddy

1

Si vous avez besoin des détails, je ne peux pas vous aider beaucoup, mais en termes de la logique:

D'un point de conception orientée objet purement de vue, je pense que cela est mieux résolu en créant une classe de panier pour garder une trace des articles. Il pourrait s'agir essentiellement d'une classe wrapper pour une liste d'un tri approprié (spécifique à la langue, et je ne connais pas beaucoup PHP = P).

Je ne vois pas de raison particulière de faire en sorte qu'un article garde une trace du chariot dans lequel il se trouve - dans la plupart des cas, il est plus logique de garder le chariot en stock. (En termes de modélisation du monde réel: les objets gardent-ils la trace du panier dans lequel ils pourraient ou ne pourraient pas être?) Mais les chariots sont simplement des conteneurs pour les articles.)

Je ne suis pas tout à fait sûr de ce que vous êtes Dans votre deuxième question, pourriez-vous élaborer, s'il vous plaît? Désolé, je ne peux pas être plus utile.

David

+0

Merci pour le conseil David. Voici la prémisse de base. J'ai une classe de panier avec un tableau d'éléments. Mais avec ces articles, j'ai aussi besoin de stocker la quantité. Maintenant, pour stocker ce panier dans une base de données, j'ai également besoin de stocker tous les articles et leurs quantités. C'est là que cette extension de classe entre en jeu. L'élément lié au panier est uniquement pour la base de données relationnelle, ce qui facilite mes requêtes. Peut-être que je vais passer la classe des articles de charrette et que tout cela sera géré par la classe de charrette ... Merci pour l'aide! – MackDaddy