我正处于为新项目设置架构的早期阶段。数据驱动的Flex UI,位于网页中,调用Amfphp Service for MySQL数据来填充Flex UI中的元素。
如此处理这么多的例子已经过时或写得不好,所以我不仅要完全理解数据流,还要建立清晰,稳健的实践。请检查我的方法,如果您觉得我可以做得更好,请告诉我。
我想要显示一个“主题列表”,让我们按照目前的流程进行操作。
我已经开发了一个名为' AtlasData'的MySQL数据库,我已经开发了我最初的Amfphp服务,它使用Amfphp后台服务浏览器,似乎返回了一个强类型的数组&#39 ; VoSubject'对象。在我的amfphp / Services / vo文件夹中的我的开发Mac(安装了MAMP)上,我有以下' VoSubject.php'文件:
<?php
/**
* Created by IntelliJ IDEA.
* User: Chris
* Date: 04/10/2014
* Time: 18:31
*/
class VoSubject {
/* *
* This Class models one row of the MySQL table. It has one field
* for each row of the Table and a special extra field.
* The extra field is $_explicitType, and its value is the fully qualified
* ActionScript Value Object I intend to use in the Flex application to model the data.
* If you don‚t configure this field correctly, then in the Flex app you
* will not get your strongly typed ActionScript class, but a dynamic object.
* */
public $subjectId;
public $subjectName;
// Explicit ActionScript class
var $_explicitType = "VoSubject";
}
我的Amfphp服务目前看起来像这样(注意我已经删除了一些简洁的方法):
<?php
require_once ('vo/VoSubject.php');
include ('DbAccess.php');
class AtlasService {
// This simple function can be used to test the service.
public function helloWorld() {
return "Hello World";
}
public function getAllSubjects() {
// Connect to the database using PHP Data Objects (PDO).
try {
/*
* The DbAccess class is a Singleton class.
* Create an instance of this class to access it's methods.
*/
$db = DbAccess::getInstance();
// Create a PHP Data Object.
$pdo = $db->getPDO();
} catch (PDOException $e) {
print "Connection Error!: " . $e->getMessage() . "<br/>";
die();
}
// Retrieve all rows from the AtlasData database 'subjects' Table.
try {
$tsql =
'SELECT s.`subjectId`, s.`subjectName`
FROM Subjects s';
$stmt = $pdo->prepare($tsql);
$stmt->execute();
// Fetch all of the data and place in variable '$results'.
$results = $stmt->fetchAll(PDO::FETCH_CLASS, 'VoSubject');
} catch (PDOException $e) {
print "Error when fetching data: " . $e->getMessage() . "<br/>";
die();
}
// Close the database connection.
$stmt = null;
$pdo = null;
// Return the array.
return $results;
}
}
使用Amfphp后台 - 服务浏览器调用&#39; getAllSubjects&#39;函数返回以下内容:
似乎使用代码
$results = $stmt->fetchAll(PDO::FETCH_CLASS, 'VoSubject')
将$ results设置为VoSubject对象数组。
所以现在我希望我的Flex应用程序调用Amfphp Service函数&#39; getAllSubjects。
在开发Flex项目时,我是View Model Presenter的拥护者,我知道这些项目的复杂性会升级。在这个项目的初期,我创建了以下内容:
views - SubjectBar_View(MXML文件) 演示者 - SubjectBar_Presenter(ActionScript类) model - Model(ActionScript类)
我的SubjectBar_View显示主题列表:
<s:List id="subjectList" dataProvider="{presenter.subjects}">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer>
<s:HGroup paddingLeft="2">
<s:Label text="{data.subjectName}" width="125"/>
</s:HGroup>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>
My SubjectBar_Presenter提供要绑定的List的数据源,并通过调用Model中的方法设置此属性:
package presenters {
import flash.events.Event;
import models.Model;
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
import vo.VoSubject;
[Bindable]
public class SubjectBar_Presenter {
private var _model:Model = Model.getInstance();
private var _subjects:ArrayCollection;
public function get subjects():ArrayCollection {
return _subjects;
}
public function set subjects(value:ArrayCollection):void {
_subjects = value;
}
// Constructor.
public function SubjectBar_Presenter() {
// Add an eventListener to listen for property changes in the Model.
_model.addEventListener("subjectsChanged", onSubjectsChanged);
}
private function onSubjectsChanged(event:Event):void {
// Update the property.
this.subjects = _model.subjects;
}
public function onCreationComplete(event:FlexEvent):void {
// Get all Subjects from MySQL database.
_model.getAllSubjects();
}
}
}
我的模型连接到服务器并调用Amfphp服务功能&#39; getAllSubjects&#39;:
package models {
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.NetConnection;
import flash.net.Responder;
import mx.collections.ArrayCollection;
// Custom Events.
[Event(name="subjectsChanged", type="flash.events.Event")]
public class Model extends EventDispatcher {
// Event Names.
public static const SUBJECTS_CHANGED:String = "subjectsChanged";
private static var _model:Model;
private var _subjects:ArrayCollection;
private var _netConnectionObject:NetConnection;
private var _responder:Responder = new Responder(handleAllSubjects, null);
public function get subjects():ArrayCollection {
return _subjects;
}
public function set subjects(value:ArrayCollection):void {
_subjects = value;
// Dispatch an event to allow the Detail view to update.
dispatchEvent(new Event(SUBJECTS_CHANGED));
}
public function get netConnectionObject():NetConnection {
return _netConnectionObject;
}
public function set netConnectionObject(value:NetConnection):void {
_netConnectionObject = value;
}
// Constructor.
public function Model(pvt:PrivateClass) {
// Call the 'init' function to carry out any preparatory work.
this.init();
}
// Singleton creator.
public static function getInstance():Model {
if (Model._model == null) {
Model._model = new Model(new PrivateClass());
//trace("Singleton instantiated");
}
else {
//trace("Sorry--already have a Singleton instantiated")
}
return Model._model;
}
private function init():void {
// Call any preparatory functions here.
this.createNetConnection();
}
private function createNetConnection():void {
netConnectionObject = new NetConnection();
//netConnection.connect( [server name] / [project folder] /amfphp);
netConnectionObject.connect("http://localhost/amfphp-2.2.1/amfphp/index.php");
}
private function handleAllSubjects(result:Object):void{
// trace(result.toString());
// The PHP method returns an Array NOT an ArrayCollection.
this.subjects = new ArrayCollection(result as Array);
}
public function getAllSubjects():void {
// Call the AtlasService.
//netConnection.call([Service Name]/[function name]", [Responder], [parameters]);
netConnectionObject.call("AtlasService/getAllSubjects", new Responder(handleAllSubjects, null));
}
}
}
class PrivateClass {
public function PrivateClass() {
//trace("Private class is up");
}
}
在我的Flex项目&#39; src&#39;文件夹我创建了一个&#39; vo&#39;文件夹并创建了以下&#39; VoSubject&#39;用于定义主题值对象的类:
package vo {
// This is the ActionScript Value Object class.
// This must match the PHP Value Object class defined within the amfphp/Services/vo folder.
[RemoteClass(alias="VoSubject")]
[Bindable]
public class VoSubject {
public var subjectId:int;
public var subjectName:String;
// Constructor.
public function VoSubject() {
}
}
}
这是在Flex方面使用这个VoSubject类,我不确定。行[RemoteClass(alias =&#34; VoSubject&#34;)]是否指向我的amfphp / Services / vo文件夹中的php类?如果是这样,这相对于哪里。它应该是[RemoteClass(别名=&#34; vo / VoSubject&#34;)],因为我的VoSubject.php类位于一个名为&#39; vo&#39;在我的服务文件夹中?
如果我调试我的应用程序,将显示List并使用subjectNames填充。这很棒。但是,我的主题数据源似乎是包含subjectId和subjectName但不包含VoSubject对象的ArrayCollection的对象的ArrayCollection。
有人可以解释一下我如何确保我的主题&#39;我的主题栏中的数据来源:#Bar_Presenter&#39; class是强类型VoSubject对象的ArrayCollection。另外,如果你觉得我可以改进我的方法,我非常愿意学习。
感谢您走到尽头!我期待着你的想法。
克里斯
答案 0 :(得分:1)
var $ _explicitType =&#34; VoSubject&#34;; 应指向您的actionscript类,在您的情况下&#39; vo.VoSubject &# 39 ;. [RemoteClass(alias =&#34; VoSubject&#34;)] 应与显式类型匹配。简而言之,两者都引用了actionscript类。
乍一看,您的代码似乎遵循MVC模式,这总是很好。但我必须承认,我很快浏览了所有代码以找到实际问题。