MVC çevrimiçi eğitimine giriş. Web Geliştirmeye Uygun Yaklaşım: MVC Modeli

  • 02.08.2019

Tasarım Deseni Model-Görünüm-Denetleyici (MVC) verilerin temsilini, verilerle etkileşime giren yöntemlerden ayrı tutmak için oluşturulmuş bir yazılım mimarisi modelidir.

MVC şeması başlangıçta kişisel bilgisayarlar için geliştirilmiş olsa da, endişelerin kesin olarak tanımlanması ve kodu yeniden kullanma yeteneği nedeniyle web geliştiricileri tarafından uyarlanmış ve yaygın olarak kullanılmaktadır. Program, geliştiricilerin hızlı bir şekilde güncelleme yapmasına, işlevsellik eklemesine veya kaldırmasına olanak tanıyan modüler sistemlerin geliştirilmesini teşvik ediyor.

Bu yazıda, temel ilkeleri anlatacağım, ayrıca bir yapı şemasının tanımına ve basit bir MVC PHP örneğine bakacağım.

MVC nedir

Tasarım deseni, üç ana bölümünden sonra adlandırılır: Model, Görünüm ve Denetleyici. MVC modelinin görsel temsili aşağıdaki gibi görünür: aşağıdaki çizelge:

Şekil, tek yönlü bir veri akışının yapısını ve çeşitli bileşenler arasındaki yolu ve bunların etkileşimini göstermektedir.

modeli

Model, yapı boyunca kullanılan kalıcı bir veri deposudur. Görüntüleme, seçme veya kaydetme için verilere erişim sağlamalıdır. Genel yapıda, "Model", "Görünüm" ve "Kontrolör" bileşenleri arasında bir köprüdür.

Aynı zamanda, Model, View veya Controller bileşenlerine iletildiğinde verilere ne olduğu hakkında hiçbir bağlantıya veya bilgiye sahip değildir. "Model" in tek görevi, verilerin kalıcı depolamada işlenmesi, MVC'nin diğer bileşenlerine iletilen verilerin aranması ve hazırlanmasıdır.

"Model" Bir "kapı bekçisi" olarak hareket etmeli, Veri ambarının yanında durmalı ve soru sormamalı, ancak gelen tüm istekleri kabul etmelidir. Bu genellikle bir MVC sisteminin en karmaşık kısmıdır. Model bileşeni, tüm yapının en üst noktasıdır, çünkü onsuz Denetleyici ve Görünüm arasında iletişim mümkün değildir.

Verim

Görünüm, “Model”den istenen verilerin çıktılarının son şeklinin verildiği sistemin bir parçasıdır. MVC tabanlı web uygulamalarında "Görünüm", HTML kodunun oluşturulduğu ve görüntülendiği bir bileşendir.

Görünüm ayrıca kullanıcının eylemini durdurur ve daha sonra "Kontrolöre" iletilir. Bunun tipik bir örneği, Görünüm tarafından oluşturulan düğmedir. Kullanıcı tıkladığında, "Kontrolör"deki eylem tetiklenir.

Görünüm bileşeni hakkında birkaç yaygın yanlış anlama vardır. Örneğin, birçok kişi yanlışlıkla " Görünüm"ile bağlantısı yok" Model"ve görüntülenen tüm veriler" Denetleyici». Gerçekte, böyle bir veri akışı şeması, MVC mimarisinin arkasındaki teoriyi hesaba katmaz. Fabio Chevasco makalesinde, geleneksel olmayan MVC PHP çerçevelerinden birinin örneğini kullanarak bu yanlış yaklaşımı açıklıyor:

"MVC mimarisini düzgün bir şekilde uygulamak için "Model" ve "Görünüm" arasında herhangi bir etkileşim olmamalıdır: tüm mantık "Kontrolör" tarafından işlenir.

Ayrıca, şablon dosyası olarak "Görüntüle" tanımı da yanlıştır. Ancak bu, bir kişinin hatası değil, çeşitli geliştiriciler tarafından ortak bir yanılgıya yol açan birçok hatanın sonucudur. Sonra başkalarına yanlış açıklıyorlar. Aslında, "Görünüm" bir şablondan çok daha fazlasıdır. Ancak modern MVC odaklı çerçeveler, bu yaklaşımı o kadar özümsemiştir ki, artık kimse doğru MVC yapısının desteklenip desteklenmediğini umursamamaktadır.

Görünüm bileşenine hiçbir zaman doğrudan Denetleyici tarafından veri verilmez. " Görünüm" ve " Kontrolör" arasında doğrudan bir bağlantı yoktur - bunlar " Model" kullanılarak bağlanır.

Denetleyici

Görevi, kullanıcının girdiği verileri işlemek ve Modeli güncellemektir. Bu, şemanın kullanıcı etkileşimi gerektiren tek kısmıdır.

"Denetleyici", daha sonra depolama için sonraki organizasyonla "Modele" aktarılan bir bilgi toplayıcı olarak tanımlanabilir. Gelen verileri toplama ihtiyacından başka bir mantık içermez. "Kontrolör" Ayrıca yalnızca bir "Görünüm" ve bir "Model"e bağlanır. Bu, veri değişim noktalarında bir giriş ve bir çıkış ile tek yönlü bir veri akışı sistemi oluşturur.

"Kontrolör", yalnızca kullanıcı "Görünüm" ile etkileşime girdiğinde yürütülecek görevleri alır ve her işlev, kullanıcının "Görünüm" ile etkileşimine bağlıdır. Geliştiricilerin yaptığı en yaygın hata, "Denetleyici"yi bir ağ geçidiyle karıştırarak "Görünüm"e ait işlevler ve görevler atamalarıdır.

Ayrıca, Denetleyiciye yalnızca Modelden Görünüme verilerin işlenmesinden ve aktarılmasından sorumlu işlevler verilmesi yaygın bir hatadır. Ancak MVC kalıbının yapısına göre bu etkileşim "Model" ve "Görünüm" arasında gerçekleştirilmelidir.

PHP'de MVC

PHP'de mimarisi MVC tabanlı bir web uygulaması yazalım. Örnek bir tel kafes ile başlayalım:

string = "MVC + PHP = Harika!"; ))denetleyici = $ denetleyici; $bu->model = $model; ) genel işlev çıktısı ()( dönüş "

" . $this->model->string . "

"; } } model = $model; ))

Şablonun her bölümü için birkaç ana sınıfı olan bir projemiz var. Şimdi aralarındaki ilişkiyi yapılandırmanız gerekiyor:

çıktı();

Yukarıdaki PHP MVC örneğinde, kullanıcı etkileşimleri uygulamada tanımlanmadığından denetleyiciye özgü bir işlev yoktur. Örneğimiz yalnızca tanıtım amaçlı olduğundan, görünüm tüm işlevleri içerir.

Denetleyici işlevselliğini nasıl ekleyeceğimizi göstermek için örneği genişletelim, böylece uygulamaya etkileşimler ekleyeceğiz:

string = "MVC + PHP = Harika, buraya tıklayın!"; ))denetleyici = $ denetleyici; $bu->model = $model; ) genel işlev çıktısı () ( dönüş "

model->dize . "

"; } } model = $model; ) public function tıklandı() ( $this->model->string = “MVC ve PHP sayesinde Veriler Güncellendi!”; ) )

Programı temel işlevlerle genişlettik. Bileşenler arasındaki etkileşimleri ayarlamak artık şöyle görünür:

($_GET["eylem"])(); ) echo $görünüm->çıktı();

Bu yazımızda projemizin "iskeletini" yazacağız. "Çerçeve" kelimesiyle, MVC yaklaşımına dayalı olacak çalışma kodunu kastediyorum, yani, kontrolörler, eylemler, şablonlar (görünümler) ve modellere net bir mantık bölünmesine sahip olacak.

