MVC modeli sebat eklemek için en iyi yöntem nedir?

5 Cevap php

PHP bir ultra-hafif bir MVC framework uygulanması sürecinde yaşıyorum. Bir veritabanından veri yükleme, vb Modelin bağımsız olmalıdır dosya ortak bir görüş gibi görünüyor, ve ben katılıyorum. Ne ben emin değilim MVC içine bu "veri katmanı" bağlantı için en iyi yoldur.


Datastore interacts with Model

//controller
public function update()
{

 $model = $this->loadModel('foo');
 $data = $this->loadDataStore('foo', $model);

 $data->loadBar(9); //loads data and populates Model
 $model->setBar('bar');
 $data->save(); //reads data from Model and saves

}

Controller mediates between Model and Datastore

Biraz ayrıntılı görünüyor ve bir veri deposu var olduğunu bilmek modeli gerektirir.

//controller
public function update()
{

 $model = $this->loadModel('foo');
 $data = $this->loadDataStore('foo');

 $model->setDataStore($data);

 $model->getDataStore->loadBar(9); //loads data and populates Model
 $model->setBar('bar');
 $model->getDataStore->save(); //reads data from Model and saves

}

Datastore extends Model

Biz flatfile datastore'una için bir veritabanı veri deposuna uzanan bir Model kaydetmek isterseniz ne olur?

//controller
public function update()
{

 $model = $this->loadHybrid('foo'); //get_class == Datastore_Database

 $model->loadBar(9); //loads data and populates
 $model->setBar('bar');
 $model->save(); //saves

}

Model extends datastore

Bu Model taşınabilirlik için izin verir, ama böyle uzatmak için yanlış görünüyor. Ayrıca, datastore Model'in yöntemlerden herhangi birinin kullanımı yapamazsınız.

//controller extends model
public function update()
{

 $model = $this->loadHybrid('foo');  //get_class == Model

 $model->loadBar(9); //loads data and populates
 $model->setBar('bar');
 $model->save(); //saves

}

EDIT: Model communicates with DAO

//model
public function __construct($dao)
{
    $this->dao = $dao;
}

//model
public function setBar($bar)
{
    //a bunch of business logic goes here
    $this->dao->setBar($bar);
}

//controller
public function update()
{
    $model = $this->loadModel('foo');
    $model->setBar('baz');
    $model->save();
}


Veya alternatif - - "iyi" seçeneği herhangi bir giriş en takdir edilmektedir.

5 Cevap

Ben bir datastore sınıf ile benim modeli dekorasyon sona erdi:

//datastore class
public function __call($name, $arguments)
{

	if (!method_exists($this->model, $name))
		throw new Exception('does not exist!');

	return call_user_func_array(array($this->model, $name), $arguments);

}

//controller - decorating
$model = new Model;
$datastore = new Datastore($model);
$datastore->actions();

Ben denetleyicisi aittir sanmıyorum - gerçekten gelip gidebilir görünümün parçası, var. Iş mantığı ve sebat görünümünde veya denetleyici bağlı olmamalıdır.

Ayrı bir servis katmanı size (örn., mobil manzaralı, toplu işlem) non-tarayıcı tabanlı müşterilere dağıtılmış bileşenler olarak bu mantık göstermek için şans verir

Ben miras bir IS-A ilişkisi olduğundan modeli, nesne yönelimli bir anlamda veri deposunu uzatmak olmazdı. Belirttiğiniz gibi, modeli bir ilişkisel veritabanı değil; bu sadece bilgi ısrarcı için birçok arasında bir seçimdir.

Ben daha kompozisyon olduğunu düşünüyorum. Sebat katman onlar daha uzun ömürlü olduğu bilincinde olmasını gerektirmeden modeli nesneleri devam ayrı bir DAO olabilir. VEYA bir modeli CRUD işlemleri olduğu gerçeğini tanıtır mixin davranış var, ama sadece kendilerine verilen konum uygulanması istekleri kapalı geçer.

Her zamanki Bahar deyim kontrolör ayrı olan bir hizmet katman olurdu. Bu kullanım durumları ve iş birimleri biliyor. Bu kullanım davanın hedefleri gerçekleştirmek için bir model ve sebat nesneleri kullanır.

MVC üç aktörler anlamına gelir. Ben tipik bir uygulamada daha fazla katman vardır söyleyebilirim - sebat ve hizmet eklenmesi gerekir.

GÜNCELLEME:

Modeli nesne kalıcılık paketinden şey almak değilse, o zaman olursa olsun bunu hiçbir bilgiye sahip. İşte bir örnek, basit bir model sınıf Kişi ve DAO arayüzü, kendi paketinde her kullanarak bulunuyor:

package persistence.model;

public class Person
{
    private String name;

