The answer is in both the error code, and your comment - error 105 is 'layout is missing', and you've said
$layout_name = ""; // why does it need a layout?
The answer to this is that in FM context is everything, and so you must provide the name of a layout, even if the script doesn't have to interact with it.
You've also said
//when specifying a valid layout name, get error 3 - Command is unavailable (for example, wrong operating system, wrong mode, etc.)
this will be because the Send Event command isn't compatible with CWP. In ScriptMaker if you set the 'Show Compatibility' in the bottom left to Custom Web Publishing, you'll see that Send Event is greyed out, as are Open URL and Exit Application...
You have to imagine that calls you make from PHP are being sent to an imaginary version of Filemaker client that is running on the server, and that each time you make a call to it, it is like the client has just been launched, with no found records, and isn't even in a layout.
It ISN'T running the script you are calling on the copy of Filemaker Pro that is on the Mac/PC that you are currently sat in front of. Forget whatever the copy of Filemaker is doing on the computer in front of you, it is irrelevant.
Therefore, whenever you call a script, you have to to tell the imaginary Filemaker client which layout to go to, and also, make it find the correct set of records to work on. If you don't specify a layout, then it does not know what context to address fields from, i.e. what table occurence it is starting from.
Also, whatever you do (like called AppleScripts or open URL's) will be happening on the server, and in fact, won't happen at all. You cannot guarantee most of the time what state the server is in, and it won't respond to commands such as you have given it (mostly, see documentation)
So when you call a script, you must give it a layout to start from, and you must perform actions on a record that the script you are calling finds for itself. So send parameters (you have 'null') that give the Filemaker script all it needs to know.
Here is a script I use called 'WEB'. I send it two parameters, qtyToReduce and stockCode, in the form "qtyToReduce = 1; stockCode = \"APPLE MD510\"". That way I can use the 'Let' command in Filemaker scripting to extract the two parameters. Note I have to use the ESCAPE character (backslash) as I need to include speechmarks in the Filemaker string.
Go to Layout [ “IWPStart” (Stock) ]
Enter Find Mode [ ]
Set Field [ Stock::Stock Code; GetAsText(Evaluate("Let ([" & Get(ScriptParameter) & "];stockCode) ")) ]
Perform Find [ ]
Set Field [ Stock::In Stock; Stock::In Stock - GetAsNumber(Evaluate("Let ([" & Get(ScriptParameter) & "];qtyToReduce) ")) ]
See how it goes to a particular layout and find a record(s), so it works in the situation where the 'imaginary' Filemaker client has started up in an unknown state.
So you need to write script that changes the contents of a field to check it is working, that is the best test.
Thanks Steve! This is awesome. Would have never assumed that there would be any difference. I see the compatibility options now in the edit script window. I see that you can set variables and perform other scripts which is just fine with me. My earlier hello world was just to execute anything...
Thank you Robert! When you put it that way, layout equals context, I get the need to have a layout. How do you pass in the parameters in PHP, though? I assumed it'd be an array like the below or something different?
$parameters = array("stockCode" => "APPLE MD510", "qtyToReduce" => "5");
Unfortunately parameters have to a string - if you try passing an array you will receive an error from the CWP API - this is why Robert is passing them in the way which he is, then using Evaluate/Let functions to extract the key-value data from that string.
Other people use differnet approaches, including passing the parameters in a known order (without keys) and separated by some delimiter (for example a |), then converting that with the substitute function to a list, or passing in JSON (which can work quite well with your array, if you use PHPs json_encode function) then using a variety of methods to parse that (since FM doesn't have native JSON parsing) like the scripts from this module: http://www.modularfilemaker.org/module/json/
Thanks for that. Just for completeness, this is what I ended up doing...
// PHP PAGE
$script_name = "Hello World";
$layout_name = "Contacts";
$parameters = "2060|Dallas";
$newPerformScript =& $fm->newPerformScriptCommand($layout_name, $script_name, $parameters);
$result = $newPerformScript->execute();
var_dump($result); die; // does get back a filemaker object result, success!
// FILEMAKER SCRIPT
Set Variable [$request; Value:Substitute( Get (ScriptParameter) ;"|"; ¶)]
Set Variable [$contact_id; Value:GetValue ($request; 1)]
Set Variable [$city; Value:GetValue ($request; 2)]
Go to Layout["Some layout"]
# do stuff
Set Field["Some Field"; $city]
Glad we could help. And by the way, I like your way of passing parameters better than mine!!
KRCS Group Ltd