Pick/MultiValue has always been a capable data platform, but its built-in facilities for modern network interaction and file-format work are thin. Whether your client is running UniVerse, UniData, D3, mvBASE, or jBASE — all now part of the Rocket Software portfolio — the problem is the same: when they need to consume a REST API, expose an endpoint, query a SQL database, parse a messy CSV, or generate a PDF invoice, you need help. For years, I've reached for PHP.
Not PHP as a web application. PHP as a command-line tool. /usr/bin/php on a Linux box is essentially a Swiss Army knife with a massive standard library: HTTP via cURL, JSON and XML parsing, PDO for every major database, FTP and SFTP, zip archives, image manipulation, you name it. And it's already installed on almost every system your Pick application runs near.
Calling PHP from Pick
The pattern is straightforward. From a Pick BASIC program, shell out and capture the result:
EXECUTE "SH -c '/usr/bin/php /path/to/helper.php arg1 arg2'" CAPTURING RESULT
The PHP script runs, prints to stdout, and Pick captures the output. Command-line arguments handle simple inputs. For larger payloads — or for longer results — I write the data to a file from Pick, have PHP read it with file_get_contents, process it, and write the result to another file that Pick reads back. Two files, zero protocol complexity, works every time.
No daemons to manage, no long-running processes, no sockets to worry about. Fire, return, done.
HTTP: consuming APIs
A common case is pulling pricing data, shipment tracking, or reference information from a vendor's REST API and pushing it into a Pick file. A short PHP script does the heavy lifting:
<?php
$ch = curl_init('https://api.example.com/prices?sku=' . $argv[1]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . getenv('API_KEY')
]);
echo curl_exec($ch);
curl_close($ch);
Pick calls it, gets back JSON, parses the fields it cares about, writes them to a file. The same pattern handles page scraping when a partner refuses to expose a proper API — DOMDocument or a regex, paired with cURL, and you're done.
HTTP: exposing endpoints
Going the other direction is just as useful. When a modern application needs to query your Pick system — a mobile app, a customer portal, a webhook receiver — you can stand up a PHP endpoint that shells out to Pick.
A single PHP file sitting in your web root can accept a POST request, invoke a Pick subroutine via the shell, wait for the output, and return JSON:
<?php
header('Content-Type: application/json');
$input = json_decode(file_get_contents('php://input'), true);
file_put_contents('/tmp/request.json', json_encode($input));
$result = shell_exec("/path/to/pick/runme GETORDER");
echo $result;
Your Pick program becomes an API backend without running a separate HTTP server, without rewriting business logic in another language, and without losing decades of code that already works.
Reading and writing SQL databases
Pick has its own data model — dictionaries, multivalued attributes, correlatives — and it's brilliant for what it was built for. But the world runs on SQL, and when you need to read from or write to a MySQL, PostgreSQL, or SQL Server instance, PHP's PDO makes it a ten-line job:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=reporting',
'user',
getenv('DB_PASS')
);
$stmt = $pdo->prepare(
"INSERT INTO daily_summary (date, revenue, orders)
VALUES (?, ?, ?)"
);
$stmt->execute([$argv[1], $argv[2], $argv[3]]);
Pick calls it with the values as command-line arguments, and the insert happens. The reverse direction — pulling from SQL into Pick — is just as straightforward: SELECT, fetchAll(), dump as JSON to stdout or a file, parse in Pick. PDO covers PostgreSQL, SQL Server, Oracle, SQLite, and more with the same API.
Data parsing and transformation
A lot of what Pick doesn't do easily, PHP does trivially. Parsing a messy CSV, converting between character encodings, decoding base64, extracting fields from XML, applying regular expressions that go beyond what Pick's MATCHES operator handles — all one-liners in PHP.
Typical jobs I've used PHP for:
- Converting a Windows-1252 file to UTF-8 before loading into Pick
- Parsing a 50-column supplier CSV where vendors embedded commas and quotes inconsistently (
fgetcsvhandles the edge cases) - Running a regex over free-text notes to extract phone numbers, dates, or order references
- Flattening nested JSON from an API into a flat record that maps cleanly to a Pick item
Pick stays the system of record. PHP is the data laundromat in front of it.
Building files Pick can't: PDFs, spreadsheets, and archives
Sometimes you need to produce something that simply isn't native to Pick: a properly formatted PDF invoice, an Excel workbook with multiple sheets and formulas, a zipped bundle of nightly export files. PHP has mature libraries for all of it.
- PDFs. Render HTML to PDF with
wkhtmltopdf(a single command-line call) or use a library like Dompdf. For invoices and reports, HTML-to-PDF is my default: you build the markup, apply CSS, and get a pixel-accurate PDF without hand-placing elements. - Excel. PhpSpreadsheet handles multi-sheet workbooks, formulas, formatting, and charts. Your Pick program prepares the data, writes it to a file, and calls a PHP script that reads it and outputs a native
.xlsx. - Zip archives. The built-in
ZipArchiveclass turns a directory of files into a single archive in a few lines — useful for packaging nightly exports before FTPing them out.
None of these require a web server, a GUI, or any long-running process. Just PHP, a command line, and the file paths you want to read and write.
A few gotchas
Permissions — but not the ones you'd expect. When PHP is called from Pick this way, it runs as the Pick user, not as apache or www-data. That's usually what you want, but the Pick user often has surprisingly narrow permissions on temp directories and output paths — anywhere your PHP script wants to write intermediate files or read inputs. Sort that out once and you won't hit it again.
Timeouts. Every outbound call needs one. cURL requests, PDO connections, shell commands, remote file fetches — if the resource is slow or unavailable, your PHP script will hang, which means your Pick program hangs right along with it. Cap everything: CURLOPT_TIMEOUT on cURL, PDO::ATTR_TIMEOUT on database connections, explicit timeouts on any stream_context you build. Thirty seconds is usually plenty; anything longer and you probably want the whole operation to be async anyway.
Why it matters
The real value of this pattern isn't the code. It's the strategy: you extend Pick without replacing it, integrate with modern systems without a rewrite, and deliver incremental value instead of a multi-year migration. That's most of what clients actually want.