John Davidson

passthru - How to properly "passthrough" a CLI program to a PHP script *while executing your own function*? (My old method has broken.)

0 comments
Message:


Up until a few days ago, I had this working. It had been working for a long time. I'm not sure if it was because of upgrading PHP 8.0.12 to 8.0.13, or because yt-dlp updated and has changed something since. I have not changed my code.


This works:


passthru($yt_dlp_command);

However, it doesn't let me run my own function while it's executing, which is the whole point.


This does no longer work, but worked up until recently:


ob_start();
$a = popen($yt_dlp_command, 'r');

if ($a)
{
$response = fgets($a, 10); // I've tried numerous other values than 10 as well.

if ($response)
{
while ($row_data = $response)
{
ob_flush();
flush();
my_function();
echo $row_data;
}
}

pclose($a);
}

ob_end_clean();

No matter what options I try for yt-dlp, such as --no-progress or --newline (or combinations of these, or none), it just won't show anything but the first line, or the beginning of the first line repeated endlessly in a broken manner.


If I run the $yt_dlp_command in a cmd.exe, it works perfectly with full animated output and all that.


I'm completely stuck now. No idea what else to try. It's probably yt-dlp that has changed something in how it outputs stuff, but even if that's the case, it's weird to me how certain programs can just break this code. It should work regardless of what specific program is being run.



My Answer:
One possible solution to properly "passthrough" a CLI program to a PHP script while executing your own function is to use the `proc_open` function instead of `popen`. Here's an example of how you can modify your code:

php
$descriptorspec = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'] // stderr
];

$process = proc_open($yt_dlp_command, $descriptorspec, $pipes);

if (is_resource($process)) {
stream_set_blocking($pipes[1], 0); // Set stdout to non-blocking mode

while (!feof($pipes[1])) {
$output = fgets($pipes[1]);

if ($output !== false) {
my_function();
echo $output;
ob_flush();
flush();
}
}

fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);

proc_close($process);
}


This code snippet uses `proc_open` to create a process and provides pipes for stdin, stdout, and stderr. It then reads the output from the stdout pipe in a non-blocking manner and executes your custom function while outputting the data.

You may need to adjust the code further based on the specific requirements of your script and the behavior of the CLI program you are interacting with.

Rate this post

4 of 5 based on 9161 votes

Comments




© 2024 Hayatsk.info - Personal Blogs Platform. All Rights Reserved.
Create blog  |  Privacy Policy  |  Terms & Conditions  |  Contact Us