Laravel - How to run a function/controller every minute ? (Task Scheduling) - php

I have a controller method that I want to run every minute. I read the documentation for Task Scheduling but it seems to document Commands only.
Is there any way that I can use it to call a route/controller method/script every minute ?
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Acc;
class ScriptController extends Controller
{
public function updateAcc()
{
$c = new Scripts\AccountA();
$xoo = $c->getInfo();
$z = json_decode($xoo,true);
$data= new Acc();
$data->price = $z["result"];
$data->save();
}
}
I need to use the DB facades and external classes etc...

Yes, just like the documentation states, you can make a call to any function. So you can do the following:
$schedule->call(function () {
$controller = new \App\Http\Controllers\ScriptController();
$controller->UpdateAcc();
})->everyMinute();
However, it is very bad practice to call a controller out of its web context, you should create a facade or a job that executes the code you want.

Yes, you can write a a shell script that will make a CurlRequest to your controller, and add the shell script to a cron job. or you can use laravel commands and call the controller by a request.
why not using the code inside the controller in a command?

Related

Laravel Illuminate Testing method for refreshing DB only at the start

I have a code that runs everyday and deletes some information from the database.
I am trying to test this code using artisan's test functionality and would like to be able to see the final result on phpmyadmin, however if I add Illuminate\Foundation\Testing\RefreshDatabase The DB seems to refresh at the start AND at the end.
Is there a way to refresh the database at the start only?
Here is a shortened sample of my code:
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Server\Models\User;
use Server\Models\...; //call multiple models
use Tests\TestCase;
class TestRemoveCertainData extends TestCase
{
use RefreshDatabase;
public function removeCertainData()
{
//create all necessary data using factory
factory(User::class)->create(); // etc...
//should run the code that deletes certain data
$this->artisan('remove_data_command')->assertSuccessful();
}
}
So after I run php artisan test Tests\Feature\TestRemoveCertainData I would like to check if php artisan remove_data_command worked the way I intended it to on the phpmyadmin panel.
I wasn't able to find a method for it.
But what I understood was that the idea of keeping the database, and checking it yourself was wrong.
The Laravel Tests themselves are supposed to be something that someone can run in the future with one simple command, such as php artisan test --group=my_group_name.
Therefore the correct way to solve this is to add an assert and compare the tables to your expectations.
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Server\Models\User;
use Server\Models\...; //call multiple models
use Tests\TestCase;
class TestRemoveCertainData extends TestCase
{
use RefreshDatabase;
public function testRemoveCertainData()
{
$users = [
$this->createUserType1(),
$this->createUserType2(),
$this->createUserType3(),
$this->createUserType4(),
];
// deletes emails for users of type 2 and 4
$this->artisan('delete_certain_emails')->assertSuccessful();
// expecting the emails of user 2 and 4 to disappear
$expected = [
$users[0]->mail,
null,
$users[2]->mail,
null,
];
$result = User::pluck('mail')->toArray();
$this->assertEquals($expected, $result);
}
}

How I can delay a piece of code to be executed without breaking the execution flow in laravel?

In a laravel controller I have a piece of code that I need to be executed 48hours later once I create a record in my database.
For example once I run the following code:
$model = new Model();
$model->value = true
$model->save();
Either in console or in a controller 48hours later to execute another job that further processes the created record. Using cron is not an option because it causes in my case unessesary load to my database.
You can use laravel queues for that, simply by delaying job dispatch by 24 hours
you start by creating the job, then in your controller you do this for example:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Jobs\ProcessModel;
use Illuminate\Http\Request;
class ModelController extends Controller
{
public function store(Request $request)
{
$model = new Model();
$model->value = true
$model->save();
ProcessModal::dispatch($model)
->delay(now()->addHours(24));
}
}
reference: https://laravel.com/docs/8.x/queues#delayed-dispatching

Laravel Cron Jobs - controller function

I have a controller in laravel project in /app/Http/Controllers.
The controller called transferDataController.
<?php
namespace App\Http\Controllers;
use DB;
class TransferDataController extends Controller{
public function moveStTempSales(){
// then a lot of queries.
}
}
I need to call this function every 15 minutes. Without calling the api using url on a button or some elements. I was reading about Laravel Schedule.
It works on Laravel 4? And if yes how can I schedule this function in my case ?
I have a good knowledge in server cron jobs.
Go the following directory:
yourproject/app/Console/Commands
In this folder create you can create a class file that contains the function which is to be called on cron.
Now on the same path there is a file : Kernel.php
This file contains:
$schedule->command();
which is to be used to call the function of the currently created class.
After that use:
php artisan schedule:run
to run the functionality.
Reference

How to run a method of a class as a cron task in laravel 5.1

