Статьи

Использование AMFPHP с AS3 и CodeIgniter

Похоже, что проект AMFPHP сейчас остановлен, но, к сожалению, он так и не прошел бета-версию 1.9, как и учебники. Однако Adobe не отказалась от этого так легко, и с новыми компиляторами Flex они включили кодировку объектов AMF3 !

Хорошие новости для всех вас, Flexers, но это отдельная история для всех вас, AS3. Flex позволяет вам быстро и просто создать сервис, который будет взаимодействовать с вашим кодом AMFPHP, но вы должны запачкать руки с AS3. Итак, я решил, что пришло время создать достойный набор классов, которые помогут Бобу создать сайт с AS3, используя шлюз AMFPHP.

И чтобы добавить немного грязи в микс, мы будем интегрировать AMFPHP с CodeIgniter, чтобы у нас была фантастическая PHP-инфраструктура для бэкэнда.




Как видите, смотреть не на что, но на самом деле это основа для наших классов общения по Flash; мы можем просто и легко отправлять и получать объекты данных между клиентской и серверной сторонами без сериализации.

Это логичная идея, что вы хорошо разбираетесь в ActionScript и PHP. Вам не обязательно знать, как использовать CodeIgniter, поскольку вы можете просто использовать класс PHP в качестве службы, но стоит знать PHP.

Этот вопрос часто обсуждается. Мы знаем, что flash может получать данные из XML, JSON и т. Д. Но AMFPHP использует другую форму кодирования, называемую «Формат сообщения действия» . Это просто отправка двоичных данных, а не ASCII. Сейчас есть много постов в блогах, посвященных сравнению XML, JSON и AMF, но в конечном итоге AMF имеет следующие большие преимущества:

  • Вам не нужно сериализовать какие-либо данные! Например, если вы передаете некоторые объекты из PHP во Flash, вам нужно сериализовать их, например, в JSON. Затем Flash придется анализировать их, чтобы они могли быть использованы, это требует времени и памяти.
  • Это легче, чем XML, потому что вы никогда не дублируете себя. Например, в XML вы должны начинать с корневого тега, затем с дополнительных тегов, а затем с закрывающими тегами, так что вы увидите, как дублируете имена тегов, и это занимает полосу пропускания. Более того, XML, как и JSON, необходимо проанализировать в E4X, и это требует времени.
  • AMF может быть полностью интегрирован с вашим PHP-кодом, что означает, что вы можете писать меньше кода. Я покажу вам это, используя CodeIgniter, а также стандартные сервисы AMF.

Помните, AMF не является заменой XML или JSON, это просто еще один инструмент в вашем арсенале, когда речь идет о разработке масштабируемых динамических приложений.

Запустите вашу любимую IDE, будь то Flex Builder , FDT , FlashDevelop или TextMate, и создайте новый проект ActionScript. В дополнение к этому, мы также будем делать PHP-кодирование, поэтому подготовьте PHP IDE (я рекомендую Aptana )

Кроме того, мы собираемся использовать класс GreenSock TweenLite, чтобы придать приложению немного магии.

Для тех из вас, кто читал мои последние статьи: на этот раз мы не будем углубляться в PureMVC, так как я хотел, чтобы результатом этой статьи был набор классов, которые вы можете использовать повторно, с PureMVC или без него.

Как и в любом приложении ActionScript, нам нужно настроить наше базовое приложение. Я просто начну с простого создания фона для приложения, а затем рассмотрим создание текстовой области для ответа и кнопок для отправки строки, массива и объекта в PHP; поэтому создайте новый файл с именем «App.as» внутри «src /»:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package
       {
           import flash.display.GradientType;
           import flash.display.Sprite;
           import flash.geom.Matrix;
           import flash.text.Font;
 
           [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
           public class App extends Sprite
           {
               [Embed( systemFont=’Arial’, fontName=’Arial’, mimeType=’application/x-font’ )]
               private var arialFont:Class;
 
               public function App()
               {
                   init();
               }
 
               private function init():void
               {
                   var mat:Matrix = new Matrix();
                   var bg:Sprite = new Sprite();
 
                   mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );
 
                   bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
                   bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
                   bg.graphics.endFill();
 
                   addChild( bg );
 
                   Font.registerFont( arialFont );
               }
           }
       }

Поскольку нам понадобится какой-то пользовательский интерфейс, чтобы пользователь мог взаимодействовать с нашим приложением, нам придется его кодировать! Теперь вам решать, хотите ли вы создать свой пользовательский интерфейс в Flash IDE (или новой IDE Flash Catalyst , выглядит красиво), но я собираюсь быть хардкорным и кодировать его …

С точки зрения компонентов пользовательского интерфейса, мы после:

  • Текстовое поле ввода
  • Кнопка
  • Текстовая область

Это только начало ваших классов пользовательского интерфейса, но это все, что нам нужно на данный момент.

Поскольку я считаю, что переписывание кода является просто длинным и ненужным, давайте создадим компонент кнопки пользовательского интерфейса многократного использования. Создайте новый файл с именем «InputTextField.as» в «src / com / flashtuts / lib / display / ui» и используйте в нем следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.flashtuts.lib.display.ui
   {
       import flash.display.Sprite;
       import flash.text.TextField;
       import flash.text.TextFieldAutoSize;
       import flash.text.TextFieldType;
       import flash.text.TextFormat;
 
       public class InputTextField extends Sprite
       {
           private var minWidth:Number = 200;
 
           private var bg:Sprite;
           private var field:TextField;
 
           public function InputTextField()
           {
               bg = new Sprite();
 
               addChild( bg );
 
               field = new TextField();
 
               addChild( field );
           }
 
           public function init(format:TextFormat, width:Number=0, height:Number=0, backgroundColour:uint=0, strokeThickness:Number=0, strokeColour:uint=0, cornerRadius:Number=0, padding:Number=4):void
           {
               field.autoSize = TextFieldAutoSize.LEFT;
               field.defaultTextFormat = format;
               field.embedFonts = true;
               field.type = TextFieldType.INPUT;
               field.width = ( width > 0 ? width — ( padding * 2 ) : minWidth );
               field.x = padding;
               field.y = padding;
 
               bg.graphics.clear();
               bg.graphics.lineStyle( strokeThickness, strokeColour );
               bg.graphics.beginFill( backgroundColour );
               bg.graphics.drawRoundRect( 0, 0, ( width > 0 ? width : field.width + ( padding * 2 ) ), ( height > 0 ? height : field.height + ( padding * 2 ) ), cornerRadius );
               bg.graphics.endFill();
           }
 
           public function set text(text:String):void
           {
               field.text = text;
           }
 
           public function get text():String
           {
               return field.text;
           }
       }
   }

Теперь давайте быстро пройдем через это. Мы начинаем с нашего конструктора, мы создаем две наши основные переменные: фон ‘bg’ и текстовое поле ‘поле’, а затем добавляем их на сцену:

01
02
03
04
05
06
07
08
09
10
public function InputTextField()
       {
           bg = new Sprite();
 
           addChild( bg );
 
           field = new TextField();
 
           addChild( field );
       }

