Laravel noun1/$arg1/noun2/$arg2 routing/controller - laravel

I would like to have the following url:
http://localhost/question/1/choices/
and optionally /question/1/choices/3
Where 1 is a question_id and 3 is a choice_id.
How can I do that in Laravel?
Thanks
UPDATE
I think I could achieve this with something like
Route::get('questions/(:num)/choices/(:num)')
But how can I link it to the controller
Class Questions extends Base_Controller {
public static $restful = TRUE;
public function get_choices($question_id, $choice_id) {
//
}
}

Do you'll want a Questions_Controller (remember the _Controller, it's important) like this:
// controllers/questions.php
class Questions_Controller extends Base_Controller {
public $restful = true;
public function get_choices($question_id, $choice_id)
{
// Use $question_id and $choice_id
}
}
And your route would look like controller#action, so...
// routes.php
Route::get('questions/(:num)/choices/(:num)', 'questions#choices');
Routing to actions is covered at the end of Controller Routing, just before the section on CLI Route Testing. Wildcards work the same with actions as they do anonymous functions.

Laravel allows you to use nested resources..
In your case you could have the following in your routes.php
Route::resource('question', 'QuestionController');
Route::resource('question.choices', 'ChoicesController');
Then in your ChoicesController be sure to pass in both question_Id and choice_Id
You can check if everything is routed correctly by running:
php artisan routes

Related

How to swap out dependency in laravel container

I have registered a Paypal service provider:
App\Providers\PaypalHelperServiceProvider::class,
and, when I type hint it in my controller it properly resolves:
public function refund(Request $request, PaypalHelper $paypal) {...
Here is my provider class:
class PaypalHelperServiceProvider extends ServiceProvider
{
protected $defer = true;
public function register()
{
$this->app->bind('App\Helpers\PaypalHelper', function() {
$test = 'test';
return new PaypalHelper();
});
}
public function provides()
{
$test = 'test';
return [App\Helpers\PaypalHelper::class];
}
}
Everything works as expected. Now I wanted to be able to modify controller to take a PayPal interface. I would then update my service provider to conditionally pass in either the real class or a mock one for testing, using the APP_ENV variable to determine which one to use. I put some debuggers into the service provider class and could not get it to ever go in. I thought perhaps that it only loads them on need, so I put a breakpoint inside my controller. The class did resolve, but it still never went into the service provider class! Can someone explain to me why this is the case? Even when I modified the code to pass in a different class type it did not pick up.
EDIT:
Here is the code flow I see when I debug this:
ControllerDispatcher -> resolveClassMethodDependencies -> resolveMethodDependencies -> transformDependency. At this point we have the following laravel code in the RouteDependencyResolveerTrait:
protected function transformDependency(ReflectionParameter $parameter, $parameters, $originalParameters)
{
$class = $parameter->getClass();
// If the parameter has a type-hinted class, we will check to see if it is already in
// the list of parameters. If it is we will just skip it as it is probably a model
// binding and we do not want to mess with those; otherwise, we resolve it here.
if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
return $this->container->make($class->name);
}
}
Since getClass() always resolves to the interface name, when we call container->make(), it always fails with
Target [App\Helpers\PaypalHelperInterface] is not instantiable.
Change
$this->app->bind('App\Helpers\PaypalHelper', function() {
$test = 'test';
return new PaypalHelper();
});
To
if (app()->environment('testing')) {
$this->app->bind(
PaypalHelperInterface::class,
FakePaypalHelper::class
)
} else {
$this->app->bind(
PaypalHelperInterface::class,
PaypalHelper::class
);
}
I finally found out the issue. My problem was that my provider wasn't being picked up at all. Here was the solution
composer dumpautoload
php artisan cache:clear
https://laravel.io/forum/02-08-2015-laravel-5-service-provider-not-working

Pass object in all methods of all controllers in Laravel

I have this code in the HomeController#index:
$towns = Town::all();
return Redirect::to('home')
->with('towns', $towns);
Is there any way I can tell Laravel to execute that lines of code before the end of methods and controllers I define without me copying and pasting those lines of code in every method?
You don't need to do that, you can just share this data with all views by using the view()->share() method in a service provider:
view()->share('towns', Town::all());
You can also use a view composer for that:
public function compose(View $view)
{
$view->with('towns', Town::all());
}
You can extend all controllers from your basic controller. Use Controller.php on app/Http/Controllers/controller.php or create new one.
Add myThreeLines to base controller.
controller.php:
function myThreeLines(){
$towns = Town::all();
return Redirect::to('home')
->with('towns', $towns);
}
class TestController extend Controller{
function index(){
return $this->myThreeLines();
}
}

multiple routes in single Method controller in laravel 4

