Please Consider Adding "Get KM Variable in PHP" to the Wiki Scripting Page

Currently, the wiki page action:Execute a Shell Script [Keyboard Maestro Wiki] does not have instructions for reading KM variables in PHP.

I did not know how to do that until I found this post and studied the plugin script file.
PHP Action Plugin - Plug In Actions - Keyboard Maestro Discourse

For reference, this is how we get the variable value:

#!/usr/bin/php
<?php

// all KM variables are stored in $_ENV which is an array.
$envVariableArray = $_ENV;

// this is how we get the value of the KM variable "VarName"
echo $envVariableArray["KMVAR_VarName"];

?>
2 Likes

I have a lot of localhost Apache PHP code so thank you for this.

However, do you have a use case you can sketch out for us? PHP being - in my hands - a server side language I don't see a use case yet.

Sorry, I don't have a real case yet.

It's like Python. Once you get the value of KM values, you can use them to do all kinds of things in PHP.

The link I put in the OP is a plugin, but you can study the script file and get an idea about how it works.

1 Like

Hey Martin,

Okay, how do you set a Keyboard Maestro variable from PHP?

Give me a decent example and I'll consider amending the wiki.

-Chris

Hi Chris,

Thanks for considering it.

I had not thought of it before, but after seeing your reply, I did some tests.

Pass KM Variables to PHP

As far as I know, there are three ways to pass KM variables to PHP.

  1. Pass variables through command line.
    I've posted the method here: Pass KM Variables to PHP in Command Line - Tips & Tutorials - Keyboard Maestro Discourse

  2. use $_ENV, as shown in the OP here.

$phpVar = $_ENV["KMVAR_VarName"];
  1. use getenv() function.
$phpVar = getenv("KMVAR_VarName");
  1. use osascript.
$phpVar = exec('osascript -e \'tell application "Keyboard Maestro Engine" to getvariable "VarName"\'');

Methods 2-4 are used inside the PHP code.

Set KM Variables in PHP

Now, setting KM variables in PHP are tricky.
I'll give my conclusion here first: If we want to set KM variables, the proper way is to use osascript.
To demonstrate the point, I've made a PHP script:

#!/usr/bin/php
<?php

//###########################################//
// This PHP code demonstrates how to get variables from KM in PHP
//-----------------------------------------------------------------------//
// Beside passing via Command Line arguments, 
// there are three ways to get the value of KM variable:
// 1. use $_ENV["KMVAR_VarName"]
// 2. use getenv("KMVAR_VarName")
// 3. use osascript
//-----------------------------------------------------------------------//
// Initially, all three should get the same value.
// However, they are actually independent from each other.
// We will see it clearly once we set new value to any of them.
//###########################################//


//###########################################//
// assume the value of VarName in KM is "initial value";
//###########################################//

echo "Before setting any variables in PHP \n";
echo "\n".'-Variable value via $_ENV:'."\n";
echo $_ENV["KMVAR_VarName"];
echo "\n".'-Variable value var getenv():'."\n";
echo getenv("KMVAR_VarName");
echo "\n".'-Variable value via osascript:'."\n";
echo exec('osascript -e \'tell application "Keyboard Maestro Engine" to getvariable "VarName"\'');
echo "\n\nEND\n\n\n";

// All will output "initial value"


//###########################################//
$_ENV["KMVAR_VarName"] = "Value set via ENV";
//-----------------------------------------------------------------------//
// this will NOT change the value of VarName in KM.
//-----------------------------------------------------------------------//
echo "After setting variable via '\$_ENV' \n";
echo "\n".'-Variable value via $_ENV:'."\n";
echo $_ENV["KMVAR_VarName"];
echo "\n".'-Variable value var getenv():'."\n";
echo getenv("KMVAR_VarName");
echo "\n".'-Variable value via osascript:'."\n";
echo exec('osascript -e \'tell application "Keyboard Maestro Engine" to getvariable "VarName"\'');
echo "\n\nEND\n\n\n";
//###########################################//

// Only $_ENV["KMVAR_VarName"] is affected.


//###########################################//
$myVar = "Value set via putenv";
putenv("KMVAR_VarName=$myVar");
//-----------------------------------------------------------------------//
// this will NOT change the value of VarName in KM either.
//-----------------------------------------------------------------------//
echo "After setting variable via 'putenv()' \n";
echo "\n".'-Variable value via $_ENV:'."\n";
echo $_ENV["KMVAR_VarName"];
echo "\n".'-Variable value var getenv():'."\n";
echo getenv("KMVAR_VarName");
echo "\n".'-Variable value via osascript:'."\n";
echo exec('osascript -e \'tell application "Keyboard Maestro Engine" to getvariable "VarName"\'');
echo "\n\nEND\n\n\n";
//###########################################//

// Only getenv("KMVAR_VarName") is affected.


//###########################################//
// use osascript to set KM variables.
exec('osascript -e \'tell application "Keyboard Maestro Engine" to setvariable "VarName" to "new value"\'');
//-----------------------------------------------------------------------//
// This will change the variable value in KM. 
// But $ENV and getenv remain the same values as before the osascript
//###########################################//
echo "After setting variable via osascript \n";
echo "\n".'-Variable value via $_ENV:'."\n";
echo $_ENV["KMVAR_VarName"];
echo "\n".'-Variable value var getenv():'."\n";
echo getenv("KMVAR_VarName");
echo "\n".'-Variable value via osascript:'."\n";
echo exec('osascript -e \'tell application "Keyboard Maestro Engine" to getvariable "VarName"\'');
echo "\n\nEND\n\n";