Наш класс полагается на пользователя, использующего публичную функцию «init ()», которая будет рисовать фон, а также настраивает текстовое поле:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public function init(format:TextFormat, width:Number=0, height:Number=0, backgroundColour:uint=0, strokeThickness:Number=0, strokeColour:uint=0, cornerRadius:Number=0, padding:Number=4):void
       {
           field.autoSize = TextFieldAutoSize.LEFT;
           field.defaultTextFormat = format;
           field.embedFonts = true;
           field.type = TextFieldType.INPUT;
           field.width = ( width > 0 ? width — ( padding * 2 ) : minWidth );
           field.x = padding;
           field.y = padding;
 
           bg.graphics.clear();
           bg.graphics.lineStyle( strokeThickness, strokeColour );
           bg.graphics.beginFill( backgroundColour );
           bg.graphics.drawRoundRect( 0, 0, ( width > 0 ? width : field.width + ( padding * 2 ) ), ( height > 0 ? height : field.height + ( padding * 2 ) ), cornerRadius );
           bg.graphics.endFill();
       }

Затем, наконец, мы хотим иметь возможность установить некоторый текст (если нам нужно) и получить любой текст, введенный пользователем, поэтому мы используем функции get / set:

1
2
3
4
5
6
7
8
9
public function set text(text:String):void
       {
           field.text = text;
       }
 
       public function get text():String
       {
           return field.text;
       }

Вы можете видеть, что можете установить достаточное количество переменных. Вы всегда можете вернуться и изменить это, но пока это работает для этого урока, так что давайте продолжим.

Теперь мы хотим добавить это поле в наше приложение, поэтому я создал новую функцию с именем «addTextField ()» и вызвал ее внутри «init ()», поэтому код нашего приложения выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package
       {
           import com.flashtuts.lib.display.ui.InputTextField;
 
           import flash.display.GradientType;
           import flash.display.Sprite;
           import flash.geom.Matrix;
           import flash.text.Font;
           import flash.text.TextFormat;
 
           [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
           public class App extends Sprite
           {
               [Embed( systemFont=’Arial’, fontName=’Arial’, mimeType=’application/x-font’ )]
               private var arialFont:Class;
 
               public function App()
               {
                   init();
               }
 
               private function init():void
               {
                   var mat:Matrix = new Matrix();
                   var bg:Sprite = new Sprite();
 
                   mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );
 
                   bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
                   bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
                   bg.graphics.endFill();
 
                   addChild( bg );
 
                   Font.registerFont( arialFont );
 
                   addTextField();
               }
 
               private function addTextField():void
               {
                   var textField:InputTextField = new InputTextField();
 
                   textField.init( new TextFormat( ‘Arial’, 12, 0x000000 ), 200, 25, 0xFFFFFF, 1, 0x333333, 5 );
 
                   textField.text = ‘Hello’;
 
                   addChild( textField );
               }
           }
       }

Вы можете видеть, что внутри функции я создал новый текстовый формат и передал это вместе с другими параметрами в наш класс «InputTextField ()». Запустите предварительный просмотр, и вы увидите текстовое поле в верхнем левом углу. Прежде чем что-то позиционировать, давайте закончим другие компоненты пользовательского интерфейса.

Теперь, когда у нас есть область ввода текста, давайте создадим кнопку, которая позволит нам отправлять вводимые нами данные в AMFPHP. Поэтому создайте файл с именем «Button.as» внутри «src / com / flashtuts / lib / display / ui /» и используйте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.flashtuts.lib.display.ui
       {
           import flash.display.Sprite;
           import flash.text.TextField;
           import flash.text.TextFieldAutoSize;
           import flash.text.TextFormat;
 
           public class Button extends Sprite
           {
               private var bg:Sprite;
               private var field:TextField;
 
               public function Button()
               {
                   this.buttonMode = true;
                   this.mouseChildren = false;
 
                   bg = new Sprite();
 
                   addChild( bg );
 
                   field = new TextField();
 
                   addChild( field );
               }
 
               public function init(text:String, format:TextFormat, backgroundColour:uint=0, strokeThickness:Number=0, strokeColour:uint=0, cornerRadius:Number=0, padding:Number=4):void
               {
                   field.autoSize = TextFieldAutoSize.LEFT;
                   field.defaultTextFormat = format;
                   field.embedFonts = true;
                   field.mouseEnabled = false;
                   field.text = text;
                   field.x = padding;
                   field.y = padding;
 
                   bg.graphics.clear();
                   bg.graphics.lineStyle( strokeThickness, strokeColour );
                   bg.graphics.beginFill( backgroundColour );
                   bg.graphics.drawRoundRect( 0, 0, field.width + ( padding * 2 ), field.height + ( padding * 2 ), cornerRadius );
                   bg.graphics.endFill();
               }
           }
       }

Краткий обзор: во многом как наш класс «InputTextField ()», мы создаем две наши переменные «bg» и «field», а также устанавливаем свойства, чтобы этот класс действовал как кнопка

01
02
03
04
05
06
07
08
09
10
11
12
13
public function Button()
       {
           this.buttonMode = true;
           this.mouseChildren = false;
 
           bg = new Sprite();
 
           addChild( bg );
 
           field = new TextField();
 
           addChild( field );
       }

Опять же, так же, как наш класс «InputTextField ()», мы настроили отображение класса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public function init(text:String, format:TextFormat, backgroundColour:uint=0, strokeThickness:Number=0, strokeColour:uint=0, cornerRadius:Number=0, padding:Number=4):void
       {
           field.autoSize = TextFieldAutoSize.LEFT;
           field.defaultTextFormat = format;
           field.embedFonts = true;
           field.mouseEnabled = false;
           field.text = text;
           field.x = padding;
           field.y = padding;
 
           bg.graphics.clear();
           bg.graphics.lineStyle( strokeThickness, strokeColour );
           bg.graphics.beginFill( backgroundColour );
           bg.graphics.drawRoundRect( 0, 0, field.width + ( padding * 2 ), field.height + ( padding * 2 ), cornerRadius );
           bg.graphics.endFill();
       }

Наконец, нам нужно настроить базовый класс нашего приложения следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package
       {
           import com.flashtuts.lib.display.ui.Button;
           import com.flashtuts.lib.display.ui.InputTextField;
 
           import flash.display.GradientType;
           import flash.display.Sprite;
           import flash.geom.Matrix;
           import flash.text.Font;
           import flash.text.TextFormat;
 
           [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
           public class App extends Sprite
           {
               [Embed( systemFont=’Arial’, fontName=’Arial’, mimeType=’application/x-font’ )]
               private var arialFont:Class;
 
               public function App()
               {
                   init();
               }
 
               private function init():void
               {
                   var mat:Matrix = new Matrix();
                   var bg:Sprite = new Sprite();
 
                   mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );
 
                   bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
                   bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
                   bg.graphics.endFill();
 
                   addChild( bg );
 
                   Font.registerFont( arialFont );
 
                   addTextField();
               }
 
               private function addTextField():void
               {
                   var format:TextFormat = new TextFormat( ‘Arial’, 12, 0x000000 );
                   var textField:InputTextField = new InputTextField();
                   var button:Button = new Button();
 
                   textField.init( format, 200, 25, 0xFFFFFF, 1, 0x333333, 5 );
 
                   textField.text = ‘Hello’;
 
                   addChild( textField );
 
                   button.init( ‘Click on me!’, format, 0xCCCCCC, 1, 0x333333, 5 );
 
                   addChild( button );
               }
           }
       }

