├── .gitignore ├── README.md ├── composer.json ├── composer.lock ├── composer.phar ├── index.php ├── output ├── PointNo0 ├── PointNo1 └── PointNo2 └── src └── Example └── Command ├── MainCommand.php └── SubProcessCommand.php /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea 3 | vendor -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-subprocess-example 2 | An example for using Symfony Process Component and async php execution. 3 | 4 | 1. `git clone https://github.com/iCubeDm/php-subprocess-example` 5 | 2. `php composer.phar update` 6 | 3. `php index.php example:main 4` - where `4` is amount of subprocesses (could be different, 2 by default) 7 | 8 | If you like it - star it. 9 | 10 | P.S. Big thanks to [@alinn](https://github.com/alinn) for help! 11 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "description" : "An example for using Symfony Process Component and async php execution.", 3 | "authors" : [ 4 | { 5 | "name" : "Dmitry Yakubovsky", 6 | "email": "icubedm@gmail.com" 7 | } 8 | ], 9 | "autoload": { 10 | "psr-0": { "": "src/" } 11 | }, 12 | "require": { 13 | "symfony/console": "^3.0@dev", 14 | "symfony/process": "^3.0@dev" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "4e91793f92c3e10359a33a181c4e3c27", 8 | "packages": [ 9 | { 10 | "name": "symfony/console", 11 | "version": "dev-master", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/symfony/Console.git", 15 | "reference": "514e8f1598d78a9ac7f25292f2627d7e8c83785c" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/symfony/Console/zipball/514e8f1598d78a9ac7f25292f2627d7e8c83785c", 20 | "reference": "514e8f1598d78a9ac7f25292f2627d7e8c83785c", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.5.9" 25 | }, 26 | "require-dev": { 27 | "psr/log": "~1.0", 28 | "symfony/event-dispatcher": "~2.8|~3.0", 29 | "symfony/phpunit-bridge": "~2.8|~3.0", 30 | "symfony/process": "~2.8|~3.0" 31 | }, 32 | "suggest": { 33 | "psr/log": "For using the console logger", 34 | "symfony/event-dispatcher": "", 35 | "symfony/process": "" 36 | }, 37 | "type": "library", 38 | "extra": { 39 | "branch-alias": { 40 | "dev-master": "3.0-dev" 41 | } 42 | }, 43 | "autoload": { 44 | "psr-4": { 45 | "Symfony\\Component\\Console\\": "" 46 | } 47 | }, 48 | "notification-url": "https://packagist.org/downloads/", 49 | "license": [ 50 | "MIT" 51 | ], 52 | "authors": [ 53 | { 54 | "name": "Fabien Potencier", 55 | "email": "fabien@symfony.com" 56 | }, 57 | { 58 | "name": "Symfony Community", 59 | "homepage": "https://symfony.com/contributors" 60 | } 61 | ], 62 | "description": "Symfony Console Component", 63 | "homepage": "https://symfony.com", 64 | "time": "2015-09-09 18:22:56" 65 | }, 66 | { 67 | "name": "symfony/process", 68 | "version": "dev-master", 69 | "source": { 70 | "type": "git", 71 | "url": "https://github.com/symfony/Process.git", 72 | "reference": "0f0810b2e1cbcfd54b13bdd1869e2cdefdf025ab" 73 | }, 74 | "dist": { 75 | "type": "zip", 76 | "url": "https://api.github.com/repos/symfony/Process/zipball/0f0810b2e1cbcfd54b13bdd1869e2cdefdf025ab", 77 | "reference": "0f0810b2e1cbcfd54b13bdd1869e2cdefdf025ab", 78 | "shasum": "" 79 | }, 80 | "require": { 81 | "php": ">=5.5.9" 82 | }, 83 | "require-dev": { 84 | "symfony/phpunit-bridge": "~2.8|~3.0" 85 | }, 86 | "type": "library", 87 | "extra": { 88 | "branch-alias": { 89 | "dev-master": "3.0-dev" 90 | } 91 | }, 92 | "autoload": { 93 | "psr-4": { 94 | "Symfony\\Component\\Process\\": "" 95 | } 96 | }, 97 | "notification-url": "https://packagist.org/downloads/", 98 | "license": [ 99 | "MIT" 100 | ], 101 | "authors": [ 102 | { 103 | "name": "Fabien Potencier", 104 | "email": "fabien@symfony.com" 105 | }, 106 | { 107 | "name": "Symfony Community", 108 | "homepage": "https://symfony.com/contributors" 109 | } 110 | ], 111 | "description": "Symfony Process Component", 112 | "homepage": "https://symfony.com", 113 | "time": "2015-08-27 07:55:57" 114 | } 115 | ], 116 | "packages-dev": [], 117 | "aliases": [], 118 | "minimum-stability": "dev", 119 | "stability-flags": { 120 | "symfony/console": 20, 121 | "symfony/process": 20 122 | }, 123 | "prefer-stable": false, 124 | "prefer-lowest": false, 125 | "platform": [], 126 | "platform-dev": [] 127 | } 128 | -------------------------------------------------------------------------------- /composer.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iCubeDm/php-subprocess-example/dc4c6b876105eea98bf799a4fd7513a186fe8914/composer.phar -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | add(new \Example\Command\MainCommand()); 8 | $application->add(new \Example\Command\SubProcessCommand()); 9 | $application->run(); -------------------------------------------------------------------------------- /output/PointNo0: -------------------------------------------------------------------------------- 1 | Point No0: 4 -------------------------------------------------------------------------------- /output/PointNo1: -------------------------------------------------------------------------------- 1 | Point No1: 2 -------------------------------------------------------------------------------- /output/PointNo2: -------------------------------------------------------------------------------- 1 | Point No2: 6 -------------------------------------------------------------------------------- /src/Example/Command/MainCommand.php: -------------------------------------------------------------------------------- 1 | setName('example:main') 15 | ->setDescription('Run example command with optional number of CPUs') 16 | ->addArgument('CPUs', null, 'number of working CPUs', 2); 17 | } 18 | 19 | protected function execute(InputInterface $input, OutputInterface $output) 20 | { 21 | $channels = []; 22 | $maxChannels = $input->getArgument('CPUs'); 23 | 24 | $exampleArray = $this->getExampleArray(); 25 | $output->writeln('Start example process'); 26 | while (count($exampleArray) > 0 || count($channels) > 0) { 27 | foreach ($channels as $key => $channel) { 28 | if ($channel instanceof Process && $channel->isTerminated()) { 29 | unset($channels[$key]); 30 | } 31 | } 32 | if (count($channels) >= $maxChannels) { 33 | continue; 34 | } 35 | 36 | if (!$item = array_pop($exampleArray)) { 37 | continue; 38 | } 39 | $process = new Process(sprintf('php index.php example:sub-process %s', $item), __DIR__ . '/../../../'); 40 | $process->start(); 41 | if (!$process->isStarted()) { 42 | throw new \Exception($process->getErrorOutput()); 43 | } 44 | $channels[] = $process; 45 | } 46 | $output->writeln('Done.'); 47 | } 48 | 49 | /** 50 | * @return array 51 | */ 52 | private function getExampleArray() 53 | { 54 | $array = []; 55 | for ($i = 0; $i < 30; $i++) { 56 | $name = 'No' . $i; 57 | $x1 = rand(1, 10); 58 | $y1 = rand(1, 10); 59 | $x2 = rand(1, 10); 60 | $y2 = rand(1, 10); 61 | 62 | $array[] = $name . '.' . $x1 . '.' . $y1 . '.' . $x2 . '.' . $y2; 63 | } 64 | 65 | return $array; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Example/Command/SubProcessCommand.php: -------------------------------------------------------------------------------- 1 | setName('example:sub-process') 14 | ->setDescription('Run example sub-process command') 15 | ->addArgument('item'); 16 | } 17 | 18 | protected function execute(InputInterface $input, OutputInterface $output) 19 | { 20 | $items = explode('.', $input->getArgument('item')); 21 | $pointName = $items[0]; 22 | $x1 = $items[1]; 23 | $y1 = $items[2]; 24 | $x2 = $items[3]; 25 | $y2 = $items[4]; 26 | 27 | // Used for mocking heavy execution. 28 | $sum = 0; 29 | for ($i = 1; $i <= 30000000; $i++){ 30 | $sum += $i; 31 | } 32 | 33 | $distance = bcsqrt(pow(($x2 - $x1),2) + pow(($y2 - $y1),2)); 34 | $data = sprintf('Point %s: %s', $pointName, (string)$distance); 35 | 36 | file_put_contents(__DIR__.'/../../../output/Point'.$pointName , print_r($data, 1), FILE_APPEND); 37 | } 38 | } 39 | --------------------------------------------------------------------------------