// Only osascript getvariable is affected.


//###########################################//
// Conclusion on $_ENV, getenv(), and osascript in PHP:
// Before changing the variable values, all three methods will get the KM variable values.
// But they are all independent from each other.
// Changing variable values of one will not change that of the other two.
// If we want to set KM variables, the proper way is to use osascript.
//###########################################//

?>

Output:
image

I've figured out a way to use PHP variables. to set KM variables.
Here is the code:

#!/usr/bin/php
<?php
//###########################################################//
//## This PHP code demonstrates how to set KM variables using osascript ##
//###########################################################//

$kmVarName = "VarName";
$kmVarValue = "this is the new value\nthe 2nd line\nthe 3rd line";

exec('osascript -e \'tell application "Keyboard Maestro Engine" to setvariable "' . $kmVarName . '" to "'. $kmVarValue .'"\'');
?>

I've noticed a problem.
Getting KM variable values using osascript will get only the last line of the variable value. @peternlewis and @ccstone, is this a bug?

After setting the KM variable via osascript, $_ENV["KMVAR_VarName"]; and getenv("KMVAR_VarName"); no longer reflect the new KM variable value. I don't know other ways to get the new KM variable value except using osascript. But if osascript gets only the last line of the variable value, it is not reliable.

(To set a KM variable and then read it back to PHP is a rare case. It is probably never needed. If we need the new value, we can update the variable within the PHP code. So practically, it might not be a problem at all. But getting only the last line of the variable value via osascript getvariable is an unexpected behavior.)

Of course not. Environment variables are local to the process, and are configured when the process launched, after which they can only be modified within the process.

Keyboard Maestro sets them up when it launches the process from the variable values at that time - any changes to Keyboard Maestro variables after that will not affect the environment variables.

Undoubtedly, but it is likely a bug in your code or in PHP’s handling of things, or your handling of the different line endings. Line endings on the Mac vary between \r and \n (and rarely \r\n).

image

tell application "Keyboard Maestro Engine"
	setvariable "Test" to "Hello\nThere\n"
	set x to getvariable "Test"
end tell

Works fine, sets the Test variable to two lines, reads the text variable, both lines, displays it in a window.

In this case, you probably want to use \r instead of \n.

1 Like

The problem is the variable value might already contain \n.
I think I've found the issue. The exec('osascript ...AppleScript...', $output) command return the result as an array, whose elements are lines of the variable value.

Given a KM variable "VarName" with value:

this is the new value
the 2nd line
the 3rd line

Execute this command in PHP:

exec('osascript -e \'tell application "Keyboard Maestro Engine" to getvariable "VarName"\'', $output);
echo var_dump($output);

Result:

array(3) {
  [0]=>
  string(21) "this is the new value"
  [1]=>
  string(12) "the 2nd line"
  [2]=>
  string(12) "the 3rd line"
}

Edit:
The exec() command returns the last line of the variable.
From PHP: exec - Manual:

[exec() returns] The last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.

So, passthru() is the correct command.

$kmVar = passthru('osascript -e \'tell application "Keyboard Maestro Engine" to getvariable "VarName"\'');
echo $kmVar;

Result:

this is the new value
the 2nd line
the 3rd line

OK, so the php exec command is turning the multiline string in to an array, and then using only the last line as the answer.

So I assume this resolves your issues?

Yes. passthru() is the comand to use if we want to return all lines as a string.

I edited my post above to add the info below. I think it's worth being added to the wiki.

Just add one point.
If $_ENV does not get the variable value, it is probably because in the php.ini file E is not included in variables_order.

We can of course add E to variables_order in the php.ini file.
To get the php.ini file, we can

  1. run php -i | grep php.ini to locate the php.ini file. In my case, it is located at /usr/local/etc/php/8.0.
  2. Open the file and search for variables_order. It looks like variables_order = "GPCS". Just add E to it.

However, since we can also get the variable with getenv("KMVAR_VarName");, we don't actually need $_ENV["KMVAR_VarName"];.

This is the instruction in the php.ini file regarding $_ENV:

; This directive determines which super global arrays are registered when PHP
; starts up. G,P,C,E & S are abbreviations for the following respective super
; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty
; paid for the registration of these arrays and because ENV is not as commonly
; used as the others, ENV is not recommended on productions servers. You
; can still get access to the environment variables through getenv() should you
; need to.
; Default Value: "EGPCS"
; Development Value: "GPCS"
; Production Value: "GPCS";
; http://php.net/variables-order
variables_order = "GPCS"

To set KM variables in PHP, we still need to use osascript:

$kmVarName = "VarName";
$kmVarValue = "this is the new value\nthe 2nd line\nthe 3rd line";

exec('osascript -e \'tell application "Keyboard Maestro Engine" to setvariable "' . $kmVarName . '" to "'. $kmVarValue .'"\'');

Of course, as also has been said, we can use osascript to get KM variables.

$kmVar = passthru('osascript -e \'tell application "Keyboard Maestro Engine" to getvariable "VarName"\'');
echo $kmVar;