Apr 02, 2009

Flex remoting with CakePHP - CpAmf plugin

by: Daniel Verner

A new version of the CpAmf plugin is available. Check out the new version here.

The goal of this project was to use CakePHP controllers as flash remoting services. The basic idea was to use AMFPHP 1.9, because we used it before and it was a good choice in earlier projects. As nobody wants to "reinvent the wheel", I googled for a solution to integrate the AMFPHP into the CakePHP framework.

After a short research I found the following solutions:

  1. cakeAMFPHP plugin
  2. cakeAMF plugin

I tried both solutions, but cakeAMFPHP does not use the latest AMFPHP, and with cakeAMF there was a problem using flex RemoteObjects.

The idea for my implementation came from cakeAMFPHP.

Requirements

  1. CakePHP 1.2
  2. AMFPHP 1.9
  3. AMF extension (optional)

Introduction

This plugin is based on the latest AMFPHP package, and works with CakePHP 1.2. The amf plugin uses all features of the AMFPHP package: works with or without the AMF PHP extension (if amfext is installed and enabled, it will be automatically used by this plugin).

CpAmf plugin allows you to use CakePHP controllers as "services", using all CakePHP controller features (models, behaviors etc.), also works with flex RemotingObject, and can be used with MATE framework (flex).

Installation

Just copy the plugin into your cake application's "plugins" directory. To check the gateway installation, simply open the following url:
yourdomain.com/cpamf/gateway.

You should see a message like this:
amfphp and this gateway are installed correctly.
You may now connect to this gateway from Flash.

If you have the amf extension you shuld see this in message:
AMF C Extension is loaded and enabled.

Value Object mapping

Amfphp has a useful feature: the VO mapping. CpAmf plugin uses this feature in a bit specialized way. We create a model in CakePHP, and a Class in flex which corresponds to our model.
The metedata tag to achieve this mapping is:
[RemoteClass(alias="User")]

