Symfony\Process package in Laravel (for python files) - php

I am trying to run python files in Laravel Project.Therefore, i use the Symfony\Process package.My code looks like this:
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
$process = new Process(["python","C:\xampp\htdocs\backend\Scrape\AnnouncementsScrape.py"]);
$process->run();
When i use this line:
throw new ProcessFailedException($process);
my laravel project returns error (I use laravel framework for my backend in my mobile app, so i can not see the exactly error; i can only see that there is problem with my backend)
Το sum up, i run the code above, but the Process is not successfull.
I check it with the condition:
if ($process->isSuccessful())
Anyone any idea?

Although the process may not be successful, it still produces an output, which you can access.
You can use $process->getOutput() and $process->getErrorOutput() for that

Related

How to run Symfony Process function inside queue jobs on laravel

Now i'm doing some project use laravel framework. do i able to run Symfony Process function inside a queue jobs?
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
right now i want to run some commend using Symfony Process function for this
process = new Process("facebook-scraper --filename public/data/nintendo.csv --pages 5 nintendo");
if outside the queue. this code can run succesful. but when i want to make it run inside the queue jobs. it can't.
how do i able to run symfony Process function inside queue on jobs laravel.
I think the problem is the paths. Replace the --filename option value with the absolute path (from /):
$path = public_path('data/nintendo.csv');
$process = new Process("facebook-scraper --filename {$path} --pages 5 nintendo");
...
...
And try to use full path to executable (facebook-scraper).
You can use which to find it.
Example:
$ which facebook-scraper
/usr/bin/facebook-scraper

Running AMPL code from PHP (Laravel Process)

I'm trying to run an ampl .run (or any ampl code) file from Laravel using Symfony Process. My code is as below:
$commandArray = array('./ampl');
$process = new Process($commandArray);
$process->setWorkingDirectory('/usr/local/bin/amplitude/amplide.linux64');
$process->run();
if (!$process->isSuccessful())
{
throw new ProcessFailedException($process);
}
dd($process->getOutput());
But I cannot start ampl. I get an error like:
""" The command "'./ampl'" failed.\n \n Exit Code: 2(Misuse of shell
builtins)\n \n Working directory:
/usr/local/bin/amplitude/amplide.linux64\n \n Output:\n
================\n \n \n Error Output:\n
================\n """
I suspected this was a permissions error in the directory but when I use:
$commandArray = array('ls');
it works and outputs the list of files and folders. I understand that ampl is basically a terminal program, so how do I access and write commands to it?
If someone can explain how to access terminal programs from Process, I think it would be very helpful. Thank you in advance.
I figured out the issue here was that just calling the ampl console by typing ./ampl does not trigger any response. As it cannot be interpreted as a actual command, Laravel gives an error. The trick is to pass an actual command to the process object and to always give the full path to any .run/.mod/ .dat file you are reffering. For example:
$commandArray = array('./ampl path/to/example.run;');
or
$command = './ampl path/to/example.run';
works fine and will give the response.
Another important thing I noticed was that, since AMPL is basically another program running in the terminal, we cannot pass different commands seperately to the process using arrays like the following:
$commandArray = array('./ampl model.mod;','./ampl data.dat;', './ampl solve;');
This will not work. Neither will this:
$commandArray = array('./ampl, model.mod; data.dat; solve;');
Ideally it is best to have everything in a .run file and then execute it.
If you need to pass parameters to the .dat file from Laravel, passing this into the commands using string concatnation causes issues, although I do not exactly know why. I would suggest to use the Storage class in Laravel to update the .dat file first and then run the ampl problem using a .run file.

Run .sh file using exec Laravel PHP

I am trying to run a .sh file that will import a excel file to my database. Both files are in same directory inside the public folder. For some reason the exec command isn't being executed or neither any error occurs.
.sh file colde:
IFS=,
while read column1
do
echo "SQL COMMAND GOES HERE"
done < file.csv | mysql --user='myusername' --password='mypassword' -D databasename;
echo "finish"
In my php file i have tried following:
$content = file_get_contents('folder_name/file_name.sh');
echo exec($content);
And:
shell_exec('sh /folder_name/file_name.sh');
Note: I can directly execute the sh file from gitbash however I want it to be done using function in Laravel controller. I'm using windows OS.
you can use Process Component of Symfony that is already in Laravel http://symfony.com/doc/current/components/process.html
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
$process = new Process('sh /folder_name/file_name.sh');
$process->run();
// executes after the command finishes
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
echo $process->getOutput();
All of these answers are outdated now, instead use (Symfony 4.2 or higher):
$process = Process::fromShellCommandline('/deploy.sh');
Or
$process = new Process(['/deploy.sh']);
https://symfony.com/doc/current/components/process.html
I know this is a little late but I can't add a comment (due to being a new member) but to fix the issue in Windows " 'sh' is not recognized as an internal or external command, operable program or batch file." I had to change the new process from:
$process = new Process('sh /folder_name/file_name.sh');
to use the following syntax:
$process = new Process('/folder_name/file_name.sh');
The only problem with is that when uploading to a Linux server it will need to be changed to call sh.
Hope this helps anyone who hit this issue when following the accepted answer in Windows.
In Symfony 5.2.0 that used by Laravel 8.x (same as current Symfony Version 6.0 used by Laravel 9.x), you need to specify the sh command and your argument, in your case:
use Symfony\Component\Process\Process;
$process = new Process(['/usr/bin/sh', 'folder_name/file_name.sh']);
$process->run();
The system will find folder_name/file_name.sh from your /public folder (if it executed from a url), if you want to use another working directory, specify that in the second Process parameter.
$process = new Process(['/usr/bin/sh', 'folder_name/file_name.sh'], '/var/www/app');
And the /usr/bin/sh sometimes have a different place for each user, but that is a default one. Type whereis sh to find it out.