    public Person(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}

DAO arayüz modeli paketi ithal, ama etrafında başka bir yol olduğunu unutmayın:

package persistence.persistence;

import persistence.model.Person;

import java.util.List;

public interface PersonDao
{
    Person find(Long id);
    List<Person> find();

    void saveOrUpdate(Person p);
}

RedBeanPHP uses a system called Fuse to solve this problem. (details on wiki: http://redbeanphp.com/community/wiki/index.php/Fuse )

//Controller
$foo = R::load("foo", 9);
$foo->bar = "bar";
R::store( $foo );

İşte size modeli aslında bir fasulye başka bir şey değildir. Ancak sistem talep üzerine tam teşekküllü bir model ile fasulye sigortalar.

class Model_Foo extends RedBean_SimpleModel {
  public function update() {
    if ($this->bar!="bar") do something... 
  }
}

Çerçeve anında tip "foo" fasulye Model_Foo bağlanır ve sadece kaydetmeden önce update () yöntemini çağırır. Eğer iş kuralları saklayabilirsiniz yerdir. Güncelleştirmenin yanı sıra (), ayrıca açık () kullanın ve silebilirsiniz ().

Modelin rota aşağı gidiyor veri deposuna uzanır için benim oyum. Bu en doğal görünüyor, çünkü yürürlükte modeliniz yatan veri deposuna ait is bir uzantısıdır. Ancak, elde edilen nesnenin tüketimi ile model nesne oluşturulmasını ayrıştırmak için bir Hizmet tasarım deseni kullanmak isteyebilirsiniz.

class Model {
   protected $_tablename == __CLASSNAME__; // or some derivative of the classname
   protected $_datastore;
   protected $_typeOfDataStore;

   function __construct( $type == 'mysql' ) { 
      $this->_typeOfDataStore = $type;
      $this->bindToDataStore();
   }

   function bindToDataStore( $ds ) { 
      $this->_datastore = DataStoreFactory::buildDataStore( $this->_typeOfDataStore );
   }

}

class DataStoreFactory {

   function buildDataStore( $type ) {
     switch ( $type ) {
       case 'flatfile' : return new FlatFileDataStore();
       case 'mysql': return new MySQLDataStore();
     }
   }
}

class DataStoreBase {
   function connect() { }
   function disconnect() { }
   function getData() { }
   // ...
} 

class FlatFileDataStore extends DataStoreBase { }
class MySQLDataStore extends DataStoreBase { 
   function runQuery() { }
}

Bu yapı parçası. Eğer yeni bir modeli uygulamaya / oluşturmanız gerektiğinde, sadece modeli uzatabilirsiniz:

class Users extends Model {
   protected $_tablename = 'users';
   protected $_typeOfDataStore = 'flatfile';

   function getAllUsers() {
      return $this->runQuery( "SELECT * FROM " . $this->_tablename );
   }

}

Ve denetleyicisi:

$usersModel = new Users();
$usersModel->getAllUsers();

Eğer datastore Model'in yöntemlerden herhangi birini kullanmak mümkün olmakla ilgili işaret itiraz sistemi üzerinde iyi bir sınırlamadır. Model veri deposuna bir tüketici olduğunu ve bu nedenle veri deposuna doğrudan modeli nesnenin işlevleri çağırmak mümkün olmamalıdır. Model kontrol korumak ve buna ihtiyacı her datastore servisten faydalanmak gerekir.

Ben çok sıkı isimleri ve kavramlara bağlı bir çerçeve oluşturmak için çalışıyoruz düşünüyorum. Ben Model-View-Controller deyim isimler ve kavramlar katı tanımlanmış değildir bulduk. Ben de o paradigma içinde çalışan kod bazen kuralları esnetmeye edebilmek için ihtiyacı olduğunu tespit ettik.

Model isn't bir Datastore, sadece has a Datastore: @ duffymo Model bileşen hakkında çok önemli bir nokta vardır. Bu, her bir örneği olması gerekiyordu ne bakmak olduğunu düşünmenin bir başka yolu açık değilse. Bir "datastore" nesnesinin bir örneği veri keyfi bir miktarda erişim aracılık bir kaynak temsil eder. Genellikle bir veritabanı bağlantısı olduğunu. Bir "model" nesnesinin bir örneği genellikle birden fazla veri parçaları ile ayrı bir kimlik. Genellikle bir tablodaki bir veritabanı satır temsil eder, ama bir metin dosyasında satır, ya da bir dosya deposunda bir dosya olabilir.

Controller ve View aynı soruda uygulamak ve Model bölümü oldukça farklı bir hayvan olduğunu görebilirsiniz. Sadece bir Kontrolör nesne ve bir View nesnesi normalde bir anda ortaya olacak iken, farklı türlerde birçok farklı model nesneler bir anda varlığı olması oldukça muhtemeldir.

Ne yazık ki, ben de MVC "çerçeveler" bir sürü SQL deyimleri hangi yapmak arkasında bir API katmanı olarak bir "Model" tanımlamak olduğunu biliyoruz. Bu çerçeveler, bir "Model" statik bir sınıf veya bir tek örnek olduğunu ve yakın-yararsız ad bölümleme sağlamak başka bir şey yok. Ve programcılar bir sürü bu mantıklı ve onunla mücadele etmek gerekiyordu düşünüyorum. This is why I recommend you don't MVC deyim adlarını ve kavramları kullanmak.

Yapılandırılmış PHP yazmak için tercih edilen yoldur sadece MVC için sallıyor. Bu dağıtıcı ve denetleyici mantığı üst ve alt HTML biçimlendirmesi vardır. Kontrolörleri ve Görüntüleme genellikle sıkıca bağlanmış ve aynı dosyada koyarak çok PHP-ish, çünkü bu iyi çalışıyor. Evet, görünüm-ish kodunda kontrolör-ish eylemler yapmak değil disiplin sürer, ama ben daha ziyade kendimi çerçeve beni zorlamak zorunda daha yapmak gerekiyor. Bu sayfalar tek başına değil, ancak, ortak mantık bir sürü yer ve hafif bir memuru sistemi gibi şeyleri almak, hatta ortak denetleyici mantığın bütün swathes arayabilirsiniz.

Ancak ortak mantık sağlayan ana şey bir veri soyutlama katmanı - benim cevap üstündeki açıklandığı gibi, temelde Model katmanı. Bir veritabanı işleyicisi, bir "nesne" nesne ve bir "koleksiyon" nesne: Ben yazdım veri soyutlama katmanı temelde üç şey olduğunu.

Veritabanı tutacağı datbasee yaşayan tüm nesneler için DataStore olduğunu. Bu bir sorgu yapmak ve bir yanıt almıyorsanız veritabanına faaliyetleri tek bir yerde tüm böylece asıl amacı bu. Çoğu veritabanı çağrıları nesne çekirdek vardır. Veritabanı tutacağı nesne çekirdek hakkında hiçbir şey bilmiyor: sadece resultsets SQL alır ve döndürür.

The other two objects are designed to be sub-classed and will not work if instantiated themselves. Using inheritance and a special extended declaration (done by a static class method), they know how to turn database data into an object. An instance of an inherited "object" object represents one row of the declared class. It is given an ID upon instantiation, and will query the database when it needs to to retreive its one row of data. It also keeps track of changes and can do a one-row UPDATE when told to. The API it presents is completely devoid of SQL: the object has fields you ->get() and ->set(), and you can ->save() when you're done.

"Koleksiyon" nesne belirli bir nesne satır filtrelenmiş listesini almak için nasıl bilir ve onlar tek tek örneği alındı ​​gibi işlev her biri, uygun olarak ayrı ayrı nesneler içine açmak için nasıl bilir. (Koleksiyon nesnesi aynı zamanda bir nesnenin kendisi olma destekler, ancak şu anda bazı uygulama sınırlamaları gibi nadiren bu özelliği kullanabilirsiniz. Ve ben en çok programcılar sorun doyumsuz var buldum bir kavramdır.)

Çoğu nesneler çekirdek miras kodu ve belirli bir tablo için bildirimleri sadece gerekir.

Sonuna etkisi the controller code bu gibi bariz şeyler yapmak alır olduğunu:

$ticket = Ticket::Create($ticket_id);
$ticket->set('queue', $new_queue);
$ticket->set('queue_changed', date('Y-m-d H:i:s'));
$ticket->save();

Yerine ... gibi opak bir şey:

TicketModel::ChangeTicketQueue($ticket_id, $new_queue);

Bu yaklaşım aynı zamanda diğer alanları veya diğer nesneleri güncelleştirmek olabilir Bilet nesne şeyleri kod sağlar zaman queue alanı değişimleri ve bu alanı değiştirmek yerine her zaman bu bunu yapmak için hatırlamak zorunda, oluşacak her işlev bir biletin kuyruğunu değiştirebilirsiniz. Ayrıca bir bilet için başka yöntemler ekleyebilirsiniz gelir: $ticket->get_queue() return TicketQueue::Create($this->get('queue')); Senin için yapmak için muhtemelen mantıklı olur. Ona Nesne yönelimli programlama iyi değil! :-)

Yani, son soruyu cevaplamak için, ben none sorunuzu yaklaşımların öneriyoruz. Sizin modeli nesneleri denetleyicisi kodu birleşik bir API sunmalıdır ve onların veri depolamak olarak nasıl onlara kalmış. Bir veritabanında ise, o zaman onlar bunu kendi aramaları organize etmek gerekir. Ancak, bir model isn't, bir veri deposuna: Bununla birlikte, iyi olabilir have on.