In our model we create an afterFilter method, and use the cakePHP built in Set::Map() function to convert the associative array to an object (or array of objects). We use generic class here (php's dummy class 'stdClass'), set the _explicitType property of all objects, and unset the _name_ property (which is set by Set::Map() method), because we don't need this property in our flex class. This approach allows us to change the model, and the corresponding flex class without the need for changing the vo classes (we don't even need to create them).

When we get data (object) from flex we don't use mapping, on php side we use associative arrays. The amfphp vo directory is set to default value (vendors/amfphp/services/vo). You can change this value if you want to use objects on php side (vendors/amfphp/globals.php).

We use one special vo class: ArrayCollection.php, it allows us to map an array of objects (php side) to an ArrayCollection of objects (flex side). Thanks to Wade Arnold for this solution.

Using the service browser

AMFPHP comes with a handy utility called service browser, which is useful for testing the services (or in this case controllers). Although you can test your controllers with CakePHP itself, but if you want to test them using flash remoting you can use the service browser.
The browser is accessible at the following url:
yourdomain.com/cpamf/browser.

NOTE: The service browser is working only when the debugging is enabled in cakePHP.

Special thanks to the developers of:

  1. cakeAMFPHP plugin
  2. cakeAMF plugin
  3. AMFPHP
  4. CakePHP

Download

CpAmf plugin v0.10

Examples

For more info see the flex and PHP examples.

Share this post:

42 comments

meix

meix

Thanks man, works like a charm!

Apr 05, 2009 (12:35:27) - #1
Nandor Stanko

Nandor Stanko

Looking forward to use it... :)

Apr 05, 2009 (16:16:07) - #2
boxtrader

boxtrader

Thank you , nice code.
I would like to read non mate code.

Apr 07, 2009 (21:48:25) - #3
Daniel Verner

Daniel Verner

In my spare time I will create a non mate example. But anyway you can call services the usual way, see the source of the service browser (vendors/amfphp/browser/servicebrowser.mxml).

Apr 07, 2009 (22:10:25) - #4
alan

alan

Great! Many thanks! Want to try it asap but I'm on windows machine... can't run cakephp.

Do you include an example in CpAmf plugin v0.10 download?

Thanks again!

May 06, 2009 (06:47:55) - #5
Daniel Verner

Daniel Verner

@alan
You can run cakephp on windows machine, install Xampp or easyphp.
You can find CpAmf examples here:
flex: http://carrotplant.com/en/blog/cpamf-flex-example
php: http://carrotplant.com/en/blog/cpamf-php-example

May 06, 2009 (08:26:22) - #6
alan

alan

you are greatest Daniel!

May 06, 2009 (14:19:28) - #7
alan

alan

Hi Daniel,

The gateway page still gives me file not found... what is the problem?

May 11, 2009 (03:57:56) - #8
alan

alan

Yea, got it sorted... it was cake's problem. I need to set the apache's config, not the .htaccess . Also, need to set the www directory's AllowOverride, not the default.

Thanks all.

May 11, 2009 (08:03:34) - #9
alan

alan

Hey Danial, it's working now! For some reason Flex didn't recomplie from the source. Once it recompiled with "localhost" instead of 127.0.0.1, it worked!!!

Many thanks for the example, time for me to study how all these work now! You're my hero!

May 12, 2009 (07:58:53) - #10
Kelsey

Kelsey

Hi Daniel,

Thank you for this software. I found that I needed to make a small change to the code in order to get the method table detection to work properly for me. Perhaps this will be useful for others.

Index: plugins/cpamf/controllers/discovery_service_contro ller.php
=====================================
--- plugins/cpamf/controllers/discovery_service_contro ller.php (revision 23)
+++ plugins/cpamf/controllers/discovery_service_contro ller.php (revision 24)
@@ -75,8 +75,7 @@
//Generate the method table from this info
// Browse the cakePHP controllers folder
$this->_path = CONTROLLERS;
-
- $methodTable = CakeMethodTable::create($this->_path . $path . $className . '.php', NULL, $classComment);
+ $methodTable = CakeMethodTable::create($className, $this->_path, $classComment);
return array($methodTable, $classComment);
}

May 24, 2009 (18:16:22) - #11
Phil

Phil

Thanks for the great plugin. I've managed to get it to work but I am having a lot of problems using it with the Auth Component.

If I do not $this->Auth->allow("*") in CpamfAppController 's beforeFilter() then I do not have access to the gateway. Unfortunately this also makes all of my controller methods accessible even if the user is not authenticated.

Is there any workaround you could recommend?

Thanks again for the great work.

May 25, 2009 (18:13:44) - #12
moon

moon

Hello,
I wanted to use cpamf, but it deosn't work !
I have many questions:

1- What is the php version used ?? (php4 or php5)
2- What is the AMF version used ? (AMF0 or AMF3)
3- Can we use cpamf with Flash CS4 (not Flex) ?
4- If question 3 is YES, how do we call a remote service ?

I am using the cpamf_test example, but not able to make it work:
1- The browser deosn't work. Many errors:

missing ; before statement
[Break on this error] C
AC_OETags.js (ligne 5)
missing ; before statement
[Break on this error] C
history.js (ligne 5)
DetectFlashVer is not defined
[Break on this error] var hasProductInstall = DetectFlashVer(6, 0, 65);

2- If I try: mysite.com/cpamf/gateway, it works fine. It says that it is installed correctly, HOWEVER, when i try to call a service from CS4 (AS3), it says: call.badVersion .
Do you know why ?

How do we call the method of a service ?
Let say my controller class is UsersController, what do we have to call and how ?

I had a loo

Jun 12, 2009 (17:29:03) - #13
moon

moon

2- If I try: mysite.com/cpamf/gateway, it works fine. It says that it is installed correctly, HOWEVER, when i try to call a service from CS4 (AS3), it says: call.badVersion .
Do you know why ?