Если вы запустите это в отладке, вы увидите кнопку над текстовым полем, так что почти там!

Это не будет так сложно, так как мы уже выполнили тяжелую работу в классе «InputTextField ()», поэтому все, что нам нужно сделать, это установить высоту и ширину нашего текстового поля, достаточно простого копирования и вставки работа. Поэтому создайте новый файл с именем «InputTextArea.as» внутри «src / com / flashtuts / lib / display / ui /» и используйте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.flashtuts.lib.display.ui
       {
           import flash.display.Sprite;
           import flash.text.TextField;
           import flash.text.TextFieldAutoSize;
           import flash.text.TextFormat;
 
           public class InputTextArea extends Sprite
           {
               private var minHeight:Number = 200;
               private var minWidth:Number = 200;
 
               private var bg:Sprite;
               private var field:TextField;
 
               public function InputTextArea()
               {
                   bg = new Sprite();
 
                   addChild( bg );
 
                   field = new TextField();
 
                   addChild( field );
               }
 
               public function init(format:TextFormat, width:Number=0, height:Number=0, backgroundColour:uint=0, strokeThickness:Number=0, strokeColour:uint=0, cornerRadius:Number=0, padding:Number=4):void
               {
                   field.autoSize = TextFieldAutoSize.LEFT;
                   field.defaultTextFormat = format;
                   field.embedFonts = true;
                   field.multiline = true;
                   field.wordWrap = true;
                   field.height = ( height > 0 ? height — ( padding * 2 ) : minHeight );
                   field.width = ( width > 0 ? width — ( padding * 2 ) : minWidth );
                   field.x = padding;
                   field.y = padding;
 
                   bg.graphics.clear();
                   bg.graphics.lineStyle( strokeThickness, strokeColour );
                   bg.graphics.beginFill( backgroundColour );
                   bg.graphics.drawRoundRect( 0, 0, ( width > 0 ? width : field.width + ( padding * 2 ) ), ( height > 0 ? height : field.height + ( padding * 2 ) ), cornerRadius );
                   bg.graphics.endFill();
               }
 
               public function set text(text:String):void
               {
                   field.text = text;
               }
 
               public function get text():String
               {
                   return field.text;
               }
           }
       }

Я думаю, что в данный момент нет необходимости объяснять весь класс, но стоит упомянуть конфигурацию поля, которая позволяет ему стать текстовой областью. Мы просто добавили еще два свойства и установили для них значение true: ‘multiline’ и ‘wordwrap’. Они превращают поле ввода в текстовую область.

Итак, наконец, давайте добавим последний компонент в класс приложения:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package
       {
           import com.flashtuts.lib.display.ui.Button;
           import com.flashtuts.lib.display.ui.InputTextArea;
           import com.flashtuts.lib.display.ui.InputTextField;
 
           import flash.display.GradientType;
           import flash.display.Sprite;
           import flash.geom.Matrix;
           import flash.text.Font;
           import flash.text.TextFormat;
 
           [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
           public class App extends Sprite
           {
               [Embed( systemFont=’Arial’, fontName=’Arial’, mimeType=’application/x-font’ )]
               private var arialFont:Class;
 
               public function App()
               {
                   init();
               }
 
               private function init():void
               {
                   var mat:Matrix = new Matrix();
                   var bg:Sprite = new Sprite();
 
                   mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );
 
                   bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
                   bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
                   bg.graphics.endFill();
 
                   addChild( bg );
 
                   Font.registerFont( arialFont );
 
                   addTextField();
               }
 
               private function addTextField():void
               {
                   var format:TextFormat = new TextFormat( ‘Arial’, 12, 0x000000 );
                   var textField:InputTextField = new InputTextField();
                   var textArea:InputTextArea = new InputTextArea();
                   var button:Button = new Button();
 
                   textField.init( format, 200, 25, 0xFFFFFF, 1, 0x333333, 5 );
 
                   textField.text = ‘Hello’;
 
                   addChild( textField );
 
                   textArea.init( format, 200, 200, 0xFFFFFF, 1, 0x333333, 5 );
 
                   textArea.text = ‘Text will appear here that’s returned from the server!’;
 
                   addChild( textArea );
 
                   button.init( ‘Click on me!’, format, 0xCCCCCC, 1, 0x333333, 5 );
 
                   addChild( button );
               }
           }
       }

Наконец, давайте просто выровняем наш пользовательский интерфейс, чтобы его можно было использовать, и установите textField и textInput таким образом, чтобы они были функциями всего класса, а не функцией addTextField ():

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package
       {
           import com.flashtuts.lib.display.ui.Button;
           import com.flashtuts.lib.display.ui.InputTextArea;
           import com.flashtuts.lib.display.ui.InputTextField;
 
           import flash.display.GradientType;
           import flash.display.Sprite;
           import flash.geom.Matrix;
           import flash.text.Font;
           import flash.text.TextFormat;
 
           [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
           public class App extends Sprite
           {
               private var textField:InputTextField = new InputTextField();
               private var textArea:InputTextArea = new InputTextArea();
                
               [Embed( systemFont=’Arial’, fontName=’Arial’, mimeType=’application/x-font’ )]
               private var arialFont:Class;
 
               public function App()
               {
                   init();
               }
 
               private function init():void
               {
                   var mat:Matrix = new Matrix();
                   var bg:Sprite = new Sprite();
 
                   mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );
 
                   bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
                   bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
                   bg.graphics.endFill();
 
                   addChild( bg );
 
                   Font.registerFont( arialFont );
 
                   addTextField();
               }
 
               private function addTextField():void
               {
                   var format:TextFormat = new TextFormat( ‘Arial’, 12, 0x000000 );
                   var button:Button = new Button();
 
                   textField.init( format, 200, 25, 0xFFFFFF, 1, 0x333333, 10 );
 
                   textField.text = ‘Hello’;
 
                   addChild( textField );
 
                   textArea.init( format, 300, 200, 0xFFFFFF, 1, 0x333333, 10 );
 
                   textArea.text = ‘Text will appear here that\’s returned from the server!’;
 
                   addChild( textArea );
 
                   button.init( ‘Click on me!’, format, 0xCCCCCC, 1, 0x333333, 10 );
 
                   addChild( button );
 
                   textField.x = ( stage.stageWidth / 2 ) — ( ( textField.width + button.width + 20 ) / 2 );
                   textField.y = 20;
 
                   button.x = textField.x + textField.width + 20;
                   button.y = 20;
 
                   textArea.x = ( stage.stageWidth / 2 ) — ( textArea.width / 2 );
                   textArea.y = 60;
               }
           }
       }

