我处于为新项目设置架构的初期阶段。数据驱动的Flex UI,位于网页内,为MySQL数据调用Amfphp服务以填充Flex UI中的元素。
关于如何解决此问题的许多示例已经过时或写得不好,因此我不仅希望完全理解数据流,而且还希望采取清晰,有效的做法。请查看我的方法,如果您觉得我可以做得更好,请告诉我。
假设我要显示“主题”列表,让我们按照到目前为止的过程进行操作。
Amfphp服务
构建并填充了一个名为“ AtlasData”的MySQL数据库后,我开发了我的初始Amfphp服务,该服务使用Amfphp后台服务浏览器似乎返回了一组强类型的“ VoSubject”对象。在我的开发Mac(已安装MAMP)的“ amfphp / Services / vo”文件夹中,我具有以下“ 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后台管理-服务浏览器调用“ getAllSubjects”函数,将返回以下内容:
看来使用代码
$results = $stmt->fetchAll(PDO::FETCH_CLASS, 'VoSubject')
已将$ results设置为VoSubject对象的数组。
弹性应用
因此,现在我希望我的Flex应用程序调用Amfphp服务函数'getAllSubjects。
在开发Flex项目时,我是View Model Presenter的拥护者,我知道它将越来越复杂。在这个项目的初期,我创建了以下内容:
视图-SubjectBar_View(MXML文件)
演示者-SubjectBar_Presenter(ActionScript类)
模型-模型(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>
我的SubjectBar_Presenter提供了要绑定到列表的数据源,并且通过在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服务函数'getAllSubjects':
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项目的“ src”文件夹中,创建了一个“ vo”文件夹,并创建了以下“ VoSubject”类来定义我的主题值对象:
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 =“ VoSubject”)]行是否指向我的amfphp / Services / vo文件夹中的php类?如果是这样,这相对于哪里。是否应该读[RemoteClass(alias =“ vo / VoSubject”)],因为我的VoSubject.php类位于“服务”文件夹中名为“ vo”的文件夹中?
如果我调试我的应用程序,则显示列表,并用subjectNames填充。这很棒。但是,看来我的主题数据源是一个包含SubjectId和subjectName的对象的ArrayCollection,而不是VoSubject对象的ArrayCollection。
有人可以解释一下我如何确保我的“ subjectBar_Presenter”类中的“主题”数据源是强类型VoSubject对象的ArrayCollection。此外,如果您认为我可以改善自己的方法,我也很乐于学习。
谢谢你的结局!我期待着您的想法。
克里斯
最佳答案
var $ _explicitType =“ VoSubject”;应该指向您的动作脚本类,在您的情况下为“ vo.VoSubject”。 [RemoteClass(alias =“ VoSubject”)]应该与显式类型匹配。简而言之,两者都引用了动作脚本类。
乍一看,您的代码似乎遵循MVC模式,这始终很好。但是我必须承认,我快速浏览了所有代码以找到实际的问题。
关于mysql - 使用Amfphp作为Flex的强类型对象获取MySQL数据时的优良作法是什么,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26255816/