How do I pass router parameters to a Concrete5 controller - php

Per https://documentation.concrete5.org/developers/routing/routing-basics one captures parameters from the route as follows:
$router->get('/api/customer/{customerId}', function($customerId) {
return 'The customer ID is: ' . $customerId;
});
However, per https://documentation.concrete5.org/developers/routing/controllers one shouldn't use closure and instead use a separate controller as follows:
$router->get('/api/current_user', 'Application\Api\Controller\UserController::getCurrentUser');
class UserController
{
public function getCurrentUser()
{
//...
}
}
How do I pass a parameter when using a controller? I would have expected the following, but $customerId is not passed to the controller method.
$router->get('/api/customer/{customerId}', 'Application\Api\Controller\UserController::getSomeUser');
class UserController
{
public function getSomeUser($customerId)
{
//...
}
}

Related

How to use same controller function in other controller in laravel?

I have and function like this, and I am using this through API and send request object.
public function test(Request $request){
//code
}
now I want to use the same function in another function like this
public function test2(){
$id = 2;
$this->test($id);
}
but in above I need to pass an id.
but the first function expects an argument type of request instance.
How can it be done? and I can't add second argument.
If you are not allowed to edit the method code for some reason, you can do the following:
Create a new Request instance.
Add id property to it with the value.
Call your method.
The Illuminate\Http\Request class has a capture() method which is like below:
/**
* Create a new Illuminate HTTP request from server variables.
*
* #return static
*/
public static function capture()
{
static::enableHttpMethodParameterOverride();
return static::createFromBase(SymfonyRequest::createFromGlobals());
}
In your code, you would do like below:
<?php
use Illuminate\Http\Request;
class xyz{
public function test(Request $request){
//code
}
public function test2(){
$request = Request::capture();
$request->initialize(['id' => 2]);
$this->test($request);
}
}
You should export your code in another function and then use a Trait in each of your controller. Therefore you will have access to the same function in two different classes.
By doing this, you can give whatever argument you want, even set defaults one without calling the controller function itself.
The official doc about Trait
The best practice would be to create a third private method in the controller (or in a separate class, as you prefer) that is called by both functions:
class TestController extends Controller {
public function test(Request $request){
$id = $request->get('id', 0); // Extract the id from the request
$this->doStuffWithId($id);
}
public function test2(){
$id = 2;
$this->doStuffWithId($id);
}
private function doStuffWithId($id) {
// code
}
}
You can and should organize your shared code across multiple controllers with services. Basically create class
<?php
namespace App\Services;
class TestService
{
public function testFunction($id)
{
// add your logic hear
return 'executed';
}
}
and in your controller inject this service and call function testFunction() like this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\TestService;
class TestController
{
protected $testService;
public function __construct(TestService $testService)
{
$this->testService = $testService;
}
public function test(Request $request){
// handle validation, get id
$this->testService->testFunction($id);
// return response from controller (json, view)
}

Laravel: calling controller method from another location

In my Laravel app I have the following controller that takes the instance of Elastic search as a first parameter and then another variable:
use Elasticsearch\Client;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class AngularController extends Controller {
public function selectRandom(Client $es, $numRows) {
# ...search params here
$results = $es->search($searchParams);
return $results;
}
}
I need to call the method of the controller above from another controller, I do it like this:
class HomeCtrl extends Controller {
public function index() {
$featured = new AngularController();
return $featured->selectRandom(12);
}
}
I get the following error
Argument 1 passed to
App\Http\Controllers\AngularController::selectRandom() must be an
instance of Elasticsearch\Client, integer given
I'm not well versed in OOP. Do I call it incorrectly? Because I though the method I call would take instance that is injected in controller, not from where I call it.
When you are calling a method from your Controller to another
Controller that means you are doing wrong. For this purpose you should
use service.
Create a class in app\Services Utility.php
use Elasticsearch\Client;
class Utility {
public function selectRandom(Client $es, $numRows) {
# ...search params here
$results = $es->search($searchParams);
return $results;
}
}
and just inject this class to your controller
In your AngularController class selectRandom method first parameter is a class instance second one is number,that's why you get this error.If you want to access this method using object form another controller you need to set first parameter of this object and second one is your id.Another solution is here
some modify in selectRandom method
public function selectRandom($numRows) {
# ...search params here
$es = new Client();
$results = $es->search($searchParams);
return $results;
}
Then you use this function
public function index() {
$featured = new AngularController();
return $featured->selectRandom(12);
}

Codeigniter Call Parent Controller Function Inside Model

I know this is MVC structure incompatible but i need to use this technique:
I have a controller and a model.
I'm calling a function in model from controller.
Model called function calles controllers another function. (This is what generates error).
Example below:
Controller:
public function B($ret=false) {
if(!$ret)$this->Model_model->M($ret);
else echo 'ok';
}
Model:
public function M($ret=false) {
$this->N($ret);
}
private function N($ret=false) {
$this->Controller->B(!$ret); //i can't find how can i call this
}
My first trigger function is:
$this->Controller->B(false);
I've moved code in function B of controller to the Model completely and now everything is going in model itself. B function calling another B function in model and at last step model isn't need to call controller; it is calling B function in Model:
Controller:
public function B($ret=false) {
$this->Model_model->B($ret);
}
Model:
public function B($ret){
if(!$ret)$this->M($ret);
else echo 'ok';
}
private function M($ret=false) {
$this->N($ret);
}
private function N($ret=false) {
$this-B(!$ret);
}
My first trigger function is:
$this->B(false);
And my controller is still has short code.

Access to a different Controller

I want to access to my TestControler in DefaultController. So I've create a new instance, but the container is null. If I want to call a method, symfony throws a FatalErrorException:
Error: Call to a member function get() on a non-object in
DefaultController:
/**
* DefaultController.
*
*/
class DefaultControllerextends Controller
{
public function indexAction()
{
$contrTest = new TestController();
var_dump($contrTest);
}
var_dump result:
object(test\testBundle\Controller\TestController)#283 (1) {
["container":protected]=> NULL }
How can i do that?
Using other controllers inside a controller is a sign of bad architecture. Usually, it means you have to split the controller into a service, which you can use everywhere, and a controller.
For instance, when you have a controller which has a parseAction which parses a file and you need to use that in another controller too, you must create a acme_demo.parser.the_file_type service (give it which name you want) and use that in both controllers:
// ...
class FirstController extends Controller
{
public function xxxAction()
{
$parser = $this->get('acme_demo.parser.the_file_type');
$data = $parser->parse(...);
}
}
// ...
class SecondController extends Controller
{
public function yyyAction()
{
$parser = $this->get('acme_demo.parser.the_file_type');
$data = $parser->parse(...);
}
}

Laravel: Load method in another controller without changing the url

I have this route: Route::controller('/', 'PearsController'); Is it possible in Laravel to get the PearsController to load a method from another controller so the URL doesn't change?
For example:
// route:
Route::controller('/', 'PearsController');
// controllers
class PearsController extends BaseController {
public function getAbc() {
// How do I load ApplesController#getSomething so I can split up
// my methods without changing the url? (retains domain.com/abc)
}
}
class ApplesController extends BaseController {
public function getSomething() {
echo 'It works!'
}
}
You can use (L3 only)
Controller::call('ApplesController#getSomething');
In L4 you can use
$request = Request::create('/apples', 'GET', array());
return Route::dispatch($request)->getContent();
In this case, you have to define a route for ApplesController, something like this
Route::get('/apples', 'ApplesController#getSomething'); // in routes.php
In the array() you can pass arguments if required.
( by neto in Call a controller in Laravel 4 )
Use IoC...
App::make($controller)->{$action}();
Eg:
App::make('HomeController')->getIndex();
and you may also give params
App::make('HomeController')->getIndex($params);
You should not. In MVC, controllers should not 'talk' to each other, if they have to share 'data' they should do it using a model, wich is the type of class responsible for data sharing in your app. Look:
// route:
Route::controller('/', 'PearsController');
// controllers
class PearsController extends BaseController {
public function getAbc()
{
$something = new MySomethingModel;
$this->commonFunction();
echo $something->getSomething();
}
}
class ApplesController extends BaseController {
public function showSomething()
{
$something = new MySomethingModel;
$this->commonFunction();
echo $something->getSomething();
}
}
class MySomethingModel {
public function getSomething()
{
return 'It works!';
}
}
EDIT
What you can do instead is to use BaseController to create common functions to be shared by all your controllers. Take a look at commonFunction in BaseController and how it's used in the two controllers.
abstract class BaseController extends Controller {
public function commonFunction()
{
// will do common things
}
}
class PearsController extends BaseController {
public function getAbc()
{
return $this->commonFunction();
}
}
class ApplesController extends BaseController {
public function showSomething()
{
return $this->commonFunction();
}
}
if you were in AbcdController and trying to access method public function test() which exists in OtherController you could just do:
$getTests = (new OtherController)->test();
This should work in L5.1

Categories