Так что это наш базовый класс в значительной степени закончен. Теперь перейдем к написанию классов для общения с AMFPHP.

Я предполагаю, что вы уже работали с загрузкой данных во Flash player. При работе со статическими данными, которые обычно загружаются в самом начале загрузки вашего приложения, хорошо использовать XML или JSON. С динамическими данными это тоже хорошо, но AMF дает вам преимущество постоянного шлюза, хорошей производительности и, что важнее, меньшего количества кода для записи, поскольку нет необходимости кодировать или декодировать данные.

Обычно при работе с данными и Flash вы обычно загружаете статический файл или динамически создаете XML или JSON, например:

Это все честно и хорошо загружает данные, но что, если вы хотите отправить данные? Да, конечно, вы можете настроить несколько классов для отправки данных в динамические сценарии вашего сайта, но тогда вы уже настроили класс для извлечения данных, а затем вам придется изменить его так, чтобы он позволял вам отправлять данные. Плюс, конечно, вам нужно обновить динамические скрипты на серверах вашего сайта. Вот где AMFPHP настолько хорош, что вам нужно создать только один набор классов для ActionScript, и тогда весь ваш PHP-код может содержаться в одной простой кодовой базе. Я также расширю его, чтобы показать вам, как вы можете использовать фреймворк, в данном случае CodeIgniter.

Поскольку AMFPHP — это служба удаленного подключения, вы можете захотеть создать другие классы в будущем, кроме того, какой смысл дублировать код? Что мы сделаем, это создадим три класса:

  • «RemoteConnectionService.as»: он будет действовать как наш базовый класс и будет иметь полезные функции, которые мы можем использовать в будущем для других служб удаленного подключения.
  • «RemoteConnectionServiceEvent.as»: это будет действовать как класс событий, который будет использовать базовый класс
  • «AMFPHPService.as»: и это будет наш класс подключения AMFPHP

Таким образом, мы сможем создать хороший набор классов, а также иметь их чистыми и масштабируемыми, если нам понадобится написать несколько новых в будущем.

Первое, что мы сделаем, это начнем с базового класса. Поэтому создайте файл с именем «RemoteConnectionService.as» в «src / com / flashtuts / lib / data /», и он расширит класс «NetConnection»:

01
02
03
04
05
06
07
08
09
10
11
12
13
package com.flashtuts.lib.data
       {
           import flash.net.NetConnection;
 
           public class RemoteConnectionService extends NetConnection
           {
               public function RemoteConnectionService()
               {
                   super();
               }
 
           }
       }

Теперь у нас есть наш класс, нам нужно написать некоторый код, поэтому мы должны подумать, какие функции можно размещать внутри базы, а не дублировать. Я бы предложил использовать конструктор для установки соединения, затем использовать базу для обработки любых событий, которые отправляет соединение, и, наконец, мы создадим стандартную функцию, которую мы будем использовать для отправки наших данных.

Первое, что нужно сделать, это написать наш конструктор:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.flashtuts.lib.data
       {
           import flash.events.NetStatusEvent;
           import flash.net.NetConnection;
           import flash.net.Responder;
 
           public class RemoteConnectionService extends NetConnection
           {
               public var handleReady:Boolean = true;
 
               public var data:Object;
               public var gatewayURL:String;
               public var responder:Responder;
 
               private var loadedEvent:String;
               private var readyEvent:String;
               private var faultEvent:String;
 
               public function RemoteConnectionService(gatewayURL:String, loadedEvent:String=», readyEvent:String=», faultEvent:String=», encoding:uint=3)
               {
                   this.gatewayURL = gatewayURL;
                   this.loadedEvent = loadedEvent;
                   this.readyEvent = readyEvent;
                   this.faultEvent = faultEvent;
 
                   objectEncoding = encoding;
 
                   if ( gatewayURL )
                   {
                       responder = new Responder( handleResponseResult, handleResponseFault );
 
                       addEventListener( NetStatusEvent.NET_STATUS, handleNetEvent );
 
                       connect( gatewayURL );
                   }
               }
           }
       }

Теперь вам может быть интересно, что на земле все это, чтобы не бояться, вот быстрый бег вниз:

  • Публичные перемены:
    Так как этот класс будет действовать как сервис, нам нужно сообщить ему, где находится шлюз AMFPHP, поэтому мы устанавливаем «gatewayURL», кроме того, чтобы иметь результаты и прослушиватели ошибок, мы должны создать новый «Responder ()» ( Вы можете задаться вопросом, почему это не связано с событиями, может быть, Adobe в тот день похмелилась), и мы свяжем этого респондента с нашими звонками Наконец, всегда удобно иметь возможность хранить данные, которые мы получаем от наших транзакций, в доступной общедоступной переменной, в данном случае называемой «данными».
  • Частные переменные и handleReady var:
    Теперь, так как это базовый класс для нашей службы удаленного подключения, могут возникнуть ситуации, когда вы захотите манипулировать данными до их отправки обратно в ваше приложение. Поэтому вместо того, чтобы просто вызывать событие «готово», я также установил событие «загружено». Это позволит вам подключиться к сервису, манипулировать данными и затем отправить событие «готово». По умолчанию любые подклассы будут определять эти события как часть класса RemoteConnectionServiceEvent (), но у нас есть возможность, при замене, сказать иначе, что обеспечивает большую гибкость.

Когда мы создаем класс, помните, что это базовый класс, поэтому он всегда будет заменен, а не создан сам, мы передаем ‘gatewayURL’, события и значение кодирования (по умолчанию это ‘3’, что Кодировка в стиле AMF3 , идеально подходит для нас).

Теперь нам нужно создать обработчики событий и ответчиков для этого класса, поэтому давайте добавим их:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.flashtuts.lib.data
       {
           import com.flashtuts.lib.events.RemoteConnectionServiceEvent;
 
           import flash.events.NetStatusEvent;
           import flash.net.NetConnection;
           import flash.net.Responder;
 
           public class RemoteConnectionService extends NetConnection
           {
               public var handleReady:Boolean = true;
 
               public var data:Object;
               public var gatewayURL:String;
               public var responder:Responder;
 
               private var loadedEvent:String;
               private var readyEvent:String;
               private var faultEvent:String;
 
               public function RemoteConnectionService(gatewayURL:String, loadedEvent:String=», readyEvent:String=», faultEvent:String=», encoding:uint=3)
               {
                   this.gatewayURL = gatewayURL;
                   this.loadedEvent = loadedEvent;
                   this.readyEvent = readyEvent;
                   this.faultEvent = faultEvent;
 
                   objectEncoding = encoding;
 
                   if ( gatewayURL )
                   {
                       responder = new Responder( handleResponseResult, handleResponseFault );
 
                       addEventListener( NetStatusEvent.NET_STATUS, handleNetEvent );
 
                       connect( gatewayURL );
                   }
               }
 
               private function handleNetEvent(e:NetStatusEvent):void
               {
                   dispatchEvent( new RemoteConnectionServiceEvent( faultEvent, e.info.code ) );
               }
 
               private function handleResponseResult(data:Object):void
               {
                   dispatchEvent( new RemoteConnectionServiceEvent( loadedEvent, data ) );
 
                   if ( handleReady )
                   {
                       handleLoaderDataReady( data );
                   }
               }
 
               public function handleLoaderDataReady(data:Object):void
               {
                   this.data = data;
 
                   dispatchEvent( new RemoteConnectionServiceEvent( readyEvent, data ) );
               }
 
               private function handleResponseFault(data:Object):void
               {
                   dispatchEvent( new RemoteConnectionServiceEvent( faultEvent, data ) );
               }
           }
       }