Ve şimdi başlayalım, önceki makalede yazdığım gibi, MVC modeli bir giriş noktası anlamına gelir - index.php, tüm istekler bu betik üzerinden gidecek, tüm proje mantığı bunun üzerinden çalışacak. Bu yaklaşımı uygulamak için sunucuyu yapılandırmanız gerekiyor, sitenin apache sunucusunda çalıştığı varsayılıyor, bu yüzden URL yönlendirme kurallarını belirlediğimiz bir .htaccess dosyası oluşturmamız yeterli. Yönlendirme, bir giriş noktası tanımlamanın yanı sıra CNC (insan tarafından okunabilir URL'ler) oluşturmanıza olanak tanır. Yani, doğru ayarlardan sonra sayfa adresleri bu site.ru/article/new gibi görünecektir.
İlk olarak, tüm sayfaların işlenmesini index.php betiğine yönlendirecek bir .htaccess oluşturalım. Kod şöyle görünür:

RewriteCond'da RewriteEngine %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule ^(.*)$ index.php?route=$1

.htaccess dosyası sitenin kök klasöründe olmalıdır, giriş noktası olan index.php betiğini hemen oluşturmalısınız. Yönlendirmenin çalışıp çalışmadığını kontrol etmek için index.php'ye bir satır yazalım:

yankı "deneme";

Artık yönlendirmenin çalışıp çalışmadığını kontrol edebilir, herhangi bir adres girebilir ve ne olduğunu görebilirsiniz: test-mvc.web/sdf/sdf/ veya test-mvc.web/sdf/sdf/2342/ önemli değil, her durumda, "test" görünmelidir. Bu yazıyı gördüyseniz, başardık demektir.
Devam edelim, kolaylık olması açısından, sitenin kök dizininde, siteyi yapılandırmamızı kolaylaştıracak çeşitli sabitler ayarlayacağımız bir config.php dosyası oluşturalım. Bunlar, komut dosyalarına, veritabanı yaklaşımlarına vb. giden farklı yollar olabilir. Şimdi yapılandırmada aşağıdakileri ayarlayalım:

// Sabitleri ayarla: define("DS", DIRECTORY_SEPARATOR); // dosya yolları için ayırıcı $sitePath = realpath(dirname(__FILE__) .DS); define("SITE_YOLU", $siteYol); // sitenin kök klasörünün yolu // veritabanına bağlanmak için define("DB_USER", "root"); define("DB_PASS", ""); define("DB_HOST", "localhost"); define("DB_NAME", "blog_mvc");

Proje boyunca sabitlerin ve diğer yapılandırma verilerinin kullanılabilmesi için config.php betiğini index.php dosyasına dahil etmemiz gerekiyor.
Dosyayı ayarlarla bağlamaya ek olarak, index.php'de veritabanına bir bağlantı oluşturmanız, komut dosyasını site çekirdeğine bağlamanız ve yönlendirmenin gerçekleşeceği yönlendiriciyi başlatmanız gerekir.
Şimdi sırayla veritabanı bağlantısının oluşturulması index.php'de olacak, böylece bağlantı sadece bir kez açılacak. Bağlantıyı açtıktan sonra, tüm denetleyicilerde ve modellerde kullanabiliriz, ancak daha sonraları. Şimdi veritabanına bir bağlantı oluşturalım. Veritabanıyla çalışmak için PDO kullanmaya karar verdim. PDO hakkında daha fazla bilgi edinebilirsiniz.
Sitenin çekirdeğini core klasörüne yerleştireceğiz ve script core.php'yi çağıracağız, burada iş için gerekli sınıfları kendi kendine bağlayacak bir fonksiyon yazacağız. Böyle bir işlev, denetleyiciler, modeller vb. ile çalışmamızı büyük ölçüde kolaylaştıracak ve basitleştirecektir. Çünkü ileriye baktığımda her bir controller ve her modelin ayrı bir sınıf olacağını söyleyeceğim.
Sınıfların otomatik bağlanmasına ek olarak, projede herhangi bir yerde faydalı olabilecek tüm gerekli nesneleri ve değişkenleri depolayacağımız bir havuz oluşturmak için çekirdeğe bir depolama (kayıt defteri) ekleyeceğiz.
Yönlendiriciyi dizin dosyasına da bağlayacağız, URL'yi ayrıştıracak ve gerekli denetleyiciyi ve eylemi bağlayacaktır. Denetleyici nedir, önceki makalede yazdım ve gereksiz bilgilerle yüklenmeden eylem hakkındaki bilgileri kasıtlı olarak kaçırdım. Peki eylem nedir?
Controller çeşitli metotlar içeren bir sınıftır, MVC yaklaşımı ile her metot bir eylem olacaktır. Yani, bir eylem (eylem), verileri işleyecek ve görünüme (şablona) iletecek bir sınıf yöntemidir. Henüz tam olarak netleşmemiş olabilir, ancak bir örnekten sonra her şey yerine oturacaktır.
Bu aşamada teori yeterli, hadi uygulamaya geçelim. Yukarıda anlattığım işi olan dosyaların kodunu vereceğim.
Index.php komut dosyası kodu:

// tüm hataların görüntülenmesini aç error_reporting (E_ALL); // yapılandırmayı dahil et ("/config.php"); // Veritabanına bağlanın $dbObject = new PDO("mysql:host=" .DB_HOST . ";dbname=" .DB_NAME, DB_USER, DB_PASS); // site çekirdeğini dahil et include (SITE_PATH .DS . "çekirdek" .DS . "core.php"); // Yönlendirici yükle $yönlendirici = yeni Yönlendirici($kayıt); // verileri $registry->set ("yönlendirici", $yönlendirici); // controllers klasörünün yolunu ayarlayın. $router->setPath(SITE_PATH . "kontrolörler"); // yönlendiriciyi başlat $router->start();

core.php betiği:

// Sınıfları anında yükle fonksiyonu __autoload($className) ( $filename = strtolower($className) . ".php"; // sınıfı tanımlayın ve onun yolunu bulun $expArr = patlat("_", $className) ) ; if(empty($expArr) VEYA $expArr == "Temel")( $klasör = "sınıflar"; )else( switch(strtolower($expArr))( case "denetleyici": $klasör = "kontrolörler"; break ; case "model": $klasör = "modeller"; break; varsayılan: $klasör = "sınıflar"; break; ) ) // sınıfa giden yol $dosya = SITE_PATH .$klasör .DS .$dosyaadı; // kullanılabilirlik dosyasını kontrol et if (file_exists($file) == false) ( false döndür; ) // include ($file) sınıfına sahip dosyayı dahil et; ) // kayıt (depolama) başlat $registry = yeni Kayıt;

Registry.php depolama sınıfı /classes/ klasöründe yer alacaktır.

// Depolama sınıfı Sınıf Kaydı ( private $vars = array(); // datayı kaydet function set($key, $var) ( if (isset($this->vars[$key]) == true) ( throw new Exception("var `" . $key . "`. Zaten ayarlanmış."); ) $this->vars[$key] = $var; return true; ) // data function get($) alınıyor key) ( if (isset($this->vars[$key]) == false) ( null döndür; ) return $this->vars[$key]; ) // veriyi sil işlevi sil($var) ( unset ($ this->vars[$key]); ) )

/classes/ klasöründe bulunan router.php dosyasının kodu

// yönlendirici sınıfı Sınıf Yönlendirici ( private $registry; private $path; private $args = dizi(); // depo işlevini al __construct($registry) ( $this->registry = $registry; ) // yolu ayarla kontrolör fonksiyonu setPath($path) ( $path = trim($path, "/\\"); $path .= DS; // eğer yol yoksa sinyal eğer (is_dir($path) =) olan klasöre = false ) ( new Exception ("Geçersiz denetleyici yolu: `" . $path . "`"); ) $this->path = $path; ) // url özel işlevi getController(&$file) öğesinden denetleyici ve eylemi tanımlayın , & $controller, &$action, &$args) ( $route = (empty($_GET["route"])) ? "" : $_GET["route"]; unset($_GET["route"] ); if (empty($route)) ( $route = "index"; ) // url parçalarını al $route = trim($route, "/\\"); $parts = patlat("/", $route ); // Denetleyiciyi bulun $cmd_path = $this->path; foreach ($parts as $part) ( $fullpath = $cmd_path . $part; // Klasörün var olup olmadığını kontrol edin if (is_dir($fullpath)) ( $cmd_path .= $part.DS; dizi_shift($parça); devam et; ) // Dosyayı bulun if (is_file($fullpath . ".php")) ( $controller = $part; array_shift($parts); break; ) ) // url'de denetleyici belirtilmemişse, şunu kullanın varsayılan dizin if (empty ($controller)) ( $controller = "index"; ) // Eylemi alın $action = array_shift($parts); if (empty($action)) ( $action = "index"; ) $dosya = $cmd_path . $kontrolör. ".php"; $args = $parçalar; ) function start() ( // $this->getController($file, $controller, $action, $args) yolunu ayrıştırın; // Dosyanın var olup olmadığını kontrol edin, aksi takdirde 404 if (is_readable($file) == false ) ( die ("404 Bulunamadı"); ) // include ($file) dosyasını dahil et; // Denetleyici örneği oluştur $class = "Controller_" .$controller;$controller = new $class($this->registry) ; // Eylem mevcut değilse - 404 if (is_callable(array($controller, $action)) == false) ( die ("404 Bulunamadı"); ) // $controller->$action eylemini yürütün (); ) )

Şimdi denetleyicileri, şablonları ve modelleri depolamak için klasörler oluşturmanız gerekiyor - kökte üç klasör denetleyicisi, görünümü ve modeli oluşturacağız. Ve bazı test dosyaları oluşturalım /controllers/index.php, /views/index/index.php ve /models/model_users.php ve şimdi dosyaları dolduralım:
Kontrolör için:

// controller Class Controller_Index Controller_Base'i Genişletiyor ( // şablon public $layouts = "first_layouts"; // action function index() ( $model = new Model_Users(); $userInfo = $model->getUser(); $this-> template->vars("userInfo", $userInfo); $this->template->view("index"); ) )

Görüntüleme için (/views/index/index.php)

test görünümü
İD:
isim:

Ve modeli:

// model Class Model_Users( public function getUser()( return array("id"=>1, "name"=>"test_name"); ) )

Fark etmiş olabileceğiniz gibi, denetleyici sınıfı, Controller_Base üst sınıfından miras alır. Bu, denetleyici sınıfını basitleştirmek için yapılır. Şablonlarla çalışmak için hala sınıfı bağlamamız gerektiğinden, bağlantısı Controller_Base'e taşınır.
İşte kodu, /classes/ klasöründe bulunur ve controller_base.php olarak adlandırılır:

// soyut denetleyici sınıfı Soyut Sınıf Controller_Base ( korumalı $kayıt defteri; korumalı $şablon; korumalı $düzenleri; // şablon genel $vars = dizi(); // şablonları yapıcı işlevine dahil et __construct($kayıt) ( $this-> kayıt defteri = $kayıt defteri; // şablonlar $bu->şablon = yeni Şablon($bu->layouts, get_class($bu)); ) özet işlev index(); )

Şimdi sadece şablonlarla uğraşmak kalıyor. Controller_Base abstract sınıfında Template sınıfını çağırır ve ona template name ve controller adını iletiriz.
Burada /classes/ bulunan ve template.php olarak adlandırılan şablon sınıf kodu

// şablonları bağlamak ve verileri ekrana aktarmak için sınıf Sınıf Şablonu ( private $template; private $controller; private $layouts; private $vars = dizi(); function __construct($layouts, $controllerName) ( $this->layouts = $layouts; $dizi = patlat("_", $controllerName); $this->controller = strtolower($dizi); ) // değişkenleri görüntülemek için değişkenleri ayarlayın vars($varname, $değer) ( if ( isset( $this->vars[$varname]) == true) ( ​​trigger_error ("var `" . $varname . "`. Ayarlanamadı. Zaten ayarlanmış ve üzerine yazmaya izin verilmiyor.", E_USER_NOTICE); return false ; ) $this ->vars[$varname] = $value; return true; ) // fonksiyonu görüntüle görünümü($name) ( $pathLayout = SITE_PATH . "görünümler" . DS . "düzenler" . DS . $bu-> düzenler . ". php"; $contentPage = SITE_PATH . "views" . DS . $this->controller . DS . $name . ".php"; if (file_exists($pathLayout) == false) ( trigger_error ("Düzen" `" . $ this->layouts . "` mevcut değil.", E_USER_NOTICE); return false; ) if (file_exists) ($contentPage) == false) ( trigger_error ("Şablon `" . $ad . "`yok.", E_USER_NOTICE); yanlış döndür; ) foreach ($this->$key => $value olarak değişir) ( $$key = $value; ) include ($pathLayout); ))

Kodu dikkatlice okuduysanız, muhtemelen sayfalarda görüntülemek için first_layouts şablonunu ve index.php görünümünü (görüntü) kullandığımızı anladınız - kodunu biraz daha yukarıda alıntıladım. Tek yapmamız gereken first_layouts şablon dosyasını oluşturmak. /views/layouts/first_layouts.php klasörüne yerleştirelim
Şablon aşağıdaki kodu içerecektir:

başlık

altbilgi

Hepsi bu, bu "çerçevenin" oluşturulmasını tamamlıyor. Şimdi MVC modeline dayanan en basit yapıya sahibiz. Bu yazıda, veritabanı ile çalışmaya değinmedim, makale zaten büyük olduğu için sadece geçerken bahsettim. Veritabanı ile yapılan çalışmaları bir sonraki yazımda direkt anlatacağım.
Bu yazımız bitmiştir kaynak kodunu arşivden indirebilirsiniz.

model Model-Görünüm-Denetleyici (MVC) 1970'lerin sonlarında keşfedilen, temel amacı verilerle çalışma işlevlerini temsillerinden ayırmak olan bir yazılım mimarisi tasarım modelidir. Teorik olarak, iyi tasarlanmış bir MVC uygulaması, ön uç ve arka uç geliştiricilerin çalışma sırasında birbirlerinin sorumluluk alanlarına müdahale etmemesine izin verecektir, yani ön uç geliştiricinin "mutfak" hakkında hiçbir şey bilmesine gerek yoktur. arka uç meslektaşı ve tam tersi.

MVC başlangıçta masaüstü geliştirme için tasarlanmış olsa da, modern görevler için uyarlanmıştır ve endişelerin ayrılması yoluyla daha net, yeniden kullanılabilir kod oluşturmak mümkün hale geldiği için web geliştiricileri arasında çok popülerdir. MVC modeli, geliştiricilerin mevcut kodda çok hızlı bir şekilde değişiklik yapmalarını sağlayan açık, modüler sistemlere yol açar.

Bu makalede, bir model tanımlayarak ve onu küçük bir örnekte uygulamaya devam ederek MVC'nin temel ilkelerini gözden geçireceğiz. Bu makale öncelikle hayatlarında bu modelle hiç karşılaşmamış olanlar ve belki de MVC bilgilerini yenilemek isteyenler için faydalı olacaktır.

MVC'yi Anlamak

Daha önce de belirtildiği gibi, kalıbın adı üç kelimenin kısaltmasından gelir: Model (model), Görüntüle (görünüm) ve Denetleyici (kontrolör). Kısaca, modelin prensibi bir şema ile gösterilebilir (Wikipedia'da bulunabilir):

Bu diyagram, modeldeki tek yönlü bilgi akışını açıkça gösterir ve ayrıca her bir bileşenin rollerini açıklar.

modeli

Model, verilere erişmek ve bunları işlemek için kullanılır. Çoğu durumda, bir veri deposuna (veritabanı gibi) erişmek için kullanılan modeldir. Model, veri alma, veri oluşturma, değiştirme ve depolamadan silme için bir arayüz sağlar. MVC modeli bağlamında model, görünüm ve denetleyici arasında bir aracıdır.

Modelin son derece önemli bir özelliği, teknik olarak denetleyicideki ve görünümdeki verilerle neler olduğu hakkında hiçbir bilgiye sahip olmamasıdır. Model, kalıbın diğer bileşenlerinden hiçbir zaman talepte bulunmamalı veya talepte bulunmamalıdır.

Bununla birlikte, bir modelin yalnızca bir veri tabanına veya başka bir sisteme erişim ağ geçidi olmadığını, tamamen veriyi ileri geri iletmekle ilgili olmadığını her zaman unutmayın. Model, verilere açılan bir ağ geçidi gibidir. Model genellikle sistemin en karmaşık parçasıdır, çünkü kısmen modelin kendisi diğer tüm parçalarla bağlantıdır.

Verim

Görünüm, modelden alınan verilerin istenilen formda görüntülendiği yerdir. MVC modelinde geliştirilen geleneksel web uygulamalarında görünüm, HTML kodunun oluşturulduğu sistemin parçasıdır. Görünüm, denetleyiciye göndermek için kullanıcıdan eylemleri almaktan da sorumludur. Örneğin, bir görünüm kullanıcı arabiriminde bir düğme görüntüler ve bu düğme tıklandığında uygun denetleyici eylemini başlatır.

Bir görünümün amacı hakkında, özellikle uygulamalarını MVC kullanarak oluşturmaya yeni başlayan web geliştiricileri arasında bazı yanlış anlamalar vardır. En sık ihlal edilen kurallardan biri, görünüm modelle hiçbir şekilde iletişim kurmamalıdır, ve tüm görünüm tarafından alınan veriler yalnızca denetleyiciden gelmelidir. Uygulamada, geliştiriciler genellikle MVC modelinin kalbinde yer alan bu kavramı görmezden gelirler. Fabio Cevasco'nun makalesi, standart olmayan birçok MVC çerçevesinden biri olan CakePHP ile MVC'ye bu kafa karıştırıcı yaklaşımı göstermektedir:

Uygun bir MVC mimarisi elde etmek için görünümler ve modeller arasında doğrudan etkileşim olmaması gerektiğini anlamak son derece önemlidir. Aralarındaki tüm veri alışverişi mantığı kontrolörlerde uygulanmalıdır.

Ayrıca, bir görünümün yalnızca bir şablon dosyası olduğuna dair yaygın bir yanılgı vardır. Tom Butler'ın belirttiği gibi, birçok geliştiricinin MVC yapısını en başından yanlış anlaması ve ardından yeni başlayan geliştiricilerin kitlelerinin bu "bilgiyi" daha fazla aşılamaya başlaması nedeniyle bu yanlış anlamanın büyük bir kapsamı vardır. Gerçekte, bir görünüm sadece bir şablondan çok daha fazlasıdır, ancak MVC modeline dayanan birçok çerçeve, bir görünüm kavramını o kadar çarpıtmıştır ki, uygulamalarının MVC modeli açısından ne kadar doğru olduğu kimsenin umurunda değildir.

Bir diğer önemli nokta, görünümün asla denetleyiciden gelen "saf" verilerle çalışmamasıdır, yani denetleyici, modeli atlayarak asla görünümle çalışmaz. Denetleyici ve görünüm arasındaki etkileşim sürecinde, model her zaman aralarında olmalıdır.

Denetleyici

Kontrolör, MVC paketinin son parçasıdır. Kontrolörün görevi, kullanıcıdan veri almak ve modeli manipüle etmektir. Kontrolördür ve sadece o, sistemin kullanıcıyla etkileşime giren kısmıdır.

Özetle, denetleyici, işleme ve depolama için onu modele ileten bir bilgi toplayıcı olarak tanımlanabilir. Verilerle hiçbir şey yapmamalı, yalnızca bunları kullanıcıdan alabilmelidir. Denetleyici, bir görünüm ve bir model ile ilişkilendirilir, böylece her aşamada kontrol ederek tek yönlü bir veri akışı organize eder.

Denetleyicinin, yalnızca ilgili denetleyici işlevini çağıran görünümle kullanıcı etkileşiminin bir sonucu olarak çalışmaya başladığını hatırlamak çok önemlidir. Geliştiriciler arasında en yaygın hata, denetleyicinin görünüm ve model arasında bir ağ geçidi olarak ele alınmasıdır. Sonuç olarak, denetleyici, görünüm tarafından gerçekleştirilmesi gereken işlevlerle donatılmıştır (bu arada, görünümün yalnızca bir şablon dosyası olduğu fikri buradan gelir). Bunun da ötesinde, çoğu genellikle MVC modelinde modelin ne amaçladığını unutarak tüm veri işleme mantığını boşaltır.

PHP'de MVC

Yukarıdakileri küçük bir uygulamada uygulamaya çalışmayı öneriyorum. Model, görünüm ve denetleyici sınıflarını oluşturarak başlayalım:

string = "MVC + PHP = Harika!"; ))denetleyici = $ denetleyici; $bu->