I want to know if it is possible to create multiple roots for single methode controller in laravel? something like this :
//route
Route::get('foo/bar', 'FooController#bar');
Route::get('foo/bar/{id}', 'FooController#bar');
Route::get('foo/bar/{id}/{date}', 'FooController#bar');
//controller
class FooController extends Controller {
public function bar($id,$date)
{
//do something
}
}
Yes but you have to handle null parameters, like that:
public function bar($id=null, $date=null)
{
....
But at this point its better to declare e single route with optional parameters:
Route::get('foo/bar/{id?}/{date?}', 'FooController#bar');

controller and routes doesn't generate the index.php I'm using laravel 4.1

I am a newbie at laravel. I have a problem about rooting and views. I am following a tutorial. But the output with the tutorial and my output are not the same.
when i insert this at address bar localhost/laravel/2nd_project/public/authors, i am not generating the index.php which supposed to be have a output just like the tutorial
here is the controllers/authors.php
<?php
class Authors_Controller extends Base_Controller{
public $restful = true;
public function get_index(){
return View::make('authors.index');
}
}
app/routes.php
<?php
Route::get('/', function()
{
return View::make('hello');
});
Route::get('authors',array('uses'=>'Authors_Controller#get_index'));
views/authors/index.php
<h1>Hi User!!</h1>
It looks like you're following the tutorial based on Laravel 3. In Laravel 4, things have changed. In laravel 4, the controllers name must follow the pattern SomethingController, so the filename for your controller must be AuthorsController.php and the class name muse be AuthorsController.
So, inside of controllers directory, you'll have a file named AuthorsController.php which will be like:
<?php
class AuthorsController extends BaseController {
public function getIndex()
{
return View::make('authors.index');
}
}
Also, if you need to have a file named BaseController.php with the class BaseController, if you're extending BaseController from the AuthorsController.
In the routes file you can do the following:
Route::get('authors', array('uses'=>'AuthorsController#getIndex'));
If you want RESTful controllers in Laravel 4, you can read more about it in the official documentation here: http://laravel.com/docs/controllers#restful-controllers

Codeigniter : calling a method of one controller from other

I have two controllers a and b.
I would like to call a method of controller a from a method of controller b.
Could anyone help explain how I can achieve this?
This is not supported behavior of the MVC System. If you want to execute an action of another controller you just redirect the user to the page you want (i.e. the controller function that consumes the url).
If you want common functionality, you should build a library to be used in the two different controllers.
I can only assume you want to build up your site a bit modular. (I.e. re-use the output of one controller method in other controller methods.) There's some plugins / extensions for CI that help you build like that. However, the simplest way is to use a library to build up common "controls" (i.e. load the model, render the view into a string). Then you can return that string and pass it along to the other controller's view.
You can load into a string by adding true at the end of the view call:
$string_view = $this->load->view('someview', array('data'=>'stuff'), true);
test.php Controller File :
Class Test {
function demo() {
echo "Hello";
}
}
test1.php Controller File :
Class Test1 {
function demo2() {
require('test.php');
$test = new Test();
$test->demo();
}
}
Very simple way in codeigniter to call a method of one controller to other controller
1. Controller A
class A extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function custom_a()
{
}
}
2. Controller B
class B extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function custom_b()
{
require_once(APPPATH.'controllers/a.php'); //include controller
$aObj = new a(); //create object
$aObj->custom_a(); //call function
}
}
I agree that the way to do is to redirect to the new controller in usual cases.
I came across a use case where I needed to display the same page to 2 different kind of users (backend user previewing the page of a frontend user) so in my opinion what I needed was genuinely to call the frontend controller from the backend controller.
I solved the problem by making the frontend method static and wrapping it in another method.
Hope it helps!
//==========
// Frontend
//==========
function profile()
{
//Access check
//Get profile id
$id = get_user_id();
return self::_profile($id);
}
static function _profile($id)
{
$CI = &get_instance();
//Prepare page
//Load view
}
//==========
// Backend
//==========
function preview_profile($id)
{
$this->load->file('controllers/frontend.php', false);
Frontend::_profile($id);
}
I posted a somewhat similar question a while back, but regarding a model on CI.
Returning two separate query results within a model function
Although your question is not exactly the same, I believe the solution follows the same principle: if you're proposing to do what you mention in your question, there may be something wrong in the way you're coding and some refactoring could be in order.
The take home message is that what you're asking is not the way to go when working with MVC.
The best practice is to either use a Model to place reusable functions and call them in a controller that outputs the data through a view -- or even better use helpers or libraries (for functions that may be needed repeatedly).
You can do like
$result= file_get_contents(site_url('[ADDRESS TO CONTROLLER FUNCTION]'));
Replace [ADDRESS TO CONTROLLER FUNCTION] by the way we use in site_url();
You need to echo output in controller function instead of return.
You can use the redirect() function.
Like this
class ControllerA extends CI_Controller{
public function MethodA(){
redirect("ControllerB/MethodB");
}
}
Controller to be extended
require_once(PHYSICAL_BASE_URL . 'system/application/controllers/abc.php');
$report= new onlineAssessmentReport();
echo ($report->detailView());
You can use the redirect URL to controller:
Class Ctrlr1 extends CI_Controller{
public void my_fct1(){
redirect('Ctrlr2 /my_fct2', 'refresh');
}
}
Class Ctrlr2 extends CI_Controller{
public void my_fct2(){
$this->load->view('view1');
}
}
very simple
in first controllr call
$this->load->model('MyController');
$this->MyController->test();
place file MyController.php to /model patch
MyController.php should be contain
class MyController extends CI_Model {
function __construct() {
parent::__construct();
}
function test()
{
echo 'OK';
}
}

Resources