I am developing a module that has function that need to run periodically in cron.
The idea of implementation is to create a controller that third party cron module is going to call. My problem is that in order to call that controller a token is needed. Tokens in admin panel are temporary per session. Is there any way to get static token for a certain controller? Or is there a better way to implement what I want (through api or something)?
routes.yml:
admin_mymodule_myaction:
path: /mymodule/myaction
methods: [GET]
defaults:
_controller: 'PrestaShop\Module\MyModule\Controller\Admin\MyController::myAction'
MyController.php:
class MyController extends FrameworkBundleAdminController{
public function myAction(){
...
}
}
link to controller (token is temporary):
http://localhost/admin303/index.php/modules/mymodule/myaction?_token=uPmkkqeqBVfnjUGdLKs9_Ik585Q1GlsXWK-qiGfC3r0
I found the solution.
I need to use Front controller, NOT Admin controller. Front controller needs no token, I can define my own security system.
https://devdocs.prestashop.com/1.7/modules/concepts/controllers/front-controllers/#using-a-front-controller-as-a-cron-task
mymodule/controllers/front/cron.php:
<?php
class MyModuleCronModuleFrontController extends ModuleFrontController
{
/** #var bool If set to true, will be redirected to authentication page */
public $auth = false;
/** #var bool */
public $ajax;
public function display()
{
$this->ajax = 1;
//my functionality goes here
$this->ajaxDie("OK.");
}
}
and the link to trigger functionality will be:
http://localhost/index.php?fc=module&module=mymodule&controller=cron
Wonder why official documentation did not come up during Google search.
Related
I am trying to pass data from login controller to login.blade.php in laravel 6 like I using common header throughout the application so I have to create dynamic title and description. default login controller is something like this
class LoginController extends Controller
{
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
Don't know how to pass. please help
Just customize your showLoginForm function provided by laravel as default in your LoginController. see code below
class LoginController extends Controller {
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct() {
$this->middleware('guest')->except('logout');
}
public function showLoginForm()
{
return view('login', ["data"=> 'this is test data']);
}
}
If you are looking to learn Laravel, I would recommend checking out the guides in their documentation here: https://laravel.com/docs/6.x
Relating to authentication, there is a short guide here that will get you up and running quickly: https://laravel.com/docs/6.x/authentication
You can use the two commands below to setup all of the framework and routing that you need to handle authentication automatically, it will also give you an idea of what to look at if you choose to build your own authentication in future.
composer require laravel/ui --dev
php artisan ui vue --auth
Well, there should have a Trait named AuthenticatesUsers onto the LoginController.php in Laravel 6.x. But somehow we don't see it in the login controller you provided above.
The Trait is located here
vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php
However there is a method called showLoginForm(). You can override this method and pass whatever you need to pass in as the following.
/**
* Show the application's login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
// Notice the second argument
return view('auth.login', ['key' => 'value']);
}
Hope this would make sense.
I am trying to create an application where i have a user activity log. I dont want to write a special function in all the pages. I just want to metnion it once and run on all the pages or controller where ever i go. Which keep showing on the header.blade.php. And i want to keep using that log all time.
I have a function with like this.
public function headerLogs()
{
$latestActivities = Activity::with('user')->latest()->limit(10)->get();
return view('layouts.header')->with('logs', $latestActivities);
}
How can i do that?
Laravel has built-in functionality for that: View Composers. They are what you use if you want some data to be in every view that is loaded (of course you specify which views exactly)
So from the docs we would create a service provider for our view composer:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ActivitiesComposerServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* #return void
*/
public function boot()
{
// Using Closure based composers...
view()->composer('layout.header.activity', function ($view) {
$latestActivities = Activity::with('user')->latest()->limit(10)->get();
$view->with('logs', $latestActivities);
});
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}
And then you register your ActivitiesComposerServiceProvider service provider by simply adding it to the providers array in config/app.php.
So now you can simply #include('layout.header.activity') and the logs will show with no extra line of code in your controller or view
In your base controller:
view()->composer('layouts.header', function($view){
//your code for header logs which gives $logActivites.
$view->with('logs', $logActivites);
}
So, whenever your view layouts.header will be created, this $logActivites will be available.
Everyone had a situation when one variable had to be accessible in every view (blade) file. One possible solution – letting the service provider load our global view information. For Example, type this in your service provider.
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// Using view composer for specific view
view()->composer('welcome',function($view) {
$view->with('latestActivities', Activity::with('user')->latest()->limit(10)->get());
});
}
}
Then you can access the latestActivities variable from all you view files
In my routes files I have a bunch or routes for testing purposes:
/** testing controllers */
Route::get('viewemail', 'TestController#viewemail');
Route::get('restore', 'TestController#restore');
Route::get('sendemail', 'TestController#send_email');
Route::get('socket', 'TestController#socket');
Route::get('colors', 'TestController#colors');
Route::get('view', 'TestController#view_test');
Route::get('numbers', 'TestController#numbers');
Route::get('ncf', 'TestController#ncf');
Route::get('dates', 'TestController#dates');
Route::get('print', 'TestController#printer');
Route::get('{variable}', 'TestController#execute');
/** End of testing controllers */
I want to eliminate all those routes and simple use the name of the given URL to call and return the method:
I have accomplished that in this way:
Route::get('{variable}', 'TestController#execute');
And in my testing controller:
public function execute($method){
return $this->$method();
}
Basically what I want to know if Laravel has a built in solution to do this, I was reading the documentation but couldn't find any way to accomplish this.
From official documentation:
http://laravel.com/docs/5.1/controllers#implicit-controllers
Laravel allows you to easily define a single route to handle every
action in a controller class. First, define the route using the
Route::controller method. The controller method accepts two
arguments. The first is the base URI the controller handles, while the
second is the class name of the controller:
Route::controller('users', 'UserController');
Next, just add methods to your controller. The method names should begin with the
HTTP verb they respond to followed by the title case version of the
URI:
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
/**
* Responds to requests to GET /users
*/
public function getIndex()
{
//
}
/**
* Responds to requests to GET /users/show/1
*/
public function getShow($id)
{
//
}
/**
* Responds to requests to GET /users/admin-profile
*/
public function getAdminProfile()
{
//
}
/**
* Responds to requests to POST /users/profile
*/
public function postProfile()
{
//
}
}
As you can see in the example above, index methods will respond to the
root URI handled by the controller, which, in this case, is users.
You could add a route pattern for the endpoints you want to listen for. Route them to a controller action, and then inspect the request:
class TestController extends Controller
{
public function handle(Request $request)
{
$method = $request->segment(1); // Gets first segment of URI
// Do something…
}
}
And in your route service provider:
$router->pattern('{variable}', 'foo|bar|qux|baz');
I'm using Resourceful controller which there are default functions such as index, create, store, show, edit, update and destroy. My question is that how can I add my own function to that controller? For instance I add a function in that controller like this:
class Account extends \Eloquent {
.
.
.
/**
* Attempt login.
* GET /accounts/login
*
* #return Response
*/
public function login()
{
//
echo "You are in login page";
}
But it seems not work when i enter that url: account/login. This is my route file:
Route::resource('account', 'AccountsController');
You need to add a separate route for it, and the route needs to come before Laravel generates the routes for the resource controller.
Route::get('account/login', 'AccountsController#login');
Route::resource('account', 'AccountsController');
Just imagine, I have a controller with several actions in it.
And to reach each action I have to define it strictly in routing.yml file like this:
admin_edit_routes:
pattern: /administrator/edituser
defaults: { _controller: MyAdminBundle:Default:edituser }
admin_add_routes:
pattern: /administrator/adduser
defaults: { _controller: MyAdminBundle:Default:adduser }
And I can have plenty of such pages. What I want to achieve is to define necessary action in my URI, just like Kohana routes do.
I mean, I want simply to use one route for all actions:
(code below is not valid, just for example)
admin_main_route:
pattern: /administrator/{action}
defaults: { _controller: MyAdminBundle:Default:{action} action:index}
It will pass all requests to /administrator/{anything} to this route, and after that, according to the action, stated in the uri, the needed action is gonna to be called.
If action is not stated in the uri, then we got thrown to index action.
Is it possible in Symfony 2 in any ways and if yes, then how?
Thanking in advance.
This doesn't feel right to do so. By exposing your controller API (methods) "on the fly" directly via GET method, you open your application to security vulnerabilities. This can also easily lead to unwanted behaviours.
Moreover, how would you generate routes in twig for example ? By giving explicit constants tied to the method names?
{{ path('dynamic_route', { 'method': 'addUser' }) }}
This is not how Symfony works nor what it recommands. Symfony is not CodeIgniter nor Kohana. You don't need a second "Front Controller"
If this is a laziness matter, you can switch your routing configurations to annotations. And let Symfony auto-generate the routes you need, with minimal efforts.
namespace Acme\FooBundle\Controller;
/**
* #Route("/administrator")
*/
class DefaultController extends Controller
{
/**
* #Route
*/
public function indexAction(Request $request);
/**
* #Route("/adduser")
*/
public function addUserAction(Request $request);
/**
* #Route("/edituser")
*/
public function editUserAction(Request $request);
/**
* #Route("/{tried}")
*/
public function fallbackAction($tried, Request $request)
{
return $this->indexAction($request);
}
}
The fallbackAction methods, returns any /administrator/* route which does not exist to the indexAction content.
To sum up, I advise not to use dynamic routing "on the fly" directly to method names.
An alternative would be to create a command which will generate routes once executed.
Well, maybe that's not the best way to do that, but it works. Your dynamicAction accepts action string parameter and checks if such action exists. If so, it executes given action with params.
/**
* Default Controller.
*
* #Route("/default")
*/
class DefaultController extends Controller
{
/**
* #Route("/{action}/{params}", name="default_dynamic")
*/
public function dynamicAction($action, $params = null)
{
$action = $action . 'Action';
if (method_exists($this, $action)) {
return $this->{$action}($params);
}
return $this->indexAction();
}
}
I'm curious if someone have any other ideas :>