I'm using CodeIgniter for my project. I have this roadblock in from of me..
There's this method in my controller that I want to call every hour. Let's have that as:
class Notifs extends CI_Controller {
public function __construct() {
parent:: __construct();
// load stuff here
}
public function index() {
}
/* I want to call this function on an hourly basis */
public function check_overdue_stuffs() {
// do the checking here
}
}
I have absolutely no idea on how to implement this. I have tried using sleep($seconds) but that was just a mess.
Any ideas for a perfectly awesome way to do this? A verbose example would be great. Thanks!
This is pretty straight forward, but don't look to just keeping it in your PHP code. You need to use a cronjob script (linux) or windows equivalent (on the server where your software lives).
Here is a simple cron you would add to pull a specific cli method:
# hourly cron
0 * * * * php /www/ciWebsite/index.php [controller] [method] >/dev/null 2>&1
That way, it runs the controller + method you want and output is dumped into /dev/null
Try running /www/ciWebsite/index.php notifs check_overdue_stuff and see if it works (obviously update your path)
edit:
fixed an extra entry (I had cli = folder + controller + method)
Related
I have added one function in timeman mosule as follows.
class CTimeManReport extends CAllTimeManReport
{
function testAgent()
{
mail('t#demo.co.in','agent','agent');
return "testAgent();";
}
}
Now I want to run this function every 60 sec.I have added agent though control panel in agent section,but its running only once.
After running the agent bitrix added to database value that agent function returns. So in your case, it must be return "CTimeManReport::testAgent();" because your function is a class method.
Also, it must be a class method, not an instance method, so add public static before your function
So, try to do something like that:
class CTimeManReport extends CAllTimeManReport
{
public static function testAgent()
{
mail('t#demo.co.in','agent','agent');
return "CTimeManReport::testAgent();";
}
}
If this advice doesn't help, you can add cron support for your agents, because by default they work on pages reloads. Follow this link for instructions
P.S. don't add your own code into the bitrix module's code. Because you may lose your code after bitrix updates. Add your own code or include your classes into the local/php_interface/init.php
I am not sure if this is doable or not. I am running cron job to process data and they are all independent of each other.
For example i have a data [x,y,z] and i have a method in the parent controller that does what it needs to do. Process takes little long and hence my queue is piling up since it is doing one at a time. I tried forking process but it loses connection to the mongo database. Therefore, I had to remove fork for now but please let me know if i can reconnect.
Pseudocode
MyTools.php
class MY_Tools extends CI_Controller {
...
public function process($item) {
Make curl request
Update database for the item
}
}
Tools.php
class Tools extends MY_Tools {
...
public function getAllDate() {
$data = fetchDataFromDB() => [X,Y,Z]
$i = 0
while ($i < sizeof($data) {
$this->process($data[$i]);
$i++;
}
}
}
if i can do this without waiting for another process to complete and just keep on going, that will be great
In addition, I am using php7
cimongo library for codeigniter and https://github.com/alcaeus/mongo-php-adapter
Possible Solution
For php7, i have used this for gearman installation
https://techearl.com/php/installing-gearman-module-for-php7-on-ubuntu
Codeigniter gearman library that I used : https://github.com/appleboy/CodeIgniter-Gearman-Library
To overcome static method accessing parent controller, use singleton method
I was struggling with this for a bit and hopefully it will help someone
Example
class MY_Tools extends CI_Controller {
private static $instance;
function __construct() {
parent::__construct();
self::$instance =& $this;
}
public static function get_instance()
{
return self::$instance;
}
}
To Access
MY_Tools::get_instance()->YOUR_PUBLIC_METHODS();
Hope this can help someone
I want to use php threads for asynchronously loading a function that executes a mysql stored procedure. The stored procedure takes a lot of time to load, so keeping it asynchronous is the only optimal solution, I found.
I have no idea on how to bring the threading inside Laravel. Laravel has queues but I want to do it directly in script with thread.
What i've done to approach a similar issue (I've done it in a sync command) is to create a class that extends from Thread and call it from the laravel code.
The class in your case might be something like this:
class LaravelWorker extends Thread
{
private $object;
public function __construct($object)
{
$this->object = $object;
}
public function run()
{
$object->runProcedure();
}
}
And you can call it at your code such as this:
$object = new ObjectWithProcedure();
$threadedMethod = new LaravelWorker($object);
$threadedMethod->start();
If, for some reason, you need to wait until the $threadedMethod finishes, you can do
$threadedMethod->join();
(more_code...)
And the more_code section will only execute once $threadedMethod has ended.
Hope it helps!
Hi I want to execute a function via cronjob to start an csv import. At the moment the import is triggered by accessing a controller in the browser tld.de/Update
The controller has this code http://pastie.org/8351266
How can I execute the function init() via Cronjob?
Thx!
In SilverStripe you can access any route that is accessible via HTTP also by running cli-script.php in the command line
There also is sake which is just a bash wrapper around cli-script.php (but sake needs to be installed)
so, from your project directory, you can run both commands which will perform the same action (in this case, run a dev/build):
php framework/cli-script.php dev/build
sake dev/build
see the docs for commandline ussage of silverstripe: http://doc.silverstripe.org/framework/en/topics/commandline
the 2nd part of your question (how to call a method from a controller) is actually more a question of routing in silverstripe and has nothing to do with how it is called (cronjob)
I assume that your controller is a Page_Controller or a subclass of that (so bound to a SiteTree Model), then routing is done for you (it takes the URLs you set in the CMS).
so lets see some example code and lets assume you have a page with the URLSegment about:
class Page_Controller extends ContentController {
private static $allowed_actions = array('something');
public function init() {
// the init method will run before every action
// this means this code will run, no matter if you visit /about or /about/something
}
public function index() {
// this is the default action (this code is optional and can be removed),
// and will be called if you visit website.com/about
return $this;
}
public function something() {
// this is the somethingaction,
// and will be called if you visit website.com/about/something
// do something here
return $this;
}
}
you can then call run to get the result of the index():
php framework/cli-script.php about
and this to get the result of something():
php framework/cli-script.php about/something
NOTE: the init method itself is not accessable via URL, it is the "setup" that runs before an action
NOTE: all actions other than index() have to be allowed by adding them to $allowed_actions (also note that you need to ?flush=1 after adding to $allowed_actions to reload the config cache)
EDIT: this was actually the response to your first question, after seeing your code example, this addition:
for standalone controllers it works the same way, just that you have to define the routes, and make sure that you have $Action in the route so that something() can be called
You could do this without Silverstripe sake. Install curl and call the URL via a cronjob, ie:
0 0 * * * curl --silent http://tld.de/Update
The proper way to do this would be to write a Silverstripe task, and invoke your controller from within the task. I haven't tested this code but it would go something like this:
class YourTask extends BuildTask {
public $description = "...";
//...
public function run($request) {
YourController::init();
}
}
You can invoke it over sake using:
0 0 * * * /path/to/framework/sake dev/tasks/YourTask
why not create a build task ? which is specially designed for such requirements (at-least that's how I consider build tasks)
<?php
class ArticleCsvUpdateTask extends BuildTask {
protected $title = 'Article Csv Update';
protected $description = 'Build task for article Csv update';
public function run($request) {
$loader = new ArticleCsvBulkLoader('Color');
if($loader->load('import-new.csv')) {
$loader->load('import-new.csv');
}
}
}
Which can be assess both from browser using "yoursite/dev/tasks/ArticleCsvUpdateTask" and from command line using "php framework/cli-script.php dev/tasks/ArticleCsvUpdateTask" OR using "sake dev/tasks/ArticleCsvUpdateTask" (if you have sake installed).
May be I am not getting your exact requirement but I believe this is much cleaner and nicer way of running a cron job with silverstripe.
See Zauberfisch's answer for a complete solution
I'm not familiar with Silverstripe, but if I understand correctly, this controller init function can be called with a HTTP request.
As the silverstripe docs say, you can call any url from the command line:
php framework/cli-script.php Update/init
More information is available here, and consider using sake for this task.
I think the right way do this is create a php file console like:
#!/usr/bin/env php
<?php
require_once "/path/to/your/class/Update.php";
$class = new Update();
$class->init();
Add right perms to this file
chmod 755 consolefile
And finally run this script with cronjob
Point 6 on the below page describes how data can be imported using a script:
http://innoexts.com/currency-pricing/#.UjI1uPlgaHo
The problem is the example provides a shell script so I get an error when trying to run this from a browser. Is there any way that these types of scripts can be run from as a browser as I don't have access to Shell?
I figured out the solution to this. Just needed to comment out the contents of protected function _validate() in /shell/abstract.php
In shell/abstract.php
add a line below
protected $_factory; // Line 76
as
protected $_passvalidation = false;
Then change in function __construct()
$this->_validate();
to
if(!$this->_passvalidation) $this->_validate();
In your shell script add
function __construct() {
$this->_passvalidation = true;
parent::__construct();
}