" . $this->model->string . "

"; } } model = $model; ))

Ana sınıflar hazır. Şimdi bunları birbirine bağlayalım ve uygulamamızı çalıştıralım:

çıktı();

Gördüğünüz gibi, kullanıcı uygulama ile hiçbir şekilde etkileşime girmediği için denetleyicinin herhangi bir işlevi yoktur. Uygulamamız tamamen veri görüntülemek için olduğundan, tüm işlevler görünüme yerleştirilmiştir.

Denetleyicinin nasıl çalıştığını görmek için uygulamayı biraz etkileşimle genişletelim:

string = "MVC + PHP = Harika, buraya tıklayın!"; ))denetleyici = $ denetleyici; $bu->model = $model; ) genel işlev çıktısı () ( dönüş "

model->dize . "

"; } } model = $model; ) public function tıklandı() ( $this->model->string = “MVC ve PHP sayesinde Veriler Güncellendi!” )

Ve son olarak, bağlantı kodunu biraz modernize edelim:

($_GET["eylem"])(); ) echo $görünüm->çıktı();

Sonuçlar

Bu kısa yazımızda, MVC tasarım deseninin temel kavramlarını ele aldık ve buna dayalı basit bir uygulama geliştirdik, ancak elbette bunu gerçek hayatta kullanmaktan hala çok uzağız. Bir sonraki makalede, MVC modeline dayalı bir uygulama mimarisi oluşturmaya daha yakından bakarsanız karşılaşacağınız temel zorluklara bakacağız. Bizi izlemeye devam edin!