Call python gearman worker using laravel 5

I am using laravel 5. What I need is to call python gearman worker.
I have created a gearman worker in python.
And I have created a gearman client in laravel 5.
I have directly added gearman client code in my controller like:
$client = new GearmanClient();
$client->addServer();
$job_data = array("func_name" => "searchTweets", "query" => "query_to_search");
$result = $client->doNormal("php_twitter_worker", json_decode($job_data));
if ($result) {
print_r($result);
}
But it throws error :
Class 'App\Http\Controllers\GearmanClient' not found
I know what is the error because I don't have GearmanClient Class in Controllers. Actually I don't know how to use it.
After doing some R&D , I found a package using gearman in laravel5 but not getting how to use it as Gearman Client and how it make a call to my python gearman worker.
Any help on this ?
Because your class is namespaced, your controller there, PHP will look for a class inside of this namespace.
Therefore, to use a class from the root namespace, you should either use a use statement or prefix the classname with \, \ being the root namespace.
use GearmanClient;
$client = new \GearmanClient();
Use one or the other, not both, my code above is actually quite confusing...

Laravel setup, trying to have cronjob call a function within php laravel file

Original Post
Good evening folks. I have a laravel setup and I'm trying to have a cronjob execute a php function to a file within the laravel project directory.
I am getting class and name space errors when I try to do something like this:
<?php
require_once('../laravel/app/Http/Controllers/NotificationsController.php');
and then calling the processQueuedNotifications() function.
This of course gives me errors, what is the correct way to call my function within the laravel directory? I need to call this function as this function has all the correct namespaces and extended controllers necessary to execute the function properly.
Update 1:
Thanks to #michael, I've been made aware of a component in Laravel called commands.
So I ran this code:
php artisan make:console processQueuedNotifications
and it created some files in the console directory.
Currently exploring on what to do next.
After checking out the Events class which the kernel.php file makes use of, I noticed that this class provides an easy to use interface for me to create cron jobs on the fly. Am I correct in think so?
I notice there is not function to run a cron job every minute, is it safe to edit the Events class file without it being overwritten by future make:console commands, or laravel updates?
I saw this code in the kernel.php file:
$schedule->command('inspire')
->hourly();
So is this the place you wanted me to add my function? as I notice that the inspire function is something automatically created for me to understand what's going on?
So I would write,
$schedule->command('processQueuedNotifications')
->everyMinute();
//Providing it's safe to edit the Event's class or figure out a clean way of doing so without my code being deleted in the future on Laravel updates.
A very convenient way is to use laravels console component. You can create a new command by issuing
php artisan make:console
And find it thereafter in your app/console directory. Make sure to enable the command in the Kernel.php file once created.
Simply call your class or whatever you want to run via cron from inside the command. The console command itself is callable via cli just as you would run one of laravels php artisan ... commands. You can set this in the file created for you. For example, you can then call the file from everywhere you want with
/usr/bin/php /path/to/file/artisan my:command
You can set options and arguments if you need to.
Here's the documentation: http://laravel.com/docs/5.0/commands / http://symfony.com/doc/current/components/console/introduction.html
There's an array in kernel.php you need to register your class (include the namespace) in. After that it is callable via cli. For a start, have a look on arguments and options you can initialize in case you need to make different requests on your controller class. (The filename you have chosen for your console command, is an argument. You can make them required or optional for your own commands. )
Within your file, you can create them by simply creating an array in the appropriate method with these values:
[$name, $mode, $description, $defaultValue]
have a look at the docs or Jeffrey's laracasts, they are very good.
To only call your class from the console command, it's enough to name your command in the above section of the file and call you controller like
(new namespace\controller)->method();
What you can do in your code, after your update, 2 choices :
Dispatching directly the command from your code using the Bus facade
first import it using the
use Illuminate\Support\Facades\Bus;
then in your code
Bus::dispatchNow(new YourCommandClass);
(don't forget to import your command class)
Dispatch it for queue process using the same bus facade:
(still importing the same way)
Bus::dispatch(new YourCommandClass);
(Note that in that case, you'll need to have the following command run by your cron job :
php artisan queue:listen
it can handle several options such as the --tries=X where is is the number of tries etc
Generally speaking, you can get more info from commands typing php artisan my:command -h

Categories