How to pass data from cron to Controller laravel php - php

How how can i transfer data from cron(sheduler) to Controller which make json in laravel
this is my route:
Route::get("/data",'DataController#Data');
and this is my function Data in controller:
public function Data(){
return response()->json(['data'-> User::all()],200);
}
And how can i make cron which will make query to mysql for User, save in variable and pass to my controller?
Update:
I try to use Cache:
in my command(which will be run by crontab)
public function handle()
{
$data = User::All();
Log::info('Data: ' . $data);
Cache::put('data',$data);
Log::info('Done!');
Log::info('Data: ' . Cache::get('data'));
}
problem is fact that First info() printf me good data but when i try to get from cache i got nothink, i try to storage data to File
CACHE_DRIVER=file (from .env)
i run page on windows, and storage folder has permissions to create files

What you are trying to do makes no sense at all. The scheduler is being run through a CLI interface, which has nothing to do with the Controllers.
I would highly recommend you to not mix the Scheduler and Controllers, but instead create Helper-classes for methods, that you might have to reuse.
If you want to run the Controller anyway, you can run it with something like:
(new App\Http\Controllers\DataController())->Data()
Disclaimer: I'm not completely sure on how the response and request classes behaves, when you call a Controller outside of the normal Request-lifecycle.

Related

Is there a way to act as a user inside of Laravel without hitting the database?

I'm writing unit tests for an API using PHPUnit and Laravel. Most functions I'm testing require that the user is authenticated before the function can be ran. The user data is stored in one table, and their permissions are stored inside of another table. I can fake the user object inside of Laravel, but I need to be able to also pull the corresponding permissions from the other table without having to hit the database like the dingo router currently is doing.
Currently running Laravel 5.8 and PHPUnit 8.1.5. I currently have the users object that I generated from a Laravel factory saved to a text file. I am able to pass that to a function called "actingAsApi" (found on Github, code below) and that allows me to authenticate as that user. However, the function is still going out and getting all permissions for that user from the database. I'm trying to mock or fake the permissions object it is pulling somewhere so that it doesn't need to hit the database at all. I also tried using the built in Passport functions for Passport::actingAs, and those did not work either as they were still hitting the DB (and not really working anyways).
actingAsApi (inside of TestCase.php)
protected function actingAsApi($user)
{
// mock service middleware
$auth = Mockery::mock('Dingo\Api\Http\Middleware\Auth[handle]',
[
Mockery::mock('Dingo\Api\Routing\Router'),
Mockery::mock('Dingo\Api\Auth\Auth'),
]);
$auth->shouldReceive('handle')
->andReturnUsing(function ($request, \Closure $next) {
return $next($request);
});
$this->app->instance('Dingo\Api\Http\Middleware\Auth', $auth);
$auth = Mockery::mock('Dingo\Api\Auth\Auth[user]',
[
app('Dingo\Api\Routing\Router'),
app('Illuminate\Container\Container'),
[],
]);
$auth->shouldReceive('user')
->andReturnUsing(function () use ($user) {
return $user;
});
$this->app->instance('Dingo\Api\Auth\Auth', $auth);
return $this;
}
Test inside of my Test file
public function testActAs() {
$user = 'tests/users/user1.txt';
$this->actingAsApi($user);
$request = new Request;
$t = new TestController($request);
$test = $t->index($request);
}
I expect the actingAsApi function to allow me to also pass in the mock permissions data that corresponds to my mock user object data from the file, but instead it is hitting the database to pull from the permissions table.
EDIT:
So i've been playing around with doing mock objects, and i figured out how to mock the original controller here:
$controlMock = Mockery::mock('App\Http\Controllers\Controller', [$request])->makePartial();
$controlMock->shouldReceive('userHasPermission')
->with('API_ACCESS')
->andReturn(true);
$this->app->instance('App\Http\Controllers\Controller', $controlMock);
but now I can't figure out how to get my call from the other controllers to hit the mocked controller and not a real one. Here is my code for hitting an example controller:
$info = $this->app->make('App\API\Controllers\InfoController');
print_r($info->getInfo('12345'));
How can i make the second block of code hit the mocked controller and not standup a real one like it does in its constructor method?
Finally came on an answer, and it is now fixed. Here's how I did it for those wondering:
$request = new Request;
$controlMock = m::mock('App\API\Controllers\InfoController', [$request])->makePartial();
$controlMock->shouldReceive('userHasPermission')
->with('API_ACCESS')
->andReturn(true);
print_r($controlMock->getInfo('12345'));
Basically, I was trying to Mock the original API controller, and then catch all of the calls thrown at it. Instead, I should've been mocking the controller I'm testing, in this case the InfoController. I can then catch the call 'userHasPermission', which should reach out to the Controller, but I am automatically returning true. This eliminates the need for hitting the database to receive permissions and other info. More information on how I solved it using Mockery can be found here: http://docs.mockery.io/en/latest/cookbook/big_parent_class.html. As you can see, this is referred to as a 'Big Parent Class'. Good luck!

View composer runs multiple times, how to reduce to 1