How do we call the method of a service ?
Let say my controller class is UsersController, what do we have to call and how ?

I had a look at the amf tutorial, but couldn't have answers to my questions !
Need Help !

Jun 12, 2009 (17:30:47) - #14
Daniel Verner

Daniel Verner

@moon
1. PHP5 is used
2. AMF3
3. I didn't tested cpamf plugin with flash, but in principle it can be used with flash.

The service browser error is strange. Which browser and op system you use?

Jun 15, 2009 (09:38:09) - #15
Peter Jankovich

Peter Jankovich

@moon
"call.badVersion" error may appear due to incorrect gateway URL.

Please make sure you have set the correct gateway URL in the service browser. By default it should be "localhost/cpamf/gateway", assuming you are using localhost as your hostname. Note that there's no trailing ".php"! You can edit this by clicking on the settings icon in the upper left corner of the service browser.

Jun 15, 2009 (19:28:45) - #16
Abdul Gaffar

Abdul Gaffar

Daniel you are great!

But I m new in flex and want work with cake php grid listing. I have installed cpamf and getting when I run
mysite.com/cpamf/gateway, it works fine. It says that it is installed correctly, HOWEVER please guide me how I can call a controller's function or models which already in my app like users_controller, User model. Please suggest me one flow from cake php using database model to flex

Jun 25, 2009 (15:51:27) - #17
Daniel Verner

Daniel Verner

@Abdul Gaffar

Have you checked out my php/flex examples? If you haven't, please give them a look! You'll understand a lot of things from them.

You can find the examples here:
flex: http://carrotplant.com/en/blog/cpamf-flex-example
php: http://carrotplant.com/en/blog/cpamf-php-example

Jun 25, 2009 (20:30:26) - #18
Abdul Gaffar

Abdul Gaffar

Hi Daniel, I have seen the examples but I m sorry to say that still I am unable to get it. Please tell me two questions: 1) where I will put the flex project? is it in app/plugins ? 2) How I will call the cakephp controller functios or model functions from flex?

I am really sorry for this type of foolish question to ask but I am really helpless. Please help me. I need it.

Jun 26, 2009 (14:48:46) - #19
Daniel Verner

Daniel Verner

@Abdul Gaffar

1) The flex example is a flex builder project. It is not necessary to put the flex project in the webserver's document root. Simply open the project with flex builder, and start the debug session
2) My example uses MATE framework, so the actual service call is made in the MainEventMap.mxml, using the RemoteObjectInvoker TAG.

I will rework the example without MATE, and it will be easier to understand.

Jun 26, 2009 (18:17:47) - #20
Daniel Verner

Daniel Verner

A non MATE version of the flex example is now available:
http://carrotplant.com/en/blog/cpamf-no ... ex-example

Jun 26, 2009 (23:55:00) - #21
Moon

Moon

Hello Daniel,

my application deosn't work anymore when updating the cpAmf plugin.

It worked fine with the last version of cpAmf.

I have just replaced the old cpAmf directory in my: app/plugins by the new one.

When I try : mydomain.com/cpamf/gateway the page is empty. (even gateway.php)
The browser deosn't work as well (logic !)

Do I have to modify something in my application ??

Regards.

Jul 01, 2009 (10:29:50) - #22
Daniel Verner

Daniel Verner

@Moon
Maybe there is a php error. You should check your apache log for php errors.
Is the CpAmf v0.11 working with my cpamf_test application?

Please provide additional information about the error.

If there is a problem with the new version I will fix it ASAP.

Jul 01, 2009 (13:31:42) - #23
michalwski

michalwski

Hi,
Does any one know how to use this plugin with cairngorm?

My problem is that I don't get ArrayCollection in result when I call getAllUsers but something like that:

[ResultEvent messageId="2D650CDF-BBD8-1BA8-431A-00003FCEE0E7" type="result" bubbles=false cancelable=true eventPhase=2]