Bu öğreticide, SPL (Standart PHP Kitaplığı, PHP Standart Kitaplığı) özelliklerini kullanarak PHP 5.1'de basit bir MVC (Model-View-Controller) sisteminin nasıl oluşturulacağını öğreneceksiniz.

giriiş

PHP 5 için ilk tam eğitime hoş geldiniz. En son PHP 5 özelliklerinden bazılarını kullanacağımız için SPL kitaplığı kuruluyken PHP 5.1'e ihtiyacınız olacak.

Bu derste size basit bir MVC sisteminin nasıl oluşturulacağını göstereceğim (MVC mimarisi, büyük web uygulamaları için en yaygın tasarım modelidir). Eksiksiz bir MVC sistemi oluşturmak için baştan sona tüm adımlarda size yol göstereceğim.

Bir giriş noktası

MVC ile ilgili önemli şeylerden biri, şöyle bir şey yapan bir grup PHP dosyası yerine uygulamaya tek bir giriş noktasıdır:

Tüm istekleri ele alan bir dosyamız olacak. Bu, her yeni sayfa oluşturmamız gerektiğinde global.php'yi dahil etme konusunda endişelenmemize gerek olmadığı anlamına gelir. Bu "tek giriş noktası" index.php olarak adlandırılacak ve şimdilik şöyle olacak:

Gördüğünüz gibi bu script henüz bir şey yapmıyor ama bir dakika bekleyin.

Tüm istekleri ana sayfaya yönlendirmek için mod_rewrite kullanacağız ve .htaccess içinde RewriteRule yönergesini ayarlayacağız. Aşağıdaki kodu .htaccess dosyasına yapıştırın ve index.php ile aynı dizine kaydedin:

RewriteCond'da RewriteEngine %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule ^(.*)$ index.php?route=$1

İlk olarak, RewriteCond yönergesini kullanarak istenen dosyanın var olup olmadığını kontrol ederiz, yoksa isteği index.php'ye yönlendiririz. Dosyanın mevcudiyeti için bu kontrol gereklidir çünkü aksi takdirde index.php, resim istekleri de dahil olmak üzere siteye gelen tüm istekleri işlemeye çalışacaktır. Ve bu sadece ihtiyacımız olmayan şey.

.htaccess veya mod_rewrite kullanamıyorsanız, tüm istekleri manuel olarak index.php'ye yönlendirmeniz gerekecektir. Diğer bir deyişle, tüm bağlantılar "index.php?route=[request-goes-buraya]" biçiminde olmalıdır. Örneğin, "index.php?route=chat/index".

Artık tüm istekler aynı giriş noktasından geçtiğine göre, index.php betiğini yazmaya başlayabiliriz. Yapmamız gereken ilk şey, sistemi başlatmak. İçerir dizinini ve onun içinde startup.php dosyasını (bizim başlatma dosyamız olacak) oluşturalım. Aşağıdaki kodu index.php'ye yapıştırın:

Bu örnekte, bir sabit tanımladık, sistem dosyalarının nerede olduğunu bulduk ve ayrıca PHP sürümünün en az 5.1 olup olmadığını kontrol ettik.

Bundan sonra yapılacak şey, global değerleri tutan bir Registry nesnesidir. Bireysel sistem nesnelerine geçirilecek ve değişkenleri "global" olarak atamak veya $GLOBALS dizisine başvurmak zorunda kalmadan global değerlere erişmek için kullanılacaktır. Kayıt nesnesi hakkında daha fazla bilgi için "PHP'de Global Değerleri Kullanma" makalesini okuyun.

Önceki örnekteki kodun arkasına aşağıdaki kodu startup.php dosyasına ekleyin:

$registry = yeni Kayıt;

Sistemi şimdi başlatmayı denerseniz, aşağıdaki hatayı görebilirsiniz:

Önemli hata: "Kayıt Defteri" sınıfı, 12. satırda g:\Projects\PHP\content\simple mvc php5\demo\includes\startup.php içinde bulunamadı

Bu elbette bizim için büyük bir sürpriz değil çünkü henüz Registry sınıfının kendisini yazmadık. Sınıf dosyası, include() işlevi kullanılarak dahil edilebilir. PHP 5'teki yeni özelliklerden birini kullanalım: __autoload().

Sihirli işlev __autoload(), sınıfları dinamik olarak yüklemek için kullanılır. PHP var olmayan bir sınıf algıladığında, önce __autoload() işlevini çağırır ve ancak o zaman bir hata atar. Sınıfları anında yüklemek için bu fırsattan yararlanabiliriz.

Bu kodu önceki örnekteki kodun önüne yapıştırın:

// Sınıfları anında yükle fonksiyonu __autoload($class_name) ( $filename = strtolower($class_name) . ".php"; $file = site_path . "classes" . DIRSEP . $filename; if (file_exists($file) = = false) ( false döndür; ) include ($file); )

__autoload() işlevimiz, kendisine argüman olarak iletilen sınıf adını alır ve sınıflar dizininde benzer bir ada sahip bir dosya olup olmadığını kontrol eder. Dosya yoksa, işlev yalnızca false döndürür ve önemli bir hata açılır. Ancak dosya varsa, yüklenecektir. Şunlar. gerekli sınıf bildirilecek ve herhangi bir hata olmayacaktır.

Henüz Registry sınıfını oluşturmadık, bu nedenle hata görünmeye devam edecek. Şuna devam edelim.

Registry sınıfının oluşturulması

Registry sınıfı, tek tek nesneler arasında global değerleri iletmek için kullanılır. Aslında birkaç küçük yöntem uygulaması gereken oldukça basit bir sınıftır.

İlk olarak sınıflar dizinini ve içinde kayıt defteri.php dosyasını oluşturalım. Aşağıdaki kodu register.php'ye yapıştırın:

Şimdi Registry sınıfının bir "iskeleti"ne sahibiz ve onu yöntemlerle yüklememiz gerekiyor. 2 metot yazalım: değerleri ayarlamak için set() ve değerleri almak için get(). Değerleri kaldırmak için bir remove() yöntemi de yazabilirsiniz. Bu yöntemleri Registry sınıfına ekleyelim:

fonksiyon set($key, $var) ( if (isset($this->vars[$key]) == true) ( ​​yeni İstisna atmak("var `" . $anahtar . "`. Zaten ayarlanamadı. set. "); ) $this->vars[$key] = $var; return true; ) function get($key) ( if (isset($this->vars[$key]) == false) ( return null; ) return $this->vars[$key]; ) function remove($var) ( unset($this->vars[$key]); ) ?>

Bu yöntemler basittir, sınıfın bir özniteliği olan $vars dizisinden öğeleri ayarlar, alır ve kaldırırlar. set() yönteminde, belirtilen anahtara sahip bir değerin zaten var olup olmadığını da kontrol ederiz ve varsa bir istisna atarız. Bu, değerlerin yanlışlıkla üzerine yazılmasını önlemek için gereklidir.

Artık tam teşekküllü bir Kayıt sınıfımız var, ancak burada durmayacağız. SPL kitaplığının özelliklerinden birini kullanalım: ArrayAccess. SPL (Standart PHP Kitaplığı'nın kısaltması), yaygın sorunları çözmek için tasarlanmış bir arayüzler ve sınıflar topluluğudur. SPL arabirimlerinden biri olan ArrayAccess, normal bir dizi gibi bir nesneye erişim sağlamak için kullanılabilir. Şu örneğe bakalım:

set("isim", "Dennis Pallett"); // değeri get() echo $registry->get ("name"); // Dizi erişimini kullanarak değer alın echo $registry["name"] ?>

İşin püf noktası, $registry'nin aslında bir nesne olmasına rağmen bir dizi gibi olmasıdır. Elbette, ArrayAccess herhangi bir özel avantaj sağlamaz, ancak her seferinde "->get ()" yazmanız gerekmediğinden kod miktarını azaltmanıza olanak tanır. Bu arayüzü kullanmak için sınıfın ilk satırını ("Sınıf Kayıt Defteri") aşağıdaki gibi düzeltmeniz gerekir:

Sınıf Kayıt Defteri Dizi Erişimini Uygular (

"Implements" anahtar sözcüğü, yorumlayıcıya, bu sınıfla bir arabirim uyguladığımızı söyler; bu, ArrayAccess'in gerçekte olduğu şeydir.

ArrayAccess arabirimini uygulayan bir sınıf aşağıdaki yöntemlere sahip olmalıdır:

function offsetExists($offset) ( return isset($this->vars[$offset]); ) function offsetGet($offset) ( return $this->get($offset); ) function offsetSet($offset, $değer) ( $this->set($offset, $value); ) function offsetUnset($offset) ( unset($this->vars[$offset]); )

Bu yöntemler kendi kendini açıklayıcı olmalıdır. Daha fazla bilgi SPL belgelerinde bulunabilir.

Şimdi, ArrayAccess arabirimini uyguladıktan sonra, nesneye sıradan bir diziymiş gibi erişebiliriz. Bu, hem önceki örnekte hem de bu örnekte açıkça gösterilmiştir:

get("isim"); // Dizi erişimini kullanarak değer alın echo $registry["name"] ?>

Registry sınıfı şimdi tamamlandı ve sistemi başlatmaya çalışırsanız, her şey çalışmalıdır (henüz hiçbir şey çıkmayacak olsa da). Başlatma dosyasıyla işimiz bittiğinde, MVC sistemimizi yazarken bir sonraki adıma geçmeye hazırız: MVC mimarisinde "Model" olarak adlandırılan veritabanı erişimini uygulamak.

modeli

"M" veya model, MVC sisteminin veritabanını (veya diğer harici kaynağı) sorgulamaktan ve denetleyiciye bilgi sağlamaktan sorumlu olan parçasıdır. İsteğe bağlı olarak gerekli modeli yüklemek mümkün olabilir ama ben bu yerde model ile controller arasındaki sınırları biraz bulanıklaştırmayı tercih ediyorum, yani. denetleyici, ayrı bir model yerine doğrudan veritabanı etkileşim kitaplığı aracılığıyla veritabanıyla çalışır. Belki farklı yapmak istersiniz, bu bir zevk meselesi.

Veritabanı bağlantısı kurmak için gerekli olan kodu yazıp index.php içerisine yerleştirmemiz gerekiyor. Dışarıda pek çok harika veritabanı kitaplığı var (kendime ait AutoCRUD dahil), ancak PHP 5'te zaten bir tane PDO var. Bu nedenle, başka bir kullanmaya gerek yoktur.

Aşağıdaki kodu index.php dosyasına yapıştırın (başlatma dosyasını ekledikten sonra):

# Veritabanına bağlanın $db = new PDO("mysql:host=localhost;dbname=demo", "", ""); $kayıt->set("db", $db);

Bu örnekte, önce PDO kitaplığının yeni bir örneğini oluşturuyoruz ve MySQL veritabanımıza bağlanıyoruz. Ardından, Registry sınıfımızı kullanarak $db değişkenini global olarak kullanılabilir hale getiriyoruz.

Sistemimizin model bileşeni hazır, o halde şimdi controller'ı yazmaya geçelim.

Bir denetleyici yazmak, isteğe bağlı olarak istenen denetleyiciyi yüklemekten sorumlu olan Router sınıfının yazılması anlamına da gelir (unutmayın, index.php'de $route değişkeni URL'den geçirilir).

yönlendirici sınıfı

Yönlendirici sınıfı, isteği ayrıştırır ve ardından gerekli denetleyiciyi yükler. Sınıfın bir "iskeletini" oluşturalım:

kayıt defteri = $kayıt defteri; ) ) ?>