Здесь вы видите, что мы добавили функции респондента «handleResponseResult ()» и «handleResponseFault ()». Кроме того, у нас есть «handleNetEvent ()», только если что-то падает на его лицо, и, наконец, у нас есть «handleLoaderDataReady ()», который будет вызываться после того, как данные будут готовы — вместо любых хуков, которые вы можете захотеть использовать.

Вы можете видеть, что это всегда отправка событий, которые вы можете определить. Это позволит повысить гибкость и масштабируемость в долгосрочной перспективе.

Так как мы отправляем события из нашего базового класса обслуживания, имеет смысл иметь класс событий по умолчанию. Если вы чувствуете себя ленивым и не можете заняться созданием своего собственного класса событий, вы можете просто использовать это, поскольку мы укажем класс для использования этих событий по умолчанию, поэтому создайте файл с именем «RemoteConnectionServiceEvent.as« inside » SRC / COM / flashtuts / Библиотека / события / «:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.flashtuts.lib.events
       {
           import flash.events.Event;
 
           public class RemoteConnectionServiceEvent extends Event
           {
               public static const NAME:String = ‘RemoteConnectionServiceEvent’;
 
               public static const LOADED:String = NAME + ‘Loaded’;
               public static const READY:String = NAME + ‘Ready’;
               public static const FAULT:String = NAME + ‘Fault’;
 
               public var data:Object;
 
               public function RemoteConnectionServiceEvent(type:String, data:Object=null, bubbles:Boolean=true, cancelable:Boolean=false)
               {
                   super( type, bubbles, cancelable );
 
                   this.data = data;
               }
           }
       }

Это довольно простой класс событий, мы расширяем стандартный класс «Event ()» и добавляем наш собственный публичный var, называемый «data», чтобы мы могли отправлять данные с событием и легко извлекать их через наших слушателей.

Теперь наш базовый класс и его класс событий готовы, все что нам нужно сделать, это расширить базовый класс, чтобы мы могли использовать его для нашего класса обслуживания AMFPHP. Создайте новый файл с именем «AMFPHPService.as» внутри «src / com / flashtuts / lib / data /»:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
package com.flashtuts.lib.data
       {
           import com.flashtuts.lib.events.RemoteConnectionServiceEvent;
 
           import flash.net.ObjectEncoding;
 
           public class AMFPHPService extends RemoteConnectionService
           {
               public function AMFPHPService( url:String )
               {
                   super( url, RemoteConnectionServiceEvent.LOADED, RemoteConnectionServiceEvent.READY, RemoteConnectionServiceEvent.FAULT, ObjectEncoding.AMF3 );
               }
           }
       }

Не смущайтесь, все это будет иметь смысл через несколько параграфов, давайте начнем с конструктора: как я уже говорил, наш базовый класс всегда будет супер-ed, поэтому внутри конструктора мы передаем ‘ переменная url, присваиваемая этому классу при его создании, а также события и, наконец, кодировка по умолчанию. Причина, по которой я решил отделить класс «AMFPHPService ()» от класса «RemoteConnectionService ()», заключается в том, что он обеспечивает большую гибкость и масштабируемость, поскольку вы можете создавать другие службы, которые будут использовать преимущества базы, но имеют разные события и функции.

Прежде чем продолжить, стоит поговорить об этих специальных переменных, называемых … (rest), что в основном означает, что функция может принимать любое количество аргументов, разделенных запятыми, например:

Традиционно вам нужно объявить аргументы функции следующим образом:

1
2
3
4
function test(arg1, arg2, arg3, arg4):void
       {
           …
       }

Однако с помощью аргументов … (rest) вы можете сделать это:

1
2
3
4
function test(… args):void
       {
           …
       }

И назовите это так:

1
test(‘var1’, ‘var2’, ‘var3’, ‘var4’, ‘var5’, ‘varN’, ‘varN+1’);

Таким образом, вы можете использовать любое количество переменных. Затем они доступны в функции в виде массива, например:

1
2
3
4
5
6
7
function test(… args):void
       {
           trace(args.length);
       }
        
       test(‘var1’, ‘var2’);
       test(‘var1’, ‘var2’, ‘var3’, ‘var4’, ‘var5’);

NetConnection.call () использует эти аргументы … (rest), позволяя вам отправлять любое количество аргументов на ваш шлюз. Тем не менее, функция также требует, чтобы вы дали ‘отвечающий’, то, что мы создали в нашем классе «RemoteConnectionService ()». Так как нам всегда нужно использовать эту функцию call (), но мы не хотим писать переменную ‘responseder’ каждый раз, когда мы ее используем, мы должны поместить ее в наш базовый класс. Давайте откроем класс «RemoteConnectionService ()» и обновим его следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.flashtuts.lib.data
       {
           import com.flashtuts.lib.events.RemoteConnectionServiceEvent;
 
           import flash.events.NetStatusEvent;
           import flash.net.NetConnection;
           import flash.net.Responder;
 
           public class RemoteConnectionService extends NetConnection
           {
               public var handleReady:Boolean = true;
 
               public var data:Object;
               public var gatewayURL:String;
               public var responder:Responder;
 
               private var loadedEvent:String;
               private var readyEvent:String;
               private var faultEvent:String;
 
               public function RemoteConnectionService(gatewayURL:String, loadedEvent:String=», readyEvent:String=», faultEvent:String=», encoding:uint=3)
               {
                   this.gatewayURL = gatewayURL;
                   this.loadedEvent = loadedEvent;
                   this.readyEvent = readyEvent;
                   this.faultEvent = faultEvent;
 
                   objectEncoding = encoding;
 
                   if ( gatewayURL )
                   {
                       responder = new Responder( handleResponseResult, handleResponseFault );
 
                       addEventListener( NetStatusEvent.NET_STATUS, handleNetEvent );
 
                       connect( gatewayURL );
                   }
               }
 
               public function send(method:String, … args):void
               {
                   call.apply( null, [ method, responder ].concat( args ) );
               }
 
               private function handleNetEvent(e:NetStatusEvent):void
               {
                   dispatchEvent( new RemoteConnectionServiceEvent( faultEvent, e.info.code ) );
               }
 
               private function handleResponseResult(data:Object):void
               {
                   dispatchEvent( new RemoteConnectionServiceEvent( loadedEvent, data ) );
 
                   if ( handleReady )
                   {
                       handleLoaderDataReady( data );
                   }
               }
 
               public function handleLoaderDataReady(data:Object):void
               {
                   this.data = data;
 
                   dispatchEvent( new RemoteConnectionServiceEvent( readyEvent, data ) );
               }
 
               private function handleResponseFault(data:Object):void
               {
                   dispatchEvent( new RemoteConnectionServiceEvent( faultEvent, data ) );
               }
           }
       }