Jul 26, 2009 (10:10:00) - #24
Daniel Verner

Daniel Verner

@michalwski Hi! I never used cairngorm, but maybe you should try to use event.result, instead of the ResultEvent.

Jul 26, 2009 (15:08:12) - #25
michalwski

michalwski

Thanks, it works now. I should have to read your example more carefuly before I asked.

Jul 26, 2009 (18:47:31) - #26
Julien

Julien

Hello,

Great work !

I just have a problem with PHP Models which have a hasOne !

In Flex it gives me an object that not matches with its Value Object (for the Object retrieved with hasOne)

Aug 07, 2009 (01:12:37) - #27
Daniel Verner

Daniel Verner

@Julien
Hi,

It looks like you have a problem with mapping. You shuold use the Set::Map function, and set _explicitType in all your models. (see afterFind in my User model, in php example) If you get data from an another model using hasOne, the data should look like this:
result => array(
some data
.
.
.
[AnotherModel] => array(
data from another model ) ).
In this case you should make an exact same VO class in flex.
pulic class someClass
{
public var someData : string;
public var AnotherClass : AnotherClass;
}

And don't forget to map, and set explicitType in both models.

Another hint: You must create and instance from your VO class somewhere in your application for the mapping to work correctly.

Cheers,

Aug 07, 2009 (09:02:57) - #28
Julien

Julien

Thanks a lot !

It was just a mapping problem, my "hasOne" objects did not have the explicit Types. I works now :)

Aug 07, 2009 (12:16:20) - #29
Martin

Martin

There is a huge problem when developing AIR application. Something is wrong with authorization. I have two methods on php - login, testAction. From cpamf browser i can login and then call testAction. When I have cpamf browser inside AIR app I have "Not authorized..." !!
Someone forced this error ?

Sep 04, 2009 (16:12:43) - #30
Gustavo

Gustavo

Daniel
I have just installed the plugin in my local wampp+cakePHP 1.2 and a newly test app.
The installation seems ok
..."CpAmf plugin v0.12 (CakePHP 1.2)
amfphp and this gateway are installed correctly. You may now connect to this gateway from Flash.
..."
But when trying to load the service browser the following error box appered :
***************************
(mx.rpc::Fault)#0
errorID = 0
faultCode = "Client.Error.MessageSend"
faultDetail = "Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed"
faultString = "Send failed"
message = "faultCode:Client.Error.MessageSend faultString:'Send failed' faultDetail:'Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed'"
name = "Error"
rootCause = (Object)#1
code = "NetConnection.Call.Failed"
description = "HTTP: Failed"
details = "http://localhost/gvcl/cpamf/gateway.php"
level = "error"
***************************
Any help will be appreciatte
Kind regards
G

Sep 25, 2009 (00:47:00) - #31
Gustavo

Gustavo

I found the solution in the web (fooling around) the problem is in the configuration of the service browser "http://localhost/myapp/cpamf/gateway.php" should not have the ".php" extension.

Now I have a different error about the php5executive expecting and object reference instead of a string.
message = "faultCode:AMFPHP_RUNTIME_ERROR faultString:'Parameter 1 to initCakeController() expected to be a reference, value given' faultDetail:'...\myapp\plugins\cpamf\vendors\amfphp\core\shared\app\php5Executive.php on line 123'"
name = "Error"
rootCause = (null)

Any suggestions?

Kind regards
Gustavo

Sep 25, 2009 (21:21:28) - #32
Joel

Joel

Gustavo

Took me almost a whole day to fix this problem. I think you are using a Mac Snow Leopard machine right? PHP 5.3 installed.

Go search for the CakeActions.php file , then find the initCakeController(&$controller)

remove the "&" and it will work.

Oct 08, 2009 (18:37:30) - #33
kaka

kaka