Ardından index.php dosyasına aşağıdaki satırları ekleyin:

# Yönlendiriciyi yükle $yönlendirici = yeni Yönlendirici($registry); $registry->set("yönlendirici", $yönlendirici);

Yazacağımız ilk şey, tüm denetleyicilerimizin olacağı dizini ayarlamak için setPath() yöntemidir. Yöntem şöyle görünür ve Router sınıfına eklenmelidir:

İşlev setPath($path) ( $path = trim($path, "/\\"); $path .= DIRSEP; if (is_dir($path) == false) ( yeni İstisna at ("Geçersiz denetleyici yolu: ` " . $yol . "`"); ) $bu->yol = $yol; )

Ardından index.php dosyasına aşağıdaki satırları ekleyin:

$router->setPath(site_path . "kontrolörler");

Denetleyicilerimizin yolunu belirlediğimize göre, denetleyiciyi yüklemekten sorumlu olan yöntemi yazalım. Bu yöntem delege() olarak adlandırılacak ve isteği ayrıştıracaktır. Bu yöntemin ilk parçası:

İşlev delegesi() ( // $this->getController($file, $controller, $action, $args) yolunu ayrıştırın;

Gördüğünüz gibi, denetleyicinin adını ve diğer birkaç değişkeni almak için getController() adlı başka bir yöntem kullanıyor. Bu yöntem şöyle görünür:

Özel işlev getController(&$file, &$controller, &$action, &$args) ( $route = (empty($_GET["route"])) ? "" : $_GET["route"]; if ( boş($route)) ( $route = "index"; ) // Bölünmüş parçaları al $route = trim($route, "/\\"); $parts = patlat("/", $route); // Doğru denetleyiciyi bulun $cmd_path = $this->path;foreach ($parts as $part) ( $fullpath = $cmd_path . $part; // Bu yola sahip bir klasör var mı? if (is_dir($fullpath)) ( $cmd_path .= $part .DIRSEP; array_shift($parts); devam; ) // Dosyayı bulun if (is_file($fullpath . ".php")) ( $controller = $part; array_shift($parts); break ; ) ) if (empty($denetleyici)) ( $denetleyici = "dizin"; ); // İşlemi al $eylem = array_shift($parçalar); if (boş($eylem)) ( $eylem = "dizin"; ) $dosya = $cmd_path .$denetleyici .".php"; $args = $parçalar; )

Bu yöntemin üzerinden geçelim. Önce istekten $route değişkeninin değerini alır, ardından patlat() işlevini kullanarak onu parçalara ayırır. Örneğin, "üyeler/görünüm" sorgusu şöyle bir diziye dönüştürülür: dizi('üyeler', 'görünüm').

Daha sonra her parçadan bir foreach döngüsü ile geçer ve o parçanın bir dizin olup olmadığını kontrol eder. Eğer öyleyse, onu dosyanın yoluna ekler ve sonraki kısmı kontrol eder. Bu, denetleyicileri alt dizinlere koymanıza ve böylece bir denetleyici hiyerarşisi elde etmenize olanak tanır. İsteğin mevcut kısmı bir dizin değil de bir dosyaysa, $controller değişkeninde saklanır ve ihtiyacımız olan controller bulunduğu için döngüden çıkarız.

Döngüden sonra controller ismi ile değişkeni kontrol ediyoruz. Boşsa, varsayılan denetleyicimiz olacak "indeks" denetleyicisini kullanırız. Yöntem daha sonra gerçekleştirilecek eylemi tanımlar. Denetleyici, birkaç yöntemden oluşan bir sınıftır. Bir eylem, belirli bir yönteme işaret eder. Eylem belirtilmemişse, varsayılan eylem olan "index" kullanacağız.

Ve son olarak, üç değişkeni birleştirerek denetleyici dosyasının tam yolunu elde ederiz: yol, denetleyici adı ve "php" uzantısı.

Artık isteği ayrıştırdığımıza göre, denetleyiciyi yüklemek ve eylemi gerçekleştirmek için delege() yöntemini çağırmanın zamanı geldi. Tam delege() yöntemi şöyle görünür:

İşlev delegesi() ( // $this->getController($file, $controller, $action, $args) yolunu ayrıştırın; // Dosya kullanılabilir mi? if (is_readable($file) == false) ( die ( "404 Bulunamadı"); ) // include ($file) dosyasını dahil et; // Denetleyicinin bir örneğini oluştur $class = "Controller_" . $controller; $controller = new $class($this->registry) ; // İşlem mevcut mu? if (is_callable(array($controller, $action)) == false) ( die ("404 Bulunamadı"); ) // $controller->$action(); ) işlemini gerçekleştirin

İsteği getController() yöntemiyle ayrıştırdıktan sonra dosyanın gerçekten var olup olmadığını kontrol ederiz ve yoksa basit bir hata mesajı döndürürüz.

Bundan sonra, dosyayı denetleyiciye dahil ediyoruz ve "Controller_[name]" olarak adlandırılması gereken sınıfının bir örneğini oluşturuyoruz. Biraz sonra kontrolörler hakkında daha ayrıntılı konuşacağız.

Ardından belirtilen eylemin (yani yöntemin) var olup olmadığını ve çağrılabilir olup olmadığını kontrol ederiz (bunun için is_callable() işlevini kullanırız). Son olarak, Router sınıfının rolünün bittiği eylemin kendisini gerçekleştiriyoruz.

Tam delege() yöntemini yazdıktan sonra, index.php dosyasına aşağıdaki satırı ekleyin:

$yönlendirici->temsilci();

Sistemi şimdi başlatmaya çalışırsak, aşağıdaki hatayı göreceğiz (tabii, henüz controllers dizini yoksa):

Önemli hata: g:\Projects\PHPit\content\simple mvc php5\demo'da "Geçersiz denetleyici yolu: `g:\Projects\PHP\content\simple mvc php5\demo\controllers\`" mesajıyla yakalanmayan "İstisna" \classes\router.php:18 Yığın izleme: #0 g:\Projects\PHP\content\simple mvc php5\demo\index.php(13): Router->setPath("g:\Projects\PHP... ") 18. satırda g:\Projects\PHP\content\simple mvc php5\demo\classes\router.php içine atılan #1 (ana)

Aksi takdirde henüz kontrolcü olmadığı için “404 Bulunamadı” hatası ile karşılaşacağız. Ama şimdi yapacağımız şey bu.

Denetleyici

MVC sistemimizdeki kontrolörler oldukça basit olacak ve çok az zaman alacaktır. İlk olarak, controllers dizininin var olduğundan emin olun. sınıflar dizininde bir controller_base.php dosyası oluşturun ve aşağıdaki kodu içine yapıştırın:

kayıt defteri = $kayıt defteri; ) soyut fonksiyon indeksi(); ) ?>

Bu soyut sınıf, tüm denetleyicilerimiz için ana sınıf olacaktır. Yalnızca iki şey yapacaktır: Registry sınıfının yerel bir kopyasını tutmak ve tüm alt denetleyicileri bu yöntemi uygulamaya zorlamak için abstract index() yöntemini kullanmak.

İlk controller'ımızı yazalım. Controller dizininde bir index.php dosyası oluşturun ve aşağıdaki kodu içine yapıştırın:

Az önce ilk controller'ımızı oluşturduk ve sistemi başlatmaya çalışırsak aşağıdakileri görebiliriz:

Bu, Router sınıfının işini yaptığı ve gerekli kontrol cihazından gerekli eylemi başlattığı anlamına gelir. "üyeler/görüntüleme" isteğiyle eşleşecek başka bir controller yazalım. controllers dizininde bir üye.php dosyası oluşturun ve aşağıdaki kodu içine yapıştırın:

Şimdi "members/view" veya "index.php?route=members/view" isteği ile MVC sistemimize gidelim. Şu sonucu görmeliyiz:

Sadece yeni bir controller yazıp ona bir method ekleyerek sistemin kendisinde hiçbir şeyi değiştirmeden yeni bir sayfa oluşturabildik. Ayrıca, denetleyicilerimizin bir global.php dosyası veya bunun gibi bir şey içermesine gerek yoktur.

Artık kontrolörlerimiz olduğuna göre, geriye tek bir şey kaldı: "V" veya "Görünüm".

Görüntülemek

Modellerde olduğu gibi, bir MVC sisteminde bir Görünüm bileşeni oluşturmak için birkaç farklı seçenek vardır. Router sınıfına "view_(name).php" gibi başka bir dosyayı otomatik olarak yüklemesini öğretebiliriz. Ancak kılavuzu daha anlaşılır kılmak için, şablonların çıktısını işleyecek bir Template sınıfı yazalım.

Öncelikle classlar dizininde bir template.php dosyası oluşturalım ve içine aşağıdaki kodu yapıştıralım:

kayıt defteri = $kayıt defteri; ) ) ?>