Теперь, когда наши сервисные классы готовы, если мы вернемся к базовому классу нашего приложения, мы должны добавить сервис, создав его как переменную для всего класса и создав его в нашей функции «init ()»:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package
       {
           import com.flashtuts.lib.data.AMFPHPService;
           import com.flashtuts.lib.display.ui.Button;
           import com.flashtuts.lib.display.ui.InputTextArea;
           import com.flashtuts.lib.display.ui.InputTextField;
 
           import flash.display.GradientType;
           import flash.display.Sprite;
           import flash.events.MouseEvent;
           import flash.geom.Matrix;
           import flash.text.Font;
           import flash.text.TextFormat;
 
           [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
           public class App extends Sprite
           {
               private var service:AMFPHPService = new AMFPHPService( ‘http://localhost/amfphp/gateway.php’ );
               private var textField:InputTextField = new InputTextField();
               private var textArea:InputTextArea = new InputTextArea();
 
               [Embed( systemFont=’Arial’, fontName=’Arial’, mimeType=’application/x-font’ )]
               private var arialFont:Class;
 
               public function App()
               {
                   init();
               }
 
               private function init():void
               {
                   var mat:Matrix = new Matrix();
                   var bg:Sprite = new Sprite();
 
                   mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );
 
                   bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
                   bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
                   bg.graphics.endFill();
 
                   addChild( bg );
 
                   Font.registerFont( arialFont );
 
                   addTextField();
               }
 
               private function addTextField():void
               {
                   var format:TextFormat = new TextFormat( ‘Arial’, 12, 0x000000 );
                   var button:Button = new Button();
 
                   textField.init( format, 200, 25, 0xFFFFFF, 1, 0x333333, 10 );
 
                   textField.text = ‘Hello’;
 
                   addChild( textField );
 
                   textArea.init( format, 300, 200, 0xFFFFFF, 1, 0x333333, 10 );
 
                   textArea.text = ‘Text will appear here that’s returned from the server!’;
 
                   addChild( textArea );
 
                   button.init( ‘Click on me!’, format, 0xCCCCCC, 1, 0x333333, 10 );
 
                   addChild( button );
 
                   textField.x = ( stage.stageWidth / 2 ) — ( ( textField.width + button.width + 20 ) / 2 );
                   textField.y = 20;
 
                   button.x = textField.x + textField.width + 20;
                   button.y = 20;
 
                   textArea.x = ( stage.stageWidth / 2 ) — ( textArea.width / 2 );
                   textArea.y = 60;
               }
           }
       }

И поскольку мы собираемся использовать службу, когда пользователь нажимает кнопку, нам нужно добавить прослушиватели событий для кнопок, а затем настроить функцию, которая будет запускать функцию нашего сервиса «send ()» для выполнения вызова:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package
       {
           import com.flashtuts.lib.data.AMFPHPService;
           import com.flashtuts.lib.display.ui.Button;
           import com.flashtuts.lib.display.ui.InputTextArea;
           import com.flashtuts.lib.display.ui.InputTextField;
 
           import flash.display.GradientType;
           import flash.display.Sprite;
           import flash.events.MouseEvent;
           import flash.geom.Matrix;
           import flash.text.Font;
           import flash.text.TextFormat;
 
           [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
           public class App extends Sprite
           {
               private var service:AMFPHPService = new AMFPHPService( ‘http://dev.ahmednuaman.com/amfphp/gateway.php’ );
               private var textField:InputTextField = new InputTextField();
               private var textArea:InputTextArea = new InputTextArea();
 
               [Embed( systemFont=’Arial’, fontName=’Arial’, mimeType=’application/x-font’ )]
               private var arialFont:Class;
 
               public function App()
               {
                   init();
               }
 
               private function init():void
               {
                   var mat:Matrix = new Matrix();
                   var bg:Sprite = new Sprite();
 
                   mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );
 
                   bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
                   bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
                   bg.graphics.endFill();
 
                   addChild( bg );
 
                   Font.registerFont( arialFont );
 
                   addTextField();
               }
 
               private function addTextField():void
               {
                   var format:TextFormat = new TextFormat( ‘Arial’, 12, 0x000000 );
                   var button:Button = new Button();
 
                   textField.init( format, 200, 25, 0xFFFFFF, 1, 0x333333, 10 );
 
                   textField.text = ‘Hello’;
 
                   addChild( textField );
 
                   textArea.init( format, 300, 200, 0xFFFFFF, 1, 0x333333, 10 );
 
                   textArea.text = ‘Text will appear here that’s returned from the server!’;
 
                   addChild( textArea );
 
                   button.init( ‘Click on me!’, format, 0xCCCCCC, 1, 0x333333, 10 );
 
                   button.addEventListener( MouseEvent.CLICK, handleButtonClick );
 
                   addChild( button );
 
                   textField.x = ( stage.stageWidth / 2 ) — ( ( textField.width + button.width + 20 ) / 2 );
                   textField.y = 20;
 
                   button.x = textField.x + textField.width + 20;
                   button.y = 20;
 
                   textArea.x = ( stage.stageWidth / 2 ) — ( textArea.width / 2 );
                   textArea.y = 60;
               }
 
               private function handleButtonClick(e:MouseEvent):void
               {
                   service.send( ‘HelloWorld.say’, textField.text );
               }
           }
       }

Вы увидите, что мы используем метод под названием «HelloWorld.say», это тестовый сервис AMFPHP, и я покажу вам, как создать свой собственный. И, наконец, нам нужно добавить слушатели к сервису, чтобы мы могли обработать событие ready и отобразить ответ в текстовой области:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package
       {
           import com.flashtuts.lib.data.AMFPHPService;
           import com.flashtuts.lib.display.ui.Button;
           import com.flashtuts.lib.display.ui.InputTextArea;
           import com.flashtuts.lib.display.ui.InputTextField;
           import com.flashtuts.lib.events.RemoteConnectionServiceEvent;
 
           import flash.display.GradientType;
           import flash.display.Sprite;
           import flash.events.MouseEvent;
           import flash.geom.Matrix;
           import flash.text.Font;
           import flash.text.TextFormat;
 
           [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
           public class App extends Sprite
           {
               private var service:AMFPHPService = new AMFPHPService( ‘http://dev.ahmednuaman.com/amfphp/gateway.php’ );
               private var textField:InputTextField = new InputTextField();
               private var textArea:InputTextArea = new InputTextArea();
 
               [Embed( systemFont=’Arial’, fontName=’Arial’, mimeType=’application/x-font’ )]
               private var arialFont:Class;
 
               public function App()
               {
                   init();
               }
 
               private function init():void
               {
                   var mat:Matrix = new Matrix();
                   var bg:Sprite = new Sprite();
 
                   mat.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI * .5 );
 
                   bg.graphics.beginGradientFill( GradientType.LINEAR, [ 0x333333, 0x000000 ], [ 1, 1 ], [ 0, 255 ], mat );
                   bg.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
                   bg.graphics.endFill();
 
                   addChild( bg );
 
                   Font.registerFont( arialFont );
 
                   addTextField();
 
                   service.addEventListener( RemoteConnectionServiceEvent.READY, handleDataReady );
               }
 
               private function addTextField():void
               {
                   var format:TextFormat = new TextFormat( ‘Arial’, 12, 0x000000 );
                   var button:Button = new Button();
 
                   textField.init( format, 200, 25, 0xFFFFFF, 1, 0x333333, 10 );
 
                   textField.text = ‘Hello’;
 
                   addChild( textField );
 
                   textArea.init( format, 300, 200, 0xFFFFFF, 1, 0x333333, 10 );
 
                   textArea.text = ‘Text will appear here that’s returned from the server!’;
 
                   addChild( textArea );
 
                   button.init( ‘Click on me!’, format, 0xCCCCCC, 1, 0x333333, 10 );
 
                   button.addEventListener( MouseEvent.CLICK, handleButtonClick );
 
                   addChild( button );
 
                   textField.x = ( stage.stageWidth / 2 ) — ( ( textField.width + button.width + 20 ) / 2 );
                   textField.y = 20;
 
                   button.x = textField.x + textField.width + 20;
                   button.y = 20;
 
                   textArea.x = ( stage.stageWidth / 2 ) — ( textArea.width / 2 );
                   textArea.y = 60;
               }
 
               private function handleButtonClick(e:MouseEvent):void
               {
                   service.send( ‘HelloWorld.say’, textField.text );
               }
 
               private function handleDataReady(e:RemoteConnectionServiceEvent):void
               {
                   textArea.text = e.data.toString();
               }
           }
       }

Вот и сделали наши классы ActionScript! Теперь немного PHP!

Первое, что нужно сделать, это зайти на сайт AMFPHP и скачать себе копию базы кода . Получив его, распакуйте его и прикрепите к тестовому серверу или запустите на локальном хосте. Если вы новичок в PHP, стоит почитать об этом на w3schools.com .

Как только вы будете довольны тем, что знаете достаточно о PHP, самое время испачкать руки! Идея AMFPHP заключается в том, что вы можете создать набор служб и вызывать их так же, как при импорте файлов в ActionScript, например:

AMFPHP поставляется со стандартным сервисом под названием HelloWorld.say. Класс и файл называются HelloWorld, а функция называется say. AMFPHP переходит в папку services, находит файл с именем «HelloWorld.php», создает класс с именем «HelloWorld» и затем запускает функцию «say». Если бы у вас был класс с именем «Test», который принадлежал к базе кода «com.flashtuts», то вы создали бы файл с именем «Test.php» внутри папок «com / flashtuts /», тогда вы бы ссылались на сервис как ‘com.flashtuts.Test.function. Просто а?

Первое, что мы собираемся сделать, это просто заставить наш класс PHP возвращать простую строку, а затем мы перейдем к интеграции CodeIgniter.

Так как мы по умолчанию установили текст в поле ввода, чтобы сказать «Hello», мы можем также сказать что-нибудь обратно, поэтому создайте новый файл с именем «HelloWorld.php» в папке «services» в папке AMFPHP и используйте следующее учебный класс:

01
02
03
04
05
06
07
08
09
10
11
12
13
<?php
       /* include the AMFPHP utils */
       include_once( AMFPHP_BASE . ‘shared/util/MethodTable.php’ );
        
       class HelloWorld
       {
           function say($msg)
           {
               return ‘You said: ‘ .
           }
       }
        
       ?>

Теперь, если вы запустите свое приложение, вы увидите, что сервер вернет «Вы сказали: (что бы вы ни говорили, возможно, привет!)» В текстовой области без брекета в конце. Да, вы использовали AMFPHP, хорошая работа! Давайте немного глубже.

Мы вернули то, что отправили на сервер, но кому это нужно? Конечно, мы хотели бы сохранить что-то в базе данных, верно? Итак, давайте разберемся с этим. Откройте файл «globals.php» в базовом каталоге AMFPHP, и вы увидите немного кода, который закомментирован так:

1
2
3
4
5
6
7
8
9
/*
       if(!PRODUCTION_SERVER)
       {
           define(«DB_HOST», «localhost»);
           define(«DB_USER», «root»);
           define(«DB_PASS», «»);
           define(«DB_NAME», «amfphp»);
       }
       */

Вы можете скопировать это и вставить его внизу или просто раскомментировать, мы будем использовать его для установки доступа к нашей БД. Введите имя пользователя, пароль и базу данных вашей БД, чтобы она выглядела следующим образом

1
2
3
4
5
6
7
if(!PRODUCTION_SERVER)
       {
           define(«DB_HOST», «localhost»);
           define(«DB_USER», «bob»);
           define(«DB_PASS», «bobsCatsName»);
           define(«DB_NAME», «bobsDatabase»);
       }

Теперь мы готовы изменить наш класс PHP, поэтому загрузите класс обслуживания «HelloWorld.php» и вставьте в него следующее:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
       include_once( AMFPHP_BASE . ‘shared/util/MethodTable.php’ );
 
       class HelloWorld
       {
           var $db;
 
           function __construct()
           {
               $this->db = mysql_connect( DB_HOST, DB_USER, DB_PASS );
               mysql_select_db( DB_NAME );
           }
 
           function say($msg)
           {
               return ‘You said: ‘ .
           }
 
           function put($data)
           {
               $query = mysql_query( ‘INSERT INTO hello_world ( id, data ) VALUES ( \’\’, \» . $data . ‘\’ )’, $this->db );
 
               if ( $query )
               {
                   return mysql_insert_id();
               }
               else
               {
                   return mysql_error();
               }
           }
       }
 
       /* End of file HelloWorld.php */
       /* Location: ./services/HelloWorld.php */
       ?>

Вот быстрый пробег через:

  • Мы создаем переменную всего класса с именем $ db, мы будем использовать ее для хранения нашего соединения с базой данных, чтобы нам не нужно было переподключаться в наших функциях
  • Функция «__construct ()» устанавливает для нас соединение с базой данных
  • Функция «put ()» вставляет строку $ data в таблицу с именем ‘hello_world’ в нашей базе данных

Круто да? давайте попробуем это. Измените метод в вашем приложении ActionScript на HelloWorld.put, запустите отладку и попробуйте. Затем используйте ваш браузер SQL или phpMyAdmin, чтобы проверить результаты в вашей базе данных. Вы должны увидеть идентификатор вставки, возвращенный в вашей текстовой области.

Теперь можно остановиться на вышесказанном, вы можете сделать несколько классов и функций, которые будут соответствовать потребностям вашего сайта, но что, если у вас есть большие надежды? Мы все знаем, что создание приложений может быть быстрее при использовании фреймворков, а CodeIgniter — отличная фреймворк Я не хочу вдаваться в аргумент о том, какую платформу использовать, потому что в конце концов CodeIgniter работает для меня по нескольким простым причинам:

  • Это легкий
  • Это просто установить
  • Это легко учиться
  • Он получил хорошую поддержку сообщества
  • И это бесплатно!

Существуют и другие фреймворки, но для этого я покажу вам, как вы можете подключить CodeIgniter к платформе AMFPHP.

Возьмите копию CodeIgniter со своего сайта , распакуйте ее и вставьте на свой сервер или локальный хост. Это довольно просто установить, но пока нам не нужно настраивать базу данных или что-то в этом роде. Для дальнейшего использования прочитайте их руководство пользователя . Поэтому, если вы затем загрузите свой браузер и укажете его туда, где вы поместили CodeIgniter, вы увидите что-то вроде этого

Хорошо, теперь нам нужно изменить вывод CodeIgniter с помощью ловушки. Хук — это просто метод, который позволяет нам «зацепиться» за ядро ​​системы без непосредственного редактирования кода CodeIgniter. Поэтому нам нужно отредактировать конфигурацию CodeIgniter, чтобы мы могли включить хуки, зарегистрировать наш хук и затем написать наш хук. В вашем каталоге CodeIgniter откройте «system / application / config / config.php», прокрутите вниз до строки 91 и измените переменную на true:

1
$config[‘enable_hooks’] = TRUE;

Теперь откройте «hooks.php» в той же папке и добавьте следующий код перед строкой «/ * Конец файла … * /» (добавьте его в строку 13):

1
2
3
4
5
6
$hook[‘display_override’] = array(
                                       ‘class’ => ‘AMFPHP’,
                                       ‘function’ => ‘output’,
                                       ‘filename’ => ‘amfphp.php’,
                                       ‘filepath’ => ‘hooks’
                                   );

Здесь мы говорим CodeIgniter о том, что мы хотим, чтобы он переопределял свой метод вывода вывода и вместо этого перенаправлял все в наш класс ловушек под названием AMFPHP в файле hooks / amfphp.php. Поскольку такого штрафа не существует, создайте файл «system / application / hooks / amfphp.php» и используйте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<?php if ( !defined(‘BASEPATH’) ) exit( ‘No direct script access allowed’ );
 
       class AMFPHP
       {
           function output()
           {
               if ( !defined( ‘AMFPHP’ ) )
               {
                   $CI =& get_instance();
 
                   $CI->output->_display( $CI->output->get_output() );
               }
           }
       }
 
       /* End of file amfphp.php */
       /* Location: ./system/application/hooks/amfphp.php */
       ?>

Все, что мы делаем здесь, это говорим CodeIgniter написать свой вывод. Таким образом, мы контролируем систему, проверяя, что мы не делаем запрос через AMFPHP, чтобы он мог отображать код как обычно, иначе AMFPHP не будет работать.

Хорошо, мы почти на месте, все, что нам нужно сделать сейчас, — это создать наш контроллер, чтобы мы могли возвращать данные обратно на шлюз AMFPHP. Создайте файл с именем «system / application / controllers / main.php» и вставьте его в файл:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<?php if ( !defined(‘BASEPATH’) && !defined(‘AMFPHP’) ) exit( ‘No direct script access allowed’ );
 
       class Main extends Controller
       {
           function __construct()
           {
               parent::Controller();
           }
 
           function index()
           {
               global $value;
 
               $value = $_POST;
           }
       }
 
       /* End of file main.php */
       /* Location: ./system/application/controllers/main.php */
       ?>

Все, что мы собираемся сделать здесь, это просто вернуть переменные, которые мы отправили AMFPHP, в виде массива, а не в виде строки, которую мы отправили. Это покажет вам, насколько волшебна AMFPHP, тот факт, что вам не нужно сериализовывать объекты перед отправкой их туда и обратно, является большим преимуществом и ускоряет процесс.

Мы действительно почти там! Теперь нам нужно создать сервис, который будет вызывать платформу CodeIgniter. Этот сервис будет работать так же, как и созданный нами сервис «HelloWorld.php», но вместо этого запустит CodeIgniter, чтобы мы могли получить доступ ко всем его достоинствам. Создайте новый файл в каталоге AMFPHP «services / CI.php» и вставьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
       include_once( AMFPHP_BASE . ‘shared/util/MethodTable.php’ );
 
       class CI
       {
           function execute($path=», $vars=false)
           {
               global $value;
 
               define( ‘AMFPHP’, true );
 
               if ( $vars && is_array( $vars ) )
               {
                   $_POST = $vars;
               }
 
               $_SERVER[‘PATH_INFO’] = $_SERVER[‘QUERY_STRING’] = $_SERVER[‘REQUEST_URI’] = ‘/’ .
 
               require_once( ‘../../codeigniter/index.php’ );
 
               return $value;
           }
       }
 
       /* End of file CI.php */
       /* Location: ./services/CI.php */
       ?>

Мы определяем функцию с именем execute (), в которой мы передаем URL нашего метода CodeIgniter ‘spoof’ (если вы запутались, он работает по базовому принципу URL-адресов MVC, когда приложение реагирует на шаблоны URL, такие как http: // host / controller / function / value1 / value2 / valueN , вы можете узнать больше здесь: http://codeigniter.com/user_guide/general/urls.html ) и значения для этого метода. Затем требуется файл index.php вашего приложения CodeIgniter, убедитесь, что он может найти это, кстати!

Ты так близко! И последнее, что нужно сделать, это сказать CodeIgniter, чтобы он отображал только явные ошибки, поэтому откройте файл «index.php» в каталоге CodeIgniter и отредактируйте строку 12 так:

1
error_reporting(E_ALL ^ E_NOTICE);

Мы говорим PHP не отображать ошибки уведомления, только полные!

И это PHP стороной вниз! Все, что нам нужно сделать, это вернуться к нашему коду ActionScript и изменить метод, поэтому откройте базовый файл вашего приложения и измените метод и значения, которые мы отправляем, следующим образом:

1
2
3
4
private function handleButtonClick(e:MouseEvent):void
       {
           service.send( ‘CI.execute’, ‘main’, [ textField.text, ‘another var’, 1, 0xFFFFFF, { data: ‘test’, data2: ‘test2’ } ] );
       }

Здесь мы отправляем массив, а не количество значений. Это проще и означает, что ваш шлюз может получить метод (как «URL») и данные как массив.

Там у нас это есть! Вы только что углубились в AMFPHP как со стороны ActionScript, так и со стороны PHP! Congrats!

В то время как некоторые люди могут спросить, в чем смысл этого, в профессиональной жизни разработчиков будут времена, когда ему или ей потребуется использовать AMFPHP, когда дело доходит до отправки и получения данных. И хотя XML и JSON прекрасно работают, прелесть AMFPHP в том, что когда вы настраиваете классы (как вы только что это сделали), вам не нужно беспокоиться о радостях сериализации данных и их синтаксического анализа на принимающей стороне, так как это все сделано для вас!