I made a view composer in Laravel 5. When i use a wildcard *, to add something to all my views, it get's called at least twice. It runs when my master template is loaded, and again when my content page is included. This will give problems in the future, because it executes the query it does multiple times. I was able to fix the multiple querying by storing it in a static variable :
class StoreComposer {
static $composed;
public function __construct(StoreRepository $repository)
{
$this->store = $repository;
}
public function compose(View $view)
{
if(static::$composed)
{
return $view->with('store', static::$composed);
}
static::$composed = $this->store->pushCriteria( new WithCategories() )
->pushCriteria( new WithSettings() )
->applyCriteria()
->all();
$view->with('store', static::$composed);
}
}
My question is, is there a way to make sure it only runs once, no matter how many views i load, or is there another solution to this? The way i fixed it now doesn't feel right to me. Thanks!
Unfortunately no, there is no way to make it run once, due to the way View Composers are implemented. The Illuminate\View\View::renderContents() method is responsible for calling the composer bound to a view, and since any form of view rendering (Blade template inheritance or simple #include statements) executes that method, it means that when any view is rendered any composer bound to it gets triggered.
Since in your case you use a * wildcard to bind all views, if your page renders ten views, the composer will get executed ten times. However your approach looks like a good solution to solve this shortcoming.
You can use config here to resolve multiple times query run issue for example show below code.
public function compose(View $view)
{
if(!Config::has('composeVars'))
{
Config::set('composeVars') = [
'data' => User::all();
];
}
$view->with('*', Config::get('composeVars'));
}
Try this singleton solution or use cache https://laracasts.com/discuss/channels/laravel/executing-a-view-composer-only-once
On Laravel 5.6.38 works fine

Laravel 5 get command response

I think I understand the concept of command in Laravel, in that it's a good place to put reuseable code, that can be called from controllers and the like, but I have a query:
Can I return a value back to the calling method from a command? For example, I have a controller method which creates a user in Active Directory, for which there is a command to do this. If the AD server is unreachable, I want to return a response back to the calling controller method. Is this possible?
It only shows in the documentation how to call a command using dispatch(), but nothing as to whether it can return anything.
And if you cannot return a value, can someone explain the reasoning behind why you wouldn't want to return a value? I know that queued commands may take a while and wouldn't be appropriate to wait for a response, but for commands that should be executed immediately I don't see why you wouldn't want to return a value.
Any help or advice is appreciated.
In the context of the command bus, yes you can return values on non-queued commands. In your command handler method, simply return what you want:
public function handle(){
return 'foobar';
}
And save the result of your dispatch command to a variable:
$my_command_result = $this->dispatch(
new MyCommand();
);
Commands are not for storing reusable code in controllers. Theyre getting renamed to jobs in 5.1 and their main purpose it to work as Cron Jobs. If you have a method to create a user and want to use it in many places, you could store it in the User model.

Does laravel Event::queue() works in local environment?

Does Event::queue('event.name') works in local environment?
Provided that it works locally, as I understand we still have to flush the event using Event::flush('event.name'). But I am not able to make it work. The usual Event::fire('event.name') works just fine.
This is my controller store method
public function store(){
$input = Input::all();
if ($this->validator->isValidForCreation($input)){
$owner = $this->admin->createOwner($input);
Event::queue('event.name', [$input]);
return Redirect::route('admin.index')->with('success', 'Owner successfully created.');
}
return Redirect::back()->withInput()->withErrors($this->validator->getErrors());
}
Where should I use the Event::flush('event.name') in my code? I tried flushing it in a route closure (just for testing) after storing the user, but it didn't trigger the event and the code inside the event handler wasn't executed. Should I flush it inside the store function before redirecting to other route?

Query caching in CodeIgniter

I want to cache a query in CodeIgniter. What I did for my test is make a controller, that I named show.php:
class Show extends CI_Controller{
public function __construct()
{
parent::__construct();
$this->load->model('rejaal_show');
}
public function _remap($method = '',$param = array())
{
$method = intval($method);
$this->output->cache(5);
var_dump ($this->rejaal_show->temp($method));
}
}
And a model that I named rejaal_show.php:
public function temp($id)
{
$this->db->cache_on();
$this->db->where('id',$id);
$query = $this->db->get('system_store_table');
return $query->result();
}
When I call http://localhost/rejaal/show/1 for the first time, it will show a result, but when I call it for the second time, it does not show anything.
I should delete the query cache file to show it again? How should I solve this problem?
With special thanks for your attention.
Can you confirm that you have set $db['default']['cachedir'] to the path of a writable folder in application/config/database.php and that when the query is first run it creates a cache file in there?
The only other reason I can think of for it failing is by your use of the _remap override. I have not used db caching using _remap, but know that CodeIgniter creates a folder called controller+action in your cache folder, and might not be handled very well if using remap? Someone correct me if I am wrong about this.
In the CodeIgniter User Guide page for Web Page Caching, it says:
Because of the way CodeIgniter stores content for output, caching will only work if you are generating display for your controller with a view.
Do your var_dump inside a view.

Categories