Controller action as a cron job phalcon - php

I need to run a cron job to do a sql query and save the data in the database every 24 hours.
I have a controller called GetproductsController.php and the method I have to execute is indexAction()
I've tried to do it this way:
5,10,15,20,25,30,35,40,45,50,55,59 * * * * /usr/bin/curl --silent http://localhost:8080/myproject/getproducts/index
But I donĀ“t know how to do it, If anyone knows how I can do it, I would appreciate it.
Regard!

You need to create a cli bootstrap for your project.
Default application class for web applications is \Phalcon\Mvc\Application. Instead, you should use \Phalcon\Cli\Console for cli applications.
Default DI class for web applications is \Phalcon\Di\FactoryDefault. Instead, you should use \Phalcon\Di\FactoryDefault\Cli for cli applications.
Default Dispatcher class for web applications is Phalcon\Mvc\Dispatcher. Instead you should use Phalcon\Cli\Dispatcher for cli applications.
Default Router class for web applications is Phalcon\Mvc\Router. Instead you should use Phalcon\Cli\Router for cli applications.
Please note that the classes that I've mentioned are for Phalcon 2.0. I'm not sure if they are the same for Phalcon 3.
Here is the documentation for cli applications in phalcon.
You can use the same config file with a few if statements. For example :
if (php_sapi_name() == "cli") {
$di = new Phalcon\Di\FactoryDefault\Cli();
} else {
$di = new Phalcon\Di\FactoryDefault();
}
if (php_sapi_name() === "cli") {
$di->set('dispatcher', function() {
$dispatcher = new Phalcon\CLI\Dispatcher();
$dispatcher->setDefaultNamespace('Project\\Tasks');
return $dispatcher;
});
} else {
$di->set('dispatcher', function() {
$dispatcher = new Phalcon\Mvc\Dispatcher();
$dispatcher->setDefaultNamespace('Project\\Controllers');
return $dispatcher;
});
}
You might be able to use controller classes with cli routing. But I would recommend using independent tasks.
After creating cli bootstrap file (let's call it cli.php) you can add shebang for php #!/usr/bin/env php and make that file executable. Then you can run your tasks as cli.php {taskname}

It doesn't seem like what you want to do is possible (calling a controller method from the cron). Personally, I would try to use the Phalcon CLI from their documentation: https://docs.phalconphp.com/en/latest/reference/cli.html
curl is another option. For that, first determine where curl is located on your server with:
which curl
The result of this command will be a path on the filesystem such as /usr/bin/curl. Use that result in the place of [path to curl] in the cron command below.
you would do:
59 23 * * * [path to curl] --silent https://mypage/getproducts/index &>/dev/null

Related

Injecting different implementations in console/web in Symfony 4

I have an interface UserIdProvider that has two implementations:
ConsoleUserIdProvider - it takes user id from CLI input option
RequestUserIdProvider - it comes from {userId} parameter in route
How should I configure Kernel to inject console implementation when I run CLI only, and how to use second one when it is regular request to web server?
I created separate ConsoleKernel extends Kernel for console.php where I load:
$loader->load($confDir . '/console_services.yml');
But unfortunately it overrides via cache in APP_ENV=prod mode regular Kernel where RequestUserIdProvider is supposed to be used.
Thanks in advance.
I figured it out. I should create new cli environment for that purpose.
I removed ConsoleKernel that loads custom yml file. It's not necessary.
I renamed console_services.yml to follow Symfony practice, which is supposed to be: services_cli.yml in my case. My console specific implementation is placed there.
I also changed console.php to disable debug mode in cli environment like for prod:
$notLikeProdEnv = !in_array($env, ["prod", "cli"], true);
$debug = ($_SERVER['APP_DEBUG'] ?? $notLikeProdEnv) && !$input->hasParameterOption(['--no-debug', '']);
Thanks to that when I run php console --env=cli I can see only commands specific to cli environment and also my ConsoleUserIdProvider implementation.

Artisan::call() outside the Laravel framework

I want to create a cron job for Laravel 5.2
My shared host (on OVH), only allows me to point to the full path of a file, and I am not able to use the recommended Cron entry from Laravel's docs, ie :
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
Therefore, I have to call the Artisan command from a .php file, outside of the Laravel framework.
Here is what my public/cron.php file looks like so far:
<?php
require __DIR__.'/../bootstrap/autoload.php';
use Illuminate\Support\Facades\Artisan;
Artisan::call('refresh');
refresh being my command for regenerating thumbnails inside my app.
When accessing cron.php through my browser (testing on local XAMPP), the following error occurs:
Fatal error: Uncaught RuntimeException: A facade root has not been set. in
C:\xampp\htdocs\site\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php:210
Stack trace:
#0 C:\xampp\htdocs\site\public\cron.php(7): Illuminate\Support\Facades\Facade::__callStatic('call', Array)
#1 {main} thrown in C:\xampp\htdocs\site\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php on line 210
I have also tried to boot the app, but it doesn't make any differences
$app = require_once __DIR__.'/../bootstrap/app.php';
$app->boot();
To avoid using the Artisan Facade, I tried calling the underlying Kernel Class directly:
use Illuminate\Contracts\Console\Kernel;
$kernel = new Kernel;
$kernel->call('refresh');
But this returns:
Uncaught Error: Cannot instantiate interface Illuminate\Contracts\Console\Kernel
EDIT: Here is a screenshot of OVH cron interface. The cron task is customized by OVH and only allows to point to the fullpath uri of a file - which file would execute my artisan command-. My question is, what should I put in this file, and should it be a PHP file, or a CMD?
What you want to do is run a specific Artisan command from within a script.
You can achieve this by copying artisan.php and forcing the input to what you want:
#!/usr/bin/env php
<?php
require __DIR__.'/bootstrap/autoload.php';
$app = require_once __DIR__.'/bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArrayInput(['command' => 'refresh']),
new Symfony\Component\Console\Output\ConsoleOutput
);
$kernel->terminate($input, $status);
exit($status);
If you compare this script to artisan.php, you'll see that I've just forced the input passed to $kernel->handle() method. It does not read the input from the CLI anymore, it takes these arguments, as an array. See Symfony Console Component documentation for more details.
If you need to pass arguments to your script, just set the input accordingly:
$input = new Symfony\Component\Console\Input\ArrayInput([
'command' => 'refresh',
'arg_foo' => 'foo',
'--option_bar' => 42
]);
$status = $kernel->handle(
$input,
new Symfony\Component\Console\Output\ConsoleOutput
);
Now, you can put this script where you want, it does not need to be accessible through web via a browser (it should not, by the way).
If you put it at the root of your hosting at OVH, I mean NOT in www, you just have to fill the form very simply:
If you want your script to be accessible through the web (which is not recommanded for obvious security reasons, but still), place it in your www directory, change the paths to bootstrap/autoload.php and bootstrap/app.php and give your script a name that is not easy to guess.
In the form in the OVH manager, don't forget to add www/ at the beginning of the path of the script.
There is no need to specify php script_name, since the manager handles it for you, when you choose PHP version. Just type the path of the script PHP will execute.
Just try simple:
shell_exec('php artisan refresh');
If it doesn't work, try to add appropriate paths to both php and artisan.
If you just want set a cron job. please edit crontab and use "your/app/path/php artisan cron:job" to excute your command directly.

