In laravel 4 i would like to have a nested controller.
I have read the documentation but didn't find any explanation on how to do it.
Supose that in a app i have some articles and each article have his own set of comments. I would like to be able to get all comment of a specific article by accessing a URL like this.
http://myapp.com/articles/5/comments
I have created a commentsController, but i don't know how to correctly get the article id from the url, so i can pass it to all my CRUD methods in my controller
in route.php
Route::resource('articles.comments','commentsController');
in controller
public function show($articleId, $comment) {}
public function create($articleId) {}
I am not sure nested resource controllers are the way to go.... Here is what I would do.
Route::resource('articles','articlesController');
Route::get('articles/{$id}/comments','articlesController#comments');
Then in your controller
public function comments($id) {
}
Related
I have been declaring all the routes for my application inside web.php , but it is now getting quite large. I find that I am losing a lot of time shifting between web.php and each controller and this is hurting productivity.
I feel like it would be better to define routes inside of the controller, perhaps ideally delegating some URL to a controller and then allowing the controller to handle the "sub routes" since this would allow me to use inheritance when I have two similar controllers with similar routes.
It is not possible given how laravel works. Every request is passed onto router to find its designated spot viz. the controller with the method. If it fails to find the route within the router, it just throws the exception. So the request never reaches any controller if the route is not found. It was possible in earlier versions on Symphony where you would configure the route in the comment of a particular controller method.
Sadly with laravel it works how it works.
But for me, I just like to have the routes in a separate file.
Alternate solution, easier way to sort all the routes.
You can move your route registration into controllers if you use static methods for this. The code below is checked in Laravel 7
In web.php
use App\Http\Controllers\MyController;
.....
MyController::registerRoutes('myprefix');
In MyController.php
(I use here additional static methods from the ancestor controller also posted below)
use Illuminate\Support\Facades\Route;
.....
class MyController extends Controller {
......
static public function registerRoutes($prefix)
{
Route::group(['prefix' => $prefix], function () {
Route::any("/foo/{$id}", self::selfRouteName("fooAction"));
Route::resource($prefix, self::selfQualifiedPath());
}
public function fooAction($id)
{
........
}
In Controller.php
class Controller extends BaseController {
....
protected static function selfAction($actionName, $parameters = [], $absolute = false)
{
return action([static::class, $actionName], $parameters, $absolute);
}
protected static function selfQualifiedPath()
{
return "\\".static::class;
}
protected static function selfRouteName($actionName)
{
//classic string syntax return "\\".static::class."#".$actionName;
// using tuple syntax for clarity
return [static::class, $actionName];
}
}
selfAction mentioned here is not related to your question, but mentioned just because it allows making correct urls for actions either by controller itself or any class using it. This approach helps making action-related activity closer to the controller and avoiding manual url-making. I even prefer making specific functions per action, so for example for fooAction
static public function fooActionUrl($id)
{
return self::selfAction('foo', ['id' => $id]);
}
Passing prefix into registerRoutes makes controller even portable in a sense, so allows inserting it into another site with a different prefix in case of conflict
What I wanna do is to know, inside a view, if I'm in a specific controller or not. From what I know, I've got two choices and I don't have the answer to either of them :-D
inject a view variable using the share method in my AppServiceProvider, which involves getting the current controller name(or at least the action name so that I can switch it) inside the service provider.
inject a variable to all the views returned in the controller. For example does controllers have a boot method? Or can I override the view() method in the following code snippet?
public function someAction(Request $request)
{
return view('someview', ['myvar' => $myvalue]);
}
well of course there's the easy (yet not easy :|) solution: add the variable in all methods of the controller. I don't like this one.
Thanks
You could use the controller's construct function.
Add this to the top of your controller:
public function __construct()
{
view()->share('key', 'value');
}
I'm using codeigniter. I'm currently working on my routes and controller.
Last week, I explored symfony2 and I liked something:
class DefaultController extends Controller
{
public function indexAction()
{
return $this->render('LVIndexBundle:Default:index.html.twig');
}
public function servicesAction()
{
return $this->render('LVIndexBundle:Default:services.html.twig');
}
public function shoppingAction()
{
return $this->render('LVIndexBundle:Default:services.html.twig');
}
In the controller, each action renders a view.
I would like to do the same in codeigniter -> get several functions / actions leading to distinct views.
I'm new to codeigniter. So far, I understood that 1 controller = 1 view.
I'd like to get 1 controller = several functions for several pages. Otherwise, that would be a lot of pages.
Thanks very much for your help!
Based on my experience(s):
In CI, a controller can has more than 1 view php file
ex (function indexAction as a controller function):
public function indexAction()
{
$this->load->view('header');
$this->load->view('content');
$this->load->view('footer');
}
In Symfony and Codeigniter the controllers are just classes that can hold multiple methods. The methods that are called (called Actions in Symfony) are the place that decides which view(s) must be rendered. One of the main differences between Symfony and CI controllers are the routings that Symfony uses. The routes makes Symfony more flexible then CI.
take a look for an explanation of CI controllers
p.s. Symfony is much more advanced then CI. I like to advise you Symfony :-)
Its absolutely not true that there should be one view per controller. even something as simple as validating a form - you will call different views depending on if the validation passes or not.
Strongly suggest you step through the Tutorial in the codeigniter manual. this is going to answer a lot of questions and its very practical.
I have seen the below functionality and I don't understand how functions in controller is choosed?
class ProfilesController extends \BaseController {
public function index() {}
public function create() {}
public function store(){}
public function show($id){}
public function edit($id){}
public function update($id){}
public function destroy($id){}
}
For local.com/profiles it would call index() function and list all the profiles. For viewing any record local.com/profiles/99 it is using show() method.
For editing any record local.com/profiles/99/edit it is using edit().
Are these methods are created automatically? Please suggest me any link or document which helps in understanding Laravel better.
The links provided to you are good to understand how to implement restful urls in Laravel but you don't know what is restful.
The method naming chosen by Laravel it's a convention used to represent what each method does. It's called CRUD.
Now which method is been called depends on the HTTP Request Method.
GET /resource index resource.index
GET /resource/create create resource.create
POST /resource store resource.store
GET /resource/{resource} show resource.show
GET /resource/{resource}/edit edit resource.edit
PUT/PATCH /resource/{resource} update resource.update
DELETE /resource/{resource} destroy resource.destroy
To avoid redundant code when we have a CRUD we use resource controller.
You have to add the below route to your routes.php and the controller you have already provide.
Route::resource('profile', 'ProfilesController');
It's the same as writing
Route::get('profile', 'ProfilesController#index'));
Route::get('profile/create', 'ProfilesController#create'));
Route::post('profile', 'ProfilesController#store'));
Route::get('profile/{id}', 'ProfilesController#show'));
Route::get('profile/{id}/edit', 'ProfilesController#edit'));
Route::put('profile/{id}', 'ProfilesController#update'));
Route::patch('profile/{id}', 'ProfilesController#update'));
Route::delete('profile/{id}', 'ProfilesController#destroy'));
If you want to generate those lines. You can use Jeffreys Way generators.
See Teach a Dog to REST to understand what I'm talking about.
You can look at github Laravel page at Router.php ->
https://github.com/laravel/framework/blob/master/src/Illuminate/Routing/Router.php
Check the resourceDefaults and addResource* functions :)
--
And of course go to Laravel documentation > http://laravel.com/docs/controllers there is the info which you need for your work..
I assume you are using Resource Controllers, http://laravel.com/docs/controllers#resource-controllers.
I have a controller/model for projects. so this controls the projects model, etc, etc. I have a homepage which is being controlled by the pages_controller. I want to show a list of projects on the homepage. Is it as easy as doing:
function index() {
$this->set('projects', $this->Project->find('all'));
}
I'm guessing not as I'm getting:
Undefined property: PagesController::$Project
Can someone steer me in the right direction please,
Jonesy
You must load every model in the controller class by variable $uses, for example:
var $uses = array('Project');
or in action use method
$this->loadModel('Project');
In my opinion the proper way to do this is add a function to your current model which instantiates the other model and returns the needed data.
Here's an example which returns data from the Project model in a model called Example and calls the data in the Example controller:
Using Project Model inside Example Model:
<?php
/* Example Model */
App::uses('Project', 'Model');
class Example extends AppModel {
public function allProjects() {
$projectModel = new Project();
$projects = $projectModel->find('all');
return $projects;
}
}
Returning that data in Example Controller
// once inside your correct view function just do:
$projects = $this->Example->allProjects();
$this->set('projects', $projects);
In the Example view
<?php
// Now assuming you're in the .ctp template associated with
// your view function which used: $projects = $this->Example->allProjects();
// you should be able to access the var: $projects
// For example:
print_r($projects['Project']);
Why is this "better" practice than loading both models into your controller? Well, the Project model is inherited by the Example model, so Project data now becomes part of the Example model scope. (What this means on the database side of things is the 2 tables are joined using SQL JOIN clauses).
Or as the manual says:
One of the most powerful features of CakePHP is the ability to link relational mapping provided by the model. In CakePHP, the links between models are handled through associations.
Defining relations between different objects in your application should be a natural process. For example: in a recipe database, a recipe may have many reviews, reviews have a single author, and authors may have many recipes. Defining the way these relations work allows you to access your data in an intuitive and powerful way. (source)
For me it's more reasonable to use requestAction. This way the logic is wrapped in the controller.
In example:
//in your controller Projects:
class ProjectsController extends AppController {
function dashboard(){
$this->set('projects', $this->Project->find('all'));
}
$this->render('dashboard');
}
Bear in mind that you need to create dashboard.ctp in /app/views/projects of course.
In the Page's dashboard view (probably /app/views/pages/dashboard.ctp) add:
echo $this->requestAction(array('controller'=>'projects', 'action'=>'dashboard'));
This way the logic will remain in the project's controller. Of course you can request /projects/index, but the handling of the pagination will be more complicated.
more about requestAction(). but bear in mind that you need to use it carefully. It could slow down your application.