Artık Template sınıfımızın ana yapısına sahibiz. Bir sonraki adım, Router sınıfı ile ilgili satırlardan hemen önce index.php dosyasına aşağıdaki kodu eklemektir:

# Bir şablon nesnesi oluşturun $template = new Template($registry); $kayıt->set("şablon", $şablon);

Modellerden ve denetleyicilerden gelen değerleri kullanmamız gerekeceğinden, şablonlarda bulunan değişkenleri ayarlamak için bir set() yöntemi yazacağız. Bir örneğe bakalım:

İşlev set($varname, $değer, $overwrite=false) ( if (isset($this->vars[$varname]) == true AND $overwrite == false) ( trigger_error ("var `" ayarlanamıyor . $varname . "`. Zaten ayarlanmış ve üzerine yazmaya izin verilmiyor.", E_USER_NOTICE); return false; ) $this->vars[$varname] = $value; return true; ) function remove($varname) ( unset($ this->vars[$varname]); true döndür; )

set() ve remove() yöntemleri oldukça basittir ve sırasıyla değişkenleri ayarlamak ve kaldırmak için kullanılır.

Şablonları gösterecek olan show() metodunu yazalım. En kolay yol, tüm şablon dosyalarının depolandığı ayrı bir şablon dizini oluşturmak ve şablonun çıktısını almak için include() işlevini kullanmaktır. Elbette, kendi show() yönteminiz tamamen farklı olabilir ve şablonları veritabanından yükleyebilir veya başka bir şey yapabilir. Kuso'ya bakalım.

Oylar: 745 | Görüntüleme: 8080

SRC:
O'Reill. ActionScript 3.0 Tasarım Modelleri.
12. Bölüm


Model-Görünüm-Denetleyici modeli nedir?

Model-View-Controller (MVC), karmaşık uygulamaları uygulamak için birlikte çalışan bileşik bir model veya birden çok modeldir. Bu kalıp en çok uygulama arabirimleri oluşturmak için kullanılır ve adından da anlaşılacağı gibi üç öğeden oluşur:

modeli(model)
Bu uygulamanın durumunu yönetmek için uygulama verilerini ve mantığı içerir

Verim(Görüş)
Ekranda gözlemlenebilen kullanıcı arayüzünü ve uygulamanın durumunu uygular

Denetleyici(Kontrolör)
Uygulamanın durumunu etkileyen kullanıcı eylemlerini yönetir.

MVC modelinin gücü, her birinin sorumluluk alanlarının çakışmasını önlemek için doğrudan bu üç öğenin ayrılmasından gelir. Her bir öğenin neden sorumlu olduğunu görelim.

modeli

Model, uygulamanın durumunu yönetmekten sorumludur. Modeldeki uygulama mantığı iki önemli görevle temsil edilir: model, uygulama durumu isteklerine yanıt verir ve bir durum değişikliği isteğine yanıt olarak eylemler gerçekleştirir.

Verim

Görünüm, uygulamanın görünümüdür. Kullanıcı, Görünüm aracılığıyla uygulama ile etkileşime girer. Bir uygulama, hem girdi hem de çıktı mekanizması olabilen birden çok Görünüm içerebilir. Örneğin, iPod gibi taşınabilir bir dijital oynatıcıda aygıtın ekranı Görünüm olacaktır. Oyuncu düğmeleri de bir Görünüm olarak kabul edilir. Ekran şarkının adını ve süresini, albüm resmini ve cihazın mevcut durumuyla ilgili diğer şeyleri gösterir. Görünümün görünür olması gerekmez. Taşınabilir bir oynatıcıda, kulaklıkta çalınan müzik de bir Performanstır. Örneğin, bir düğmeye basmak, kulaklıklarda bazı sesli tıklama yanıtlarına neden olabilir. Ses seviyesi değişiklikleri, ses çıkış kanalına da yansır. Sesli geri bildirim, uygulamanın durumu ile ilgilidir.

Denetleyici

Denetleyici terimi dolaylı olarak uygulamanın denetlendiği arabirimi ifade etse de, MVC modelinde Denetleyici herhangi bir kullanıcı arabirimi öğesi içermez. Yukarıda belirtildiği gibi, girdi sağlayan kullanıcı arabirimi öğeleri Görünüm bileşenine aittir. Denetleyici ise, Görünümlerin kullanıcı girişine nasıl yanıt vereceğini belirler.

Diyelim ki dijital oynatıcımızda düğmeler var daha yüksek sesle ve Sessizlik Görünüm'de. Ses düzeyi bir durum değişkenidir. Model, bu değişkenin değerini uygulama mantığına göre değiştirmek için bu değişkeni takip edecektir. Ses seviyesi değeri 0'dan 10'a derecelendirilirse, Kontrolör bu düğmelerden birine bir kez basıldığında sesi ne kadar artıracağını veya azaltacağını belirleyecektir. Davranış, Model'e sesi 0,5 veya 0,1 veya programlı olarak belirtildiği gibi herhangi bir başka değer artırmasını söyleyebilir. Bu bağlamda, Denetleyiciler, bir uygulamanın kullanıcı girdisine nasıl yanıt vereceğini tanımlayan uygulama özellikleridir.

MVC triadındaki her bir elementin ayrı ve benzersiz bir sorumluluk alanı olmasına rağmen, izole olarak çalışmazlar. Aslında bir MVC örüntüsü oluşturmak için her elemanın diğerleriyle iletişim kurması gerekir. Bunun ne anlama geldiğini aşağıda ele alacağız.

MVC elemanlarının etkileşimi

MVC modelindeki her öğe, geri kalanıyla çok özel yollarla iletişim kurar. İletişim, tipik olarak uygulama ile kullanıcı etkileşimi tarafından tetiklenen bir dizi olay tarafından gerçekleştirilir. Olayların sırası şöyle görünür:

  1. Kullanıcı bir arabirim öğesiyle etkileşime girer (örneğin, Görünümdeki bir düğmeyi tıklatır).
  2. Görünüm, tıklamanın nasıl ele alınacağına karar vermek için Kontrolöre bir tıklama olayı gönderir.
  3. Kontrolör, basılan düğmeyle ilgili kararlarına göre Modeli değiştirir.
  4. Model, Görünüm'e Modelin durumunun değiştiğini bildirir.
  5. Görünüm, Modeldeki durum bilgisini okur ve kendini değiştirir.

Bu, MVC öğelerinin nasıl etkileşime girdiğinin çok basit bir diyagramıdır. Bazı durumlarda, Denetleyici Görünüme değişmesini söyleyebilir. Bu, Kullanıcı eylemi nedeniyle Görünümde değişikliklerin gerekli olduğu ve Modelde değişiklik gerektirmediği, yalnızca yalnızca görsel değişikliklerle sonuçlandığı tek durumdur. Örneğin, kullanıcının dijital oynatıcıda bir şarkıyı nasıl seçtiğini düşünün. Kaydırma düğmeleriyle listeden bir şarkı seçer. Görünümün Denetleyiciye Yukarı Kaydır veya Aşağı Kaydır düğmelerine basıldığını söylemesi gerekir, ancak Denetleyicinin Modeli bilgilendirmesi gerekmez. Doğrudan Görünüm'e şarkı listesini istenen yönde kaydırmasını söyler. Böyle bir kullanıcı eylemi, Modelde değişiklik yapılmasını gerektirmez. Ancak, kullanıcı listeden bir şarkı seçip onu çalmaya başladığında, Kontrolör Modeli, bu değişikliği o anda çalınan şarkının değerinde yansıtacak şekilde değiştirecektir.

Ayrıca, Modeldeki değişiklikler her zaman kullanıcı eylemleriyle başlatılmaz. Model, belirli olaylara göre kendini güncelleyebilir. Örneğin, bir hisse senedi fiyat göstergesini ele alalım. Model, hisselerin cari değeri ile ilgili değildir. Ancak, maliyetin kendisi değişir ve Model, web hizmetinden periyodik güncellemeler almak için bir zamanlayıcı ayarlayabilir. Ardından, Model hisse fiyatı verilerini her güncellediğinde, Görünüm'e durumun değiştiğini bildirecektir.

MVC modelinin bir başka özelliği de, bu tür her bir Modelin kendisiyle ilişkilendirilmiş birden fazla Görünüme sahip olabilmesidir. Örneğin, taşınabilir oynatıcımızda ses seviyesi ayarları bir seviye ölçer kullanılarak ekranda gösterilebilir. Ayrıca, ses çıkışındaki ses seviyesi, kulaklıktaki sesin seviyesi ile ilişkilidir. Kulaklıklardaki hem görüntü hem de ses, Cihaz Durumu Temsilleridir.

Şekil 12-1'e bakın ve okların yönünü not edin. Öğeler arasındaki etkileşimi kimin başlattığını gösterirler. Bir MVC öğesinin diğeriyle iletişim kurabilmesi için onu bilmesi ve o öğeye bir referansa sahip olması gerekir.

Model, View ve Controller'ı üç farklı sınıf olarak düşünün. Hangi sınıfların diğer sınıflara referans olması gerektiğini görelim:

Verim
Hem Modele hem de Kontrolöre bir referansı olması gerekiyor.

Denetleyici
Model için bir referansa sahip olması gerekiyor