Look I have a class that looks like this, i want to cache some info every day in a cron job with this method cacheTopFilters in laravel 5.1
<?php
namespace namescape/of/the/class;
class FilterTypeCacheService extends BaseService implements IFilterTypeCacheService
{
private $searchFilterService;
private $filterCacheHandler;
function __construct(SearchFilterService $searchFilterService, IFilterTypeCacheHandler $filterCacheHandler){
$this->searchFilterService = $searchFilterService;
$this->filterCacheHandler = $filterCacheHandler;
}
public function cacheTopFilters($type,$keyValuePair,$limit){
$filters = $this->searchFilterService->getAllFilters($type,$keyValuePair);
$this->filterCacheHandler->deleteFiltersBulkFromCache();
$this->filterCacheHandler->SaveFiltersBulk($filters,$type);
}
public function getTopFilters(){
$topFilters = $this->filterCacheHandler->getCachedTopFilters();
return $topFilters;
}
}
As they have dependency injection how can i accomplished to called that method on the app/console/kernel on the schedule method?
You want to take a look at Task Scheduling:
https://laravel.com/docs/5.1/scheduling#defining-schedules
In the App\Console\Kernel class, inside the schedule function, you can schedule anything at all like this:
$schedule->call(function () {
doSomething();
})->daily();
Assuming you have the scheduler setup (system cron job every minute) you should be all set.
If you have a class you need to instantiate, with dependencies injected, you can always use the global app() helper function that Laravel gives you:
$schedule->call(function () {
app(\namespace\of\the\class::class)->cacheTopFilters(...);
})->daily();
That's assuming that Laravel knows how to handle your dependencies. I see that one of your dependencies is a contract (interface) so I'm assuming you've already bound the concrete instance in the Laravel IoC.

Integrating CLI PHP with CakePHP

I have a nice functioning CakePHP 1.3.11 site and I need a scheduled maintenance CLI script to run, so I'm writing it in PHP. Is there any way to make a cake-friendly script? Ideally I could use Cake's functions and Cake's Database models, the CLI requires database access and not much else however. I would ideally like to include my CLI code in a controller and the datasource in a model so I can call the function like any other Cake function, but only from the CLI as a sheduled task.
Searching for CakePHP CLI mostly brings results about CakeBake and cron jobs; this article sounded very helpful but it's for an old version of cake and requires a modified version of index.php. I'm no longer sure how to change the file to make it work in the new version of cakePHP.
I'm on Windows if it matters, but I have complete access to the server. I'm currently planning to schedule a simple cmd "php run.php" style script.
Using CakePHP's shells, you should be able to access all of your CakePHP app's models and controllers.
As an example, I've set up a simple model, controller and shell script:
/app/models/post.php
<?php
class Post extends AppModel {
var $useTable = false;
}
?>
/app/controllers/posts_controller.php
<?php
class PostsController extends AppController {
var $name = 'Posts';
var $components = array('Security');
function index() {
return 'Index action';
}
}
?>
/app/vendors/shells/post.php
<?php
App::import('Component', 'Email'); // Import EmailComponent to make it available
App::import('Core', 'Controller'); // Import Controller class to base our App's controllers off of
App::import('Controller', 'Posts'); // Import PostsController to make it available
App::import('Sanitize'); // Import Sanitize class to make it available
class PostShell extends Shell {
var $uses = array('Post'); // Load Post model for access as $this->Post
function startup() {
$this->Email = new EmailComponent(); // Create EmailComponent object
$this->Posts = new PostsController(); // Create PostsController object
$this->Posts->constructClasses(); // Set up PostsController
$this->Posts->Security->initialize(&$this->Posts); // Initialize component that's attached to PostsController. This is needed if you want to call PostsController actions that use this component
}
function main() {
$this->out($this->Email->delivery); // Should echo 'mail' on the command line
$this->out(Sanitize::html('<p>Hello</p>')); // Should echo <p>Hello</p> on the command line
$this->out($this->Posts->index()); // Should echo 'Index action' on the command line
var_dump(is_object($this->Posts->Security)); // Should echo 'true'
}
}
?>
The whole shell script is there to demonstrate that you can have access to:
Components that you load directly and that are not loaded through a controller
Controllers (first import the Controller class, then import your own controller)
Components that are used by controllers (After creating a new controller, run the constructClasses() method and then the particular component's initialize() method as shown above.
Core utility classes, like the Sanitize class shown above.
Models (just include in your shell's $uses property).
Your shell can have a startup method that is always run first, and the main method, which is your shell scripts main process and which is run after the startup.
To run this script, you would enter /path/to/cake/core/console/cake post on your command line (might have to check the proper way to do this on Windows, the info is in the CakePHP book (http://book.cakephp.org).
The result of the above script should be:
mail
<p>Hello</p>
Index action
bool(true)
This works for me, but maybe people who are more advanced in CakePHP shells could offer more advice, or possibly correct some of the above... However, I hope this is enough to get you started.
As of CakePHP 2, the shell scripts should now be saved to \Console\Command. There is good documentation at http://book.cakephp.org/2.0/en/console-and-shells.html

Categories