Symfony2 - what to watch out for when running a controller on the command line Vs browser

I'm about to start writing a Symfony2 application and I've come across some notes I must have written a while back about ensuring I write Symfony2 controllers with the fact it needs to be ran from the command line too.
Rather than bash out a load of controllers and seemingly be happy they work in a web browser, I want to ensure all controllers work on the command line too.
A lot of them will need to be ran from the command line, e.g. Cron Tasks etc.
(1) My notes tell me to insert this in AppKernel.php:
* This prevents a 'You cannot create a service ("request") of an inactive scope ("request")' error
<?php
class AppKernel extends Kernel
{
protected function initializeContainer() {
parent::initializeContainer();
if (PHP_SAPI == 'cli') {
$this->getContainer()->enterScope('request');
$this->getContainer()->set('request', new \Symfony\Component\HttpFoundation\Request(), 'request');
}
}
}
?>
(2) I've also got a pre-written request listener that runs various code on every request, and I'm aware the variables generated won't be used on the command line.
(3) I know that none of my Apache config will run (as it's not running inside Apache), and I also know that there's two php.ini files (CLI and Apache).
What else do I need to consider?
What else isn't available on the command line compared to a browser?
I would consider Console Component.
Symfony 2 has a build in interface for creating CLI based commands that will have the entire application bootstrapped, it's called Console Component.
Build out your cronjobs and tasks using this and you can use dependency injection to ensure you have all of the services you need.
I'm sure with some research you could figure out how to load a controller if necessary--controller forwarding or virtual?

Phalcon and cli applications

Is it possible to use phalcon in cli applications to handle requests with argv parameters?
I want to use argv parameters to understand command that should be executed, e.g.
./script.php robot/create --color=red --feature=weapon
and to get this inside my application with controllers, actions, etc in this way:
controller: robot
action: create
GET params: color=red,feature=weapon
Is it possible using CLI classes like
Phalcon\ClI\Dispatcher
http://docs.phalconphp.com/en/latest/api/Phalcon_CLI_Dispatcher.html
Phalcon\CLI\Console http://docs.phalconphp.com/en/latest/api/Phalcon_CLI_Console.html
Phalcon\CLI\Task http://docs.phalconphp.com/en/latest/api/Phalcon_CLI_Task.html
and other similar?
There are no docs and how-to manuals... Perhaps somebody has experience or just an idea.
I understand that we have to define DI and initialize application, but how to make this in a more native way I just don't have any ideas.
Also, one more question: can phalcon handle argv parameters automatically?
As I understand, we should start Phalcon\CLI\Console object as application and pass to it DI. But the whole process/scenario... I just can't get it :)
So, i have following folders structure:
~/www
~/www/app
~/www/app/models
~/www/app/controllers - controllers for web
~/www/app/tasks - task for cli
~/www/public/app.php - web application
~/www/cli/app.php - console application
In cli/app.php i have following code:
#!/usr/bin/php
<?php
/**
* This makes our life easier when dealing with paths.
* Everything is relative to the application root now.
*/
chdir(dirname(__DIR__));
/**
* Init loader
*/
$loader = new \Phalcon\Loader();
$loader->registerDirs(['app/tasks/'])
->register();
/**
* Setup dependency injection
*/
$di = new Phalcon\DI();
// Router
$di->setShared('router', function() {
return new Phalcon\CLI\Router();
});
// Dispatcher
$di->setShared('dispatcher', function() {
return new Phalcon\CLI\Dispatcher();
});
/**
* Run application
*/
$app = new Phalcon\CLI\Console();
$app->setDI($di);
$app->handle($argv);
then i put my tasks classes in app/tasks folder.. and it just works.
perhaps this will help somebody ;)
I'm a Phalcon enthusiast, but actually tasks seem to me something to create cron jobs. They are something different from commands. I don't think tasks are the right way to create a complete cli application. There are many limitation. I really suggest you to use Symfony Console instead: it's well documented, it manages multi arguments and params, it provides automatically a command line help and you can install it via Composer.
If you are creating cron jobs you can go with Phalcon tasks, but if your intention is to create a cli application, take a look at Symfony Console.
can phalcon handle argv parameters automatically?
yes, PHP will pass command line parameters to $argv in any framework.