MVC'nin birden çok kalıbı birleştiren bileşik bir kalıp olduğunu belirterek başladık. Bu bileşik kalıba hangi kalıpların dahil olduğunu merak ediyor olmalısınız. Ya da daha doğrusu nasıl temsil edilebilirler? MVC modelini kullanmanın ana avantajı, onu oluşturan üç öğeye ayırma yeteneğidir. Bu, birden fazla Görünümü aynı Modele bağlamamıza, diğer öğeleri etkilemeden Modelleri ve Denetleyicileri değiştirmemize olanak tanır. Ancak MVC üçlüsündeki bazı öğeler, diğer öğelere referanslar sağlamalı ve ayrıca bunlar arasındaki aktif iletişimi desteklemelidir. Böyle bir bölünmeye ne ad verebiliriz? Bunun Gözlemci, Strateji ve Bileşik kalıplarla ilgisi var.

MVC'de Kalıpları Enjekte Etme

Daha önce gördüğümüz gibi, bir Model birden çok Görünümle ilişkilendirilebilir. MVC'de Modelin, kendisiyle ilişkili tüm Görünümleri meydana gelen değişiklikler hakkında bilgilendirmesi gerekir. Ayrıca, bu, Görünümler hakkında belirli ayrıntıları bilmeden ve hatta kaç Görünümün değişmesi gerektiğini bilmeden yapılmalıdır. Bu görev, en iyi Tarayıcı modelinin bir uygulamasını kullanarak gerçekleştirilir (bkz. Bölüm 8).

Her Model, kendisiyle ilişkilendirilmiş birden fazla Görünüme sahip olabilir. Benzer şekilde, Görünümler, diğer kullanıcı arabirimi öğelerini içeren birden çok pencere veya panel ile karmaşık olabilir. Örneğin, düğmeler, metin alanları, listeler, kaydırıcılar vb. gibi arabirim öğeleri. sekmeli bir panelde gruplandırılabilir ve panel de diğer panellerle birlikte bir pencerenin parçası olabilir. Her düğme veya düğme grubu bir Görünüm olabilir. Metin alanlarının toplanması ile aynı. Basit Görünüm koleksiyonlarını içeren bir panele veya pencereye, diğer Görünümlere davrandığımız gibi davranmak yararlı görünüyor. Bu, Linker modelini kullanmanın bizi çok fazla efordan kurtaracağı yerdir (bkz. Bölüm 6). Bağlayıcı desen uygulaması bu bağlamda neden bu kadar kullanışlı? Görünümler, Oluşturucu deseni kullanılarak oluşturulduklarında iç içe yerleştirilebilirse, güncelleme işlemi basitleştirilir. Güncelleme olayı, tüm alt Görünümleri otomatik olarak atlayacaktır. İç içe geçmiş her Görünüme ayrı güncelleme mesajları göndermeye gerek olmadığında karmaşık Görünümler oluşturmak daha kolay hale gelir.

Görünümler, etkinliklerini yalnızca Modelin durumunun harici bir temsiliyle sınırlar. UI olaylarını Kontrolöre iletirler. Bu nedenle, bir Denetleyici daha çok belirli bir Görünümde kullanıcı girişinin nasıl ele alınacağına ilişkin bir algoritmadır. Böyle bir yetkilendirme, Modeldeki bir değişiklik karşısında özel bir öğenin belirli bir öğesinin nasıl davrandığının uygulanmasını kapsar. Farklı bir davranış elde etmek için aynı Görünüm için bir Denetleyiciyi kolayca değiştirebiliriz. Bu, Strateji modelini uygulamak için ideal bağlamdır.

Minimalist MVC Desen Örneği

Bu basit örnek, tuş vuruşlarını izler. Sonraki tuşuna basıldığında bu Modelin değişmesine neden olur ve View'e kendisini güncellemesi için bilgi verir. Görünüm, kullanıcının yazdığı karakter kodunu yerleştirmek için Flash'ın standart Çıktı penceresini kullanır. Karakter kodu, mevcut yerleşimin kod tablosundaki karakterin sayısal değeridir. Bu örnek, Tarayıcı, Strateji ve Oluşturucu kalıplarının MVC'ye nasıl entegre edildiğini açıklar.

Tarayıcı Şablonunda Somut Konu Olarak Modelleme

Model ve Görünüm arasındaki ilişki, Konu ile Tarayıcı arasındaki ilişkidir (Bkz. Bölüm 8). Model, Tarayıcı modelinin bir parçası olan Konu arabirimini uygulamalıdır. Neyse ki ActionScript 3.0, tarayıcıları değişikliklerden haberdar etmek için ActionScript olay modelini kullanarak bu ilkeyi zaten uygulayan yerleşik sınıflara sahiptir.

ActionScript 3.0'da EventDispatcher sınıfı

EventDispatcher sınıfı, IEventDispatcher arabirimiyle sağlanır. Diğer yöntemlerle birlikte, IEventDispatcher arabirimi, Tarayıcı şablonundaki bir konu için gerekli olan aşağıdaki yöntemleri tanımlar. (Tüm yöntem parametreleriyle ilgili ayrıntılar için AS3 belgelerine bakın).

addEventListener(type :String , listener:Function , useCapture:Boolean = false , Priority:int = 0 , useWeakReference:Boolean = false ) :void removeEventListener(type :String , listener:Function , useCapture:Boolean = false ) :void sevkEvent olay:Etkinlik) :Boole

Bir Modelin Tarayıcı modelinde Somut Konu olarak hareket etmesi için IEventDispatcher arabirimini uygulamanız gerekir. Ancak, belirli bir özel sınıfın olayları dağıtma yeteneğini elde etmesinin en kolay yolu EventDispatcher sınıfından miras almaktır.

Tarayıcı, addEventListener() yöntemini kullanarak EventDispatcher nesnelerinden bildirim almak için dinleyici yöntemlerini kaydeder.

modeli

Modelimiz, basılan tuşa karşılık gelen karakter kodunu bir özellikte saklar. Görünüm ve Denetleyicinin bu özelliğe erişmesini ve değiştirmesini mümkün kılmak için bir ayarlayıcı ve alıcı uygulamanız gerekir. Modelimizi tanımlayalım (Örnek 12-1).

Örnek 12-1. IModel.as

paket ( import flash.events .* ; genel arabirim IModel, IEventDispatcher'ı genişletir ( function setKey(key :uint) :void ; function getKey() :uint; ) )

Örnek 12-1'de gösterilen IModel arabirimi, IEventDispatcher arabirimini genişletir ve basılan son tuşun karakter kodunu okumak ve ayarlamak için birkaç yöntem tanımlar. IModel arabirimi IEventDispatcher'ı genişlettiğinden, onu uygulayan herhangi bir sınıf, her iki arabirimde de tanımlanan tüm yöntemleri uygulamalıdır. Örnek 12-2'de gösterilen Model sınıfı, IModel arabirimini uygular.

Örnek 12-2. Model.as

paket ( import flash.events .* ; genel sınıf Model, EventDispatcher'ın IModel uygulamasını genişletir ( özel var lastKeyPressed:uint=0 ; genel işlev setKey(anahtar :uint) :void ( this .lastKeyPressed =key ; sevkEvent(new Event(Event.CHANGE) ) ) ; // olay yayılır) genel işlev getKey() :uint ( lastKeyPressed'i döndür; ) )

Model sınıfı, IEventDispatcher arabirimini zaten uygulayan EventDispatcher sınıfını genişletir. SendEvent() işlevinin setKey() yönteminin içinde çağrıldığını unutmayın. setKey() yöntemi içinde lastKeyPressed değeri değişir değişmez, tüm kayıtlı tarayıcılara bir CHANGE olayı gönderir.

Strateji şablonunda Somut Strateji olarak Denetleyici.

Denetleyici ve Görünüm arasındaki ilişki, Strateji modelinde bir strateji ve bir bağlam olarak temsil edilebilir. Her Kontrolör, Strateji arayüzü çerçevesinde gerekli davranışı uygulayan özel bir strateji olacaktır.

Denetleyici

Minimalist örneğimizde, Denetleyiciden istenen davranış sadece bir tuşa basma olayını kabul etmektir. IKeyboardInputHandler, tek bir keyPressHandler() yönteminin tanımlandığı bir Strateji arabirimidir (Örnek 12-3).

Örnek 12-3. IkeyboardInputHandler.as

paket ( import flash.events .* ; genel arabirim IkeyboardInputHandler ( işlev keyPressHandler(event:KeyboardEvent) :void ;) )

Somut Controller, IKeyboardInputHandler arabirimini uygulayan Controller sınıfı (Örnek 12-4) olacaktır.

Örnek 12-4. Controller.as