(mx.rpc::Fault)#0
errorID = 0
faultCode = "Client.Error.MessageSend"
faultDetail = "Channel.Connect.Failed error NetConnection.Call.BadVersion: "
faultString = "Send failed"
message = "faultCode:Client.Error.MessageSend faultString:'Send failed' faultDetail:'Channel.Connect.Failed error NetConnection.Call.BadVersion: '"
name = "Error"
rootCause = (Object)#1
code = "NetConnection.Call.BadVersion"
description = ""
details = ""
level = "error"


can you help me ?thanks

Oct 24, 2009 (21:46:10) - #34
kaka

kaka

hi
when i change the version cpamf 0.12:

(mx.rpc::Fault)#0
errorID = 0
faultCode = "Client.Error.MessageSend"
faultDetail = "Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed"
faultString = "Send failed"
message = "faultCode:Client.Error.MessageSend faultString:'Send failed' faultDetail:'Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed'"
name = "Error"
rootCause = (Object)#1
code = "NetConnection.Call.Failed"
description = "HTTP: Failed"
details = "http://localhost/cakephp/cpamf/gateway.php"
level = "error"

can you tell me why ? thank you

Oct 24, 2009 (21:56:53) - #35
Daniel Verner

Daniel Verner

Check your gateway, it should look like: http://domain.com/cpamf/gateway
without ".php" extension.

Oct 27, 2009 (11:36:52) - #36
Alex A

Alex A

Can this AMF plugin handle not just value assignments, but also file uploads from Flex to PHP?

Nov 06, 2009 (11:32:19) - #37
Mike

Mike

Hi ! I'm a cake and flex user.
I tried your amazing cpamf plugin, and I read carefully your cakephp and flex examples.

My problem is I can't really see the connection between my flex app and my cakephp app.

I have my flex project integrated in my cakephp webroot folder.

And when I tried to remote with flex I have this message :

[MessagingError message='Destination 'amfphp' either does not exist or the destination has no channels defined (and the application does not define any default channels.)']


I think there is no connection between my service-congig.xml file and my cpamf services.

Thanks for your help :)

Nov 11, 2009 (18:06:32) - #38
Daniel Verner

Daniel Verner

@Alex A
File upload is a bit different story. You can upload a file from flex to cakephp, using filereference, but in this case it is not an amf message, thus you cant' use the plugin for that. Theoretically you could upload a file like a byte stream using amf message, but then you need to read a file into the flex from local hard drive, which is possible only if you use flash player 10. I recommend using filereference for file upload.

Nov 12, 2009 (08:32:33) - #39
Daniel Verner

Daniel Verner

@Mike
Check your services-config.xml file. You can find an example in my test project. It looks like there is a problem with your services configuration. Don't forget to add -services services-config.xml in your flex compiler configuration: Project/Properties/Flex compiler/Additional compiler arguments.
Tip: If you change the services config, clean and rebuild your project.

Nov 12, 2009 (08:45:15) - #40
Shingo Mori

Shingo Mori

Thanks for great work CpAmf!!

I think it's really good solution to use CakePHP from Flex, so I wrote introduce blogs about how to use CpAmf, for Japanese user.

I hope you like it and it helps someone using CpAmf.

Part1-> http://d.hatena.ne.jp/sngmr/20100107/1262884993
Part2-> http://d.hatena.ne.jp/sngmr/20100109/1263052676
Part3-> http://d.hatena.ne.jp/sngmr/20100110/1263145276

Jan 10, 2010 (18:59:57) - #41
Benjamin Morrise

Benjamin Morrise

When I view the service browser all my services have this message: Service does not contain any methods

I have methods on all my services. Any ideas why they wouldn't be showing up?

Jan 30, 2010 (17:04:05) - #42

Your reply

You can't use HTML, but URLs will be automatically linkyfied and Your e-mail address will never be published. We reserve the right to moderate Your comments. Gravatar service is used for avatars. Upload yours at www.gravatar.com.

All fields marked with an asterisk (*) are required!

Remaining characters

security image