Cakephp 2.0, CPanel and Shell scripts

I have cPanel on a shared server and I need to run a shell script everyday.
This script has to call a controller function that scraps a webpage everyday.
My problem is that I don't know how to do a shell script that calls this function and add it at cron jobs in cpanel. How do I do all of this?
Thanks in advance!
I'm going to extend my question.
I have this code "TestTask.php":
class TestTask extends Shell {
function main() {
$this->out('Hello world.');
}
function execute() {
$this->out('Hello world 2.');
}
}
It's located in: /home/myuser/public_html/app/Console/Command/Task
And then, my cronjob is like this:
* * * * * php /home/myuser/public_html/app/Console/cake.php test -app /home/myuser/public_html/app >> /home/myuser/public_html/file.log
The last part it's to log the output in a file.
It doesn't work at all.
Help please!!!
Here's the command for a cron job I am using on my server:
/home/path-to-cake/lib/Cake/Console/cake -app /home/path-to-cake/app time
where time is my shell, located in /app/Console/Command/TimeShell.php. This is how you run shells.
Now, on the other part of your question, a task must be called from within a shell. From the code you posted, it seems that you are confusing a bit shells with tasks. A shell can contain tasks, just like controllers can have components. main(); is required for a shell when it is called without any arguments. It is not necessary for a task to implement it. On the other hand, a task must implement an execute(); method.
In order to run a task from your shell, be sure to add public $tasks = array('Test'); in the TestShell class; You can use this task in your shell just like you use a component in a controller: $this->Test->whatever();
For more info on CakePHP 2.0 shells and tasks, have a look here
Hope this helped!

Categories