PHP API: date-time field conditional (terminal syntax)

I’ve been working with PHP API using PEAR2 recently.. (but I’m newbie in mikrotik)
so I was wondering, can I write conditional sentence for date-time field?

[admin@MikroTik] > /tool user-manager user print
Flags: X - disabled, A - active, I - incomplete
0 customer=admin name="ged" actual-profile="1 time" password="ged"
shared-users=1 wireless-psk="" wireless-enc-key=""
wireless-enc-algo=none uptime-used=1m28s download-used=793673
upload-used=90934 last-seen=jan/02/1970 00:32:55

1 customer=admin name="gris" actual-profile="1 time" password="gris"
shared-users=1 wireless-psk="" wireless-enc-key=""
wireless-enc-algo=none uptime-used=12m52s download-used=5272817
upload-used=799134 last-seen=jan/02/1970 00:46:35

2 customer=admin name="flyver" actual-profile="6timer" password="flyver"
shared-users=1 wireless-psk="" wireless-enc-key=""
wireless-enc-algo=none uptime-used=7m1s download-used=1853791
upload-used=222722 last-seen=jan/02/1970 00:53:48 active-sessions=1

all I want is showing user with last-seen-date after “jan/02/1970 00:40:00”
I know I can filter it using php code, but is there any way to do that conditional query?

this one didn’t work.. returned zero result

[admin@MikroTik] > /tool user-manager user print where last-seen>"jan/02/1970 00:40:00"

anyone can help me?

thanks in advance

I don’t think you can do that, whether with API… or with a single scripting command. In both ways, you need to first get the full list, then iterate over it and discard mismatches.

The problem is RouterOS doesn’t store last-seen as time, and a simple :totime wouldn’t really work in a “where” - you need to do some string parsing, which can’t happen while RouterOS is matching the “where”/query.

IMHO, the parsing is much easier in PHP than in scripting. In PHP, you can just do

$printRequest = new Request('/tool user-manager user print');
$printRequest->setTag('p');
$client->sendAsync($printRequest, function($response) {
    if (DateTime::createFromFormat('M/d/Y H:i:s', ucfirst($response->getArgument('last-seen'))) > DateTime::createFromFormat('M/d/Y H:i:s', 'Jan/02/1970 00:40:00')) {
        //Match
    }
});
$client->loop(); 

And with scripting, it’s (at least) a little more complicated than that.

hi boen_robot.. thanks for responding to my question :slight_smile:

cool.. so send Async can be given 2nd parameter that can catch every response it gets..

but Idk what is this used for?

$printRequest->setTag('p');



DateTime::createFromFormat

also, I don’t have this class.. I think I can use php date built-in function instead
but apparently date(‘Y/m/d H:i:s’, strtotime(ucfirst($response->getArgument(‘last-seen’))) ) didn’t work well..

strtotime(‘Jan/02/1970 00:40:00’) will return ‘’ (empty string)
when it’s in correct format (Y/m/d H:i:s) like strtotime(‘1970/01/01 00:00:53’) it will return ‘53’ which means it’s 53 seconds after 1970/01/01 00:00:00..
but format (m/d/Y H:i:s) strtotime(‘01/02/1970 00:40:00’) will also work..

for looping the result it also can performed this way

	$printRequest= new Request('/tool user-manager session print');
	$printResult = $client->sendSync($printRequest);

	while ($printResult->key() !== false) {
		echo $printResult->getArgument('name');
		echo ' [last seen] '.$printResult->getArgument('last-seen');
		echo '<br><br>';
		$printResult->next();
	}

but still, I can’t filter the date.. :frowning:
I think I’ll create a function that will replace the M format into m one..

thanks again boen_robot. really appreciated it.

You do have DateTime. It’s part of the PHP core… I simply forgot to namespace it properly… sorry about that. You need "" in front of it, to indicate the root namespace, i.e.:

    if (\DateTime::createFromFormat('M/d/Y H:i:s', ucfirst($response->getArgument('last-seen'))) > \DateTime::createFromFormat('M/d/Y H:i:s', 'Jan/02/1970 00:40:00')) { 

The \DateTime::createFromFormat() method creates a DateTime object out of a string. The string itself is expected to conform to the format defined in the first argument. It’s similar in idea to strptime(), only the result is an object, not an array. Why DateTime objects? Because these can be easily compared to each other, which is exactly what the line is doing.

About the line

$printRequest->setTag('p'); 

sendAsync() doesn’t process responses until you later ask it to (using loop() or completeRequest()). This means you can send multiple requests before you start receiving responses. Responses do not arrive in any particular order - a response for the second request may arrive before any response for the first. In order for the client to know what response is for which request, a “tag” must be attached to each request, and every response for that request will also contain this tag. The tag itself can be any string you want, as long as it’s different for each request.

The reason I used sendAsync() is to also showcase another thing… using callbacks, you don’t save all responses in memory. You just have the last response being passed to the function, and after the function is over, the response is discarded. If you use sendSync() instead, all responses are in memory before you then start filtering them.

If you do use sendSync(), you don’t have to use “while” btw… you can also use “foreach”, like:

foreach ($printResult as $response) {
      echo $response->getArgument('name');
      echo ' [last seen] '.$response->getArgument('last-seen');
      echo '<br><br>';
} 

but yeah, using “while” and next() like that is acceptable too. In fact, an even better way to use it is with do…while, like:

   do {
      echo $printResult->getArgument('name');
      echo ' [last seen] '.$printResult->getArgument('last-seen');
      echo '<br><br>';
   } while ($printResult->next());