paket ( import flash.events .* ; public class Controller, IkeyboardInputHandler'ı uygular ( private var model:IModel; public function Controller(aModel:IModel) ( this .model =aModel; ) public function keyPressHandler(event:KeyboardEvent) :void ( model. setKey(event.charCode); // modeli değiştir } } }

Denetleyicinin, Model örneğini parametre olarak alan bir kurucuya sahip olduğunu unutmayın. Bu, Kontrolörün Şekil 12-1'de gösterildiği gibi Model ile iletişim kurabilmesi için gereklidir. Bu nedenle, Modele bir referans kaydetmek gereklidir.

keyPressHandler() yöntemi, bir kullanıcı arabirimi olayını (bu durumda, KeyboardEvent) parametre olarak alır ve ardından bunun nasıl işleneceğine karar verir. Örneğimizde, Model'de basılan tuşun kodunu basitçe ayarlar.

Tarayıcı şablonunda Somut Tarayıcı Olarak Temsil ve Strateji şablonunda Bağlam

Görünüm, MVC modelindeki belki de en karmaşık öğedir. Model ve Denetleyici ile ilişkisinin temelini oluşturan Tarayıcı ve Strateji kalıplarının uygulanmasında bütünleştirici bir rol oynar. Liste 12-5'te gösterilen Görünüm sınıfı, minimalist bir örnekte bir Görünüm uygular.

Örnek 12-5. Olarak görüntüle

package ( import flash.events .* ; import flash.display .* ; public class View ( private var model:IModel; private var controller:IKeyboardInputHandler; public function View(aModel:IModel,oController:IKeyboardInputHandler,target :Stage ) ( bu .model=aModel;bu .controller=oController; // Modelden bildirim almak için abone olur model.addEventListener (Event.CHANGE ,bu .update ) ; // sahneden tuş vuruşlarını almak için abone olur hedef .addEventListener (KeyboardEvent.KEY_DOWN , bu .onKeyPress ) ; ) özel işlev güncellemesi (event:Event) :void ( // Modelden veri alın ve Görünümü güncelleyin trace(model.getKey()); ) özel işlev onKeyPress(event:KeyboardEvent) :void ( // işleme, işlenmek üzere Kontrolöre (Strateji) aktarılır controller.keyPressHandler(olay) ; ) ))

Görünüm, Şekil 12-1'de gösterildiği gibi, onlarla etkileşim kurmak için hem Model hem de Denetleyici referanslarına ihtiyaç duyar. Hem Model örneği hem de Controller örneği, yapıcısındaki Görünüme iletilir. Ek olarak, örneğimizdeki Görünüm, kendisini tuşa basma olaylarının alıcısı olarak kaydetmek için Sahne Alanı'na bir referansa ihtiyaç duyar.

Kullanıcı arabirimini çizmeye ek olarak, View sınıfı birkaç önemli görev daha gerçekleştirir. Güncelleme olaylarını almak için Model'e kaydolur ve kullanıcı girdisini işlemek için Denetleyiciye yetki verir. Örneğimizde, Görünümün sahnede harici bir görünür varlığı yoktur, ancak Modelin durumunu Çıktı penceresinde görüntüler. Keypress olayını alması gerekir ve olay yerinden KEY_DOWN olayını almak için onKeyPress() yöntemini kaydeder. İkinci görev, modelden CHANGE olayını almak için bir update() dinleyici yöntemini kaydetmektir. Bir değişiklik bildirimi alındığında, update() yöntemi Modelden basılan son tuşun kodunu okur ve trace() işlevini kullanarak bunu çıktı penceresine yazdırır.

MVC Triad'ı Oluşturma

MVC modelinin üç bölümünün her birinin uygulamasını ayrı ayrı ele aldık. Ancak, her öğeyi başlatacak ve MVC modelini oluşturacak bir istemci olmalıdır. Aslında, karmaşık bir yapı olmayacak - Model, View ve Controller sınıfları yazılırken yapılması gereken her şey zaten yapıldı. Örnek 12-6, MVC öğelerini gösteren bir Flash belge sınıfı sağlar.

Örnek 12-6. Main.as (minimalist örneğin ana sınıfı)

paket ( flash.display .* içe aktar ; flash.events içe aktar .* ; /** * Ana Sınıf * @ amaç: Film için belge sınıfı */ public class Main, Sprite'ı genişletir ( public function Main() ( var model:IModel=new Model ; var controller:IKeyboardInputHandler=new Controller(model) ; var view:View=new View(model,controller,this .stage ) ; ) ) )

Model, Denetleyici ve Görünüm başlatıldıktan sonra birbirleriyle iletişim kuracaklar ve çalışmaya başlayacaklar. Klavyede bir tuşa basılması, Çıktı penceresinde ilgili karakter kodunu görüntüleyecektir.

Tuş vuruşlarını test etmek için kısayolları devre dışı bırakmanız gerekir. Aksi takdirde, Flash UI, kısayollara karşılık gelen tuşa basma olaylarını durduracaktır. Klavye kısayollarını devre dışı bırakmak için video çalışırken Kontrol menüsünden Klavye Kısayollarını Devre Dışı Bırak'ı seçin.

Model örneğinin Controller'a iletildiğini unutmayın. Benzer şekilde, Model ve Denetleyici örnekleri Görünüme geçirilir. IModel ve IKeyboardInputHandler arabirimlerini uyguladıkları sürece, mevcut Model ve Denetleyiciyi başkalarıyla değiştirebiliriz. Ek Görünümler, Model ve Görünüm arasındaki Konu-Görüntüleyici ilişkisine doğrudan ağrısız bir şekilde eklenebilir. Model, Görünümler hakkında hiçbir şey bilmez, çünkü Model'in değişiklik bildirimleri için kendisini bir dinleyici olarak kaydetmek Görünüm'e bağlıdır. Bu, MVC modelinin büyük bir artısıdır; Model, Görünüm ve Denetleyici, kullanımlarında esneklik sağlayan ayrı, gevşek bir şekilde birleştirilmiştir.

İç İçe Görünümler ve Şablon Düğümleri

Görünümün MVC üçlüsünün belki de en karmaşık öğesi olduğunu hatırlayın, çünkü MVC bağlamında hem Tarayıcı modelinin hem de Stratejinin uygulanmasında yer alır. Görünüm öğelerimiz daha karmaşık olabilir, çünkü üçüncü bir düzeni, Düzeni uygulayabilirler (Bölüm 6'daki Düzen düzeni örneklerine bakın). Görünümleri Şablon Öğeleri Olarak Uygulama Bileşik, birden çok Görünüm içeren karmaşık kullanıcı arabirimleriyle uğraşmanıza olanak tanır. Güncelleştirmeler, bileşik Görünümün yapısal ağacının dalları boyunca yayılabileceğinden, İç İçe Görünümler, UI güncelleme işlemine bazı avantajlar sağlar. Kompozit Görünümler ayrıca uygulama davranışına ve kullanıcı tercihlerine göre iç içe Görünümler ekleyebilir ve kaldırabilir. Karmaşık bir arabirime iyi bir örnek, Flash geliştirme ortamındaki Properties Inspector panelidir. Özellikler Denetçisinin içeriği bağlama duyarlıdır ve UI öğeleri, sahnede hangi nesnenin seçildiğine bağlı olarak görünür ve kaybolur.

Bileşen ve Kompozit Görünüm

İlk adım, Görünüm için bileşen ve bileşik sınıfları oluşturmaktır. Bu sınıflar, Örnek 12-7'de gösterildiği gibi, özet olarak bildirilmelidir, alt sınıflar olmalıdır ve somutlaştırılmamalıdır.

Örnek 12-7. ComponentView.as

paket ( import flash.errors .IllegalOperationError ; flash.events .Event ; import flash.display .Sprite ; genel sınıf ComponentView Sprite'ı genişletir ( ( korumalı var model:Object ; korumalı var controller:Object ; public function ComponentView(aModel:Object , aController:Object =null ) ( this .model =aModel; this .controller =aController; ) public function add (c:ComponentView) :void ( throw new IllegalOperationError("ekleme işlemi desteklenmiyor" ) ); ) public function remove(c: ComponentView) :void (yeni IllegalOperationError( "kaldırma işlemi desteklenmiyor") ; ) genel işlev getChild(n:int ) :ComponentView ( yeni IllegalOperationError( "getChild işlemi desteklenmiyor") ; null döndür; ) // ABSTRACT yöntemi (soydan gelen sınıfta geçersiz kılınmalıdır) genel işlev güncellemesi(event:Event=null ) :void ( ) ) ) )

Örnek 12-7'deki ComponentView sınıfı, bir Bileşen Görünümü için soyut bir arabirim tanımlar. Bu, Bölüm 6'daki klasik bileşen sınıfına benzer, ancak birkaç önemli farkla. ComponentView sınıfı, Model ve Görünüme bir referans tutar ve bir kurucu içerir. Tüm Görünümler kullanıcı girdisini işlemez ve bir bileşen Görünümü, Modelin bir örneğini ileterek oluşturulabilir. Bu nedenle, yapıcıdaki aController parametresi varsayılan olarak boştur. Ayrıca ComponentView sınıfının Sprite sınıfından türetildiğini unutmayın. Çoğu Görünüm sahnede kullanıcı arayüzünü çizdiği için bu mantıklıdır. Görüntüleme listesine nesneler çizmek ve eklemek için Sprite sınıfında uygulanan özellikleri ve yöntemleri kullanabiliriz.

update() yöntemi, soyut bir yöntem gibi davranmalıdır. Bir ComponentView'ın alt öğeleri olan Alt Görünümler, kullanıcı arabiriminin kendi kısımlarını güncelleyebilmek için update() yöntemini geçersiz kılmalı ve uygulamalıdır. Bu nedenle, yönteme Event türünde bir parametre iletilir. Bu parametre ayrıca varsayılan olarak null değerine ayarlanmıştır ve bu, parametre olarak bir olayı iletmeden update() öğesini çağırmanıza olanak tanır. Bu yaklaşım, başlangıçta oluşturulan kullanıcı arabirimi varsayılan durumundayken kullanışlıdır ve sonraki örneğimiz bunu göstermektedir.

CompositeView sınıfı, ComponentView'ı genişletir ve alt Görünümlerden sorumlu olan yöntemleri geçersiz kılar.

Örnek 12-8. Kompozit Görünüm.as

paket ( flash.events .Event'i içe aktar ; // ABSTRACT sınıfı (bu sınıfın bir örneğini oluşturmadan ondan miras almanız gerekir) genel sınıf CompositeView, ComponentView'ı genişletir ( private var aChildren:Array ; public function CompositeView(aModel:Object ,aController:Object =null ) ( super (aModel,aController) ; bu .aChildren =new Array ; ) public function add (c:ComponentView) geçersiz kılar ) :void ( aChildren.push (c) ; ) genel işlev güncellemesini geçersiz kılar update(event:Event=null ) :void ( her biri için (var c:ComponentView in aChildren) ( c.update (event) ; ) ) )

Örnek 12-8'de CompositeView sınıfının geçersiz kılınan update() işlevine dikkat edin. Tüm alt sınıflarda güncelleme yöntemini çağırır. Bu nedenle, bir bileşik Görünümün yapısının kökündeki update() işlevinin çağrılması, güncellemeyi yapı boyunca yayacak ve tüm Görünümleri güncelleyerek bileşenin ağacından geçecektir. CompositeView ve ComponentView sınıflarını genişletelim ve nasıl çalıştığını görmek için bir View yapısı oluşturalım.