I am building a Laravel 4 application and I am trying to sort out where my admin controller functions should go.
eg my admin user view, edit and update functions.
Previously in my User controller, I would have
function getIndex()
{
// Get method for normal users
}
function getAdminIndex()
{
// Get method for admin users
}
I would then have in the routes /users -> getIndex() and /admin/users -> getAdminIndex()
however, is this ideal?
The reason is it makes my routes file quite large as I have to specify every route.
With things like Blog posts, and Products, should I have one controller for logged out / user access, and then a separate controller, in an admin folder for just the admin functions?
Is there some open source projects I can look at?
You should separate your regular controllers from your admin controllers. It's a matter of personal preference how you do it: you can create folders inside your controllers folder, or maybe you could create –almost– independent modules with controllers on their own.
For the first option, take a look at this project:
https://github.com/andrew13/Laravel-4-Bootstrap-Starter-Site
For the second one, which is a bit more complex, you can get inspired from this post by Ryan Tablada:
http://ryantablada.com/post/juggling-larger-laravel-applications
I personally prefer this last one if the project is medium/large size, and the other one if it's a small project.
You can also try Laravella, a CMS, CRUD, Bootstrap, Uploader etc. framework for Laravel.
https://github.com/laravella/laravella/releases
If your project is small, then you can use Resource Controller.
Related
I’ve to make a webapp with public and administrator parts and we are two different developer teams. I’ve searched the best way to do that and I found HMVC. I accomplished to install the codeigniter-modular-extensions-hmvc from wiredesignz and it’s working, but I think I haven’t understood the philosophy of the folder/module structure.
If I want to create a webapp with admin and public pages referencing the same db tables (for example with the admin part can configure the general preferences, blog categories, add users, add roles… and with the public part an user can add blogs, images, ...)
It will be a good structure something like that?
/modules/blog/ -> only blog model
/modules/user/ -> only user model
...
/modules/login/ -> login controller and pages referencing user and role modules (models)
/modules/admin/ -> admin controller and pages referencing other modules
/modules/public/ -> public controller and pages referencing other modules
...
/modules/templates -> controller and pages for public and admin template
If I want to have more than admin or public controller, I’ve to create more modules? (modules/admin_dashboard, modules/admin_users, ...)
I hope you can help me, I’m a little bit lost :/
Thx!
There are some nice tutorials by David Connelly on youtube. He suggests '1 table - 1 module' structure. Then, you can use those module's controller's methods in other modules (like dashboards) to get or manipulate the data. This is how I understood it.
I'm new to Codeigniter and pretty new to OOP as of the last month or so. I've been playing around and have been trying to make a blog page with a list of 10 posts and have different functions and possibilities for each.
For example, in the future I want to be able to show different buttons below posts depending on whether they are a logged in user, or if they are the post creator, etc.
Would I be best off making a new class 'blog_posts' and making an instance of it for every post I show on the page? like:
$this->load->library('blog_posts'); // in library or models, I'm not too sure?
$new_inst = new blog_posts;
$new_inst->show_post();
My end goal is to get it all as easily updated, changed, or modified in future if needed, I've seen simple tutorials online:
http://blog.pisyek.com/2011/03/create-a-simple-blog-using-codeigniter-2-0-part-1/
But I can't see them being easily updated and modified in future. I haven't seen a lot of other CI apps using new instances of classes, so I'm thinking there may be a different way in CI? Are new instances used in CI a lot?
Start with the controller. With Codeigniter -- anything you can do in a model, you can do in the controller. The easiest way to start -- just put your methods in the controller and set up a simple view file.
Always do a simple sanity check to make sure the basics are proper. Set up a controller and echo out some text.
In the controller try:
Get blog posts from your database using active record commands
Pass the blog posts result to $Data
With each step, Echo out something in the controller to confirm that its working
Next -- try using $Data to pass the blog results to the view.
After its working and you understand the basics -- then start pushing your methods to a Model. As you refactor and clean, your controller will get 'thinner'.
typically for blog posts you would have one model, that would return the blog posts and might also have your insert / update / delete methods. i say might because it usually makes more sense to have a public blog controller, that just shows blog posts. and then a separate blog admin controller -- that is only available to users who are logged in.
These two controllers - can share the same blog model. So for example to show blog posts on an admin screen - you could use the same method as showing the posts on a public page. Whereas you might have an admin blog model -- which has the create / update / delete methods.
That way you enforce a very clear separation of User Roles from the start -- people who are viewing the public blog should not be able to delete posts. The public show blog class is not "responsible" for editing.
This is something that i'm grappling with -- like the normal way to demonstrate a blog is to have all the methods together. Which makes sense in terms of "what can we do with a blog post" -- but it doesn't make any sense in terms of user roles.
ok Next - work on your create and update and delete methods.
Next try creating your log in methods. Make the Login process separate controller / model / view.
Eventually you could have one method call in the constructor of your blog admin class that checks to make sure that the user is logged in - otherwise it redirects them to a login page. That way you dont have to check over and over again in the view files etc to make sure they are authorized.
( highly recommend the free codeigniter tutorial series on net tuts website )
more rambling:
looking at the process from the point of view of the actor (user,role) -- for me helps to clarify what the chain of control should be. really critical roles - like an admin that has the power to delete all blog posts - the system should know that role at the top of the class.
best 'worst example' is when there are "is this a super admin?" checks in the view code. the view should not know anything about admin roles. BUT MUCH WORSE when you put a reference to an admin role in some view file -- what happens when you want to change that admin role in some way? now you have to go into all your view files!
class and method names - i'm moving towards not revealing any business or crud or field or any other type of business information in the URL. no nouns no verbs no ids. as simple as possible, with very few public url 'doors' into the app.
whats wonderful is that codeigniter makes it really easy to make your methods private. for critical pages: only use the public index method in the class for redirecting and make all other methods private.
use routes that directly to private methods. or public methods with broad names, that if successful -- like you have confirmed their credentials - go to private methods in the class like $this->_showAdminPage()
this is where defining a role like - blog editor - makes things very clear from a functionality point of view, AND keeps the valuable business knowledge private.
I have been developing with CakePHP and the Alaxos ACL plugin has helped in tremendously.
However, I am facing one issue I am not sure how to fix it?
I added a plugin named 'pages', but I cannot get ACL to see it so it is added to the list of allowed/denied actions.
If I access the plugin thru domain.com/pages/pages I get the following error
DbAcl::check() - Failed ARO/ACO node lookup in permissions check.
When I check thru the ACL plugin display, there is no reference to the pages controller and if I run the ACL build function, it simply says that there is nothing to add.
Is it because this controller is named pages and there is already a pages controller within Cake?
If it is how do I fix it? Is my only option, at this time, adding this manually to the Db? Should I go thru this plugin and rename pages to something else? or is there anything else I should be doing?
Thanks,
I see two things here. First like you suspect, having two classes in your application that share the same name is a bad idea. It will likely give you some problems in one way or another, with the wrong class being instantiated or whatever. As far as Cake does not use namespaces, this is not recommended.
Then, even if you change this name, there will be another problem if the controller you want to manage with ACL is the 'default' controller (a controller that has the same name as the plugin). There was an issue with the ACO nodes retrieval when the path contains twice the same name, which is the case for plugins default controllers.
controllers/Pages/Pages/index
So I decided to just skip the plugins default controllers from the controllers supported by the ACL plugin.
If you are the author of this plugin, you could rename it (because PagesController exists already), and move the actions in some other controller than the default controller.
You have the URL:
http:///www.site.com/controller/method/values/1/2/3
Do I have to always have the controller being called or can I have the view being called and instantiate the controller inside the view or in a bootstrap file referring to this view?
What I don't get it is if I need more than 1 controller on the view, how to archive that?
For example:
On my index page I want run a simple CMS, where the admin can change the text blocks and images of the site. That would be on the content management controller.
On my index page I also got the latest added products vitrine, what would be controlled by the controller products.
If I define www.site.com/contentmanagement or www.site.com to run the contentmanagement controller, how the product controller would be called?
Also, another example. On my menu I got a link to a page called aboutus, that would be a simple page and the only feature needed would be the content management controller to manage the texts blocks.
If I follow the pattern Im reading all over the place I will end with a link like:
http://www.site.com/contentmanagement/method/aboutus
?
Kinda lost here cause surely this URL will look weird. Would be much easier to have the URL calling the view http://www.site.com/aboutus and a boot file where I can tell the controller that should be loaded when the surfer is there ...
bootstrap would look like:
switch($view)
case: index
controller load contentmanagement
controller load product
case: aboutus
controller load contentmanagement
I appreciate any help or a light here, thanks.
by the way, Im coding in PHP.
Hm, if you want to have text blocks and images of the site (one controller), and products vitrine (second controller), then call the methods you need in one controller..
I would do it this way: when you request index page with all the elements you mentioned above, actually one controller is called, and it decides which view to show.. so in that controller, you call the all methods that you need, get the data, and pass it to the view.. if the methods are called from other controllers, just call that methods and get the data.. i often make some static methods in controllers, which I can call anywhere, so I don't have to instantiate whole object..
E.g. you call www.site.com/contentmanagement, controller is called, which will display index view, and in that controller, you call all methods you need, prepare the data, and pass that data to the final view which will be displayed..
Do I have to always have the controller being called or can I have (..blah blah..)?
It kinda depends on what you understand by "call".
Controller needs an ability to change state of both View and Model(s).
And each View need ability to request data (in Model2 MVC) from Model(s).
Thought Controller should not cause the rendering of View (which is common in all the RoR sycophants) much like View has not business in executing actions on the Controller.
What I don't get it is if I need more than 1 controller on the view, how to archive that?
Views and Controllers should have 1:1 relationship. If your view need more then one controller, you might want to look into HMVC architecture.
For example: On my index page I want run a simple CMS, (.. more blah .. ) how the product controller would be called?
CMS should be a separate application ( or at least module ) with multiple controllers.
If I follow the pattern Im reading all over the place I will end with a link like: http://www.site.com/contentmanagement/method/aboutus ?
Why not just http://site.com/cms/content/2/edit (where 2 is the ID for "about us" page). There is no law which states that URL structure for site administration must mirror the publicly available page .. hell .. it can actually cause increased vulnerability.
I am going to try to walk
What I don't get it is if I need more than 1 controller on the view,
how to archive that?
For example: On my index page I want run a simple CMS, where the admin
can change the text blocks and images of the site. That would be on
the content management controller. On my index page I also got the
latest added products vitrine, what would be controlled by the
controller products. If I define www.site.com/contentmanagement or
www.site.com to run the contentmanagement controller, how the product
controller would be called?
Having the URL to contains the controller's name is definitely nice, but it is not the requirement for MVC. So you don't have to necessary map your controller to the URL itself. A classic MVC does not tie itself to a particular naming convention, so you could call your product controller via different URL which then process the product and show the view for the product.The important for MVC is to have one controller that deals with sets of model and resulting in one view as the presentation layer. In your particular example, your entry point seems to be a single controller that interacts with both ContentManagement and Product Class/Module and the resulting interaction produce a single view.
bootstrap would look like:
switch($view)
case: index
controller load contentmanagement
controller load product
case: aboutus
controller load contentmanagement
Thus your original interaction above is not completely off, except that you are not really calling two controllers, but rather doing the following upon hitting index:
Load a controller, let's call this one IndexController
Load ContentManagement module to get the related content, you might want to put the info as part of your Model for the Index page
Load Product module to get related products, again put this into your Model
Pass the Model containing the info for rendering the page into the View
In your View, you render the Model that contains both Content from ContentManagement module and Product list from the Product module thereby producing a single view
If I follow the pattern Im reading all over the place I will end with
a link like: http://www.site.com/contentmanagement/method/aboutus ?
This is again not a requirement, you should follow what makes sense and easier for the users. Also, if you are required to follow the conventions, you could always make your URL pretty by using URL mapping.
What you are looking for is called HMVC and there are a couple of frameworks for that out there, like Kohana.
Also see this question:
What is the HMVC pattern?
I'm working on an app in CodeIgniter, and I want to have admin pages for several of the objects in the application, and I'm wondering what would be the better way to put these into an MVC structure.
Idea 1:
In each controller, have an admin function, and add all of the admin pages I would like into that function.
example URL: domain.com/articles/admin
Idea 2
Make a new admin controller, which would have to reference many different models, and put all of the admin pages in there.
example URL: domain.com/admin/articles
Which way would be better?
Edit for clarification: By admin functionality, I mean being able to do the basic CRUD actions on any object, and be able to display a list of all of said object.
Definitely a different controller at least!
I used to think that I could keep all my admin functions in a single controller, but as my programs grew, I realized that I needed multiple controllers in my administration section.
So, I created a folder inside my controllers folder with the name "admin" and put all my administrative controllers in there. So my folders would look something like:
application
controllers
front.php
welcome.php
admin
dashboard.php
useradmin.php
etc...
One problem this creates, however, is when you type http://mysite.com/admin in your browser, it returns a 404 page. So, go to your "application/config/routes.php" file and add a custom route:
$routes['admin'] = 'admin/dashboard/index';
I'll echo Justin in keeping it part of the individual controllers.
You should setup some kind of authorization system that the individual controllers can use to so who is logged in (username) and what access they have (admin/member/etc). Here's a SO thread on CodeIgniter Auth Classes.
The view would then conditionally show the appropriate links, and the controller would enforce the policy by checking the auth before passing any data to the model or rendering an edit view. On unauthorized access an error could be rendered, or simply render with the non-editing view.
This approach seems to make the most sense (at least to me) because all the functionality is stored in the individual controller. Keeping admin functions in a single admin controller means you'll have to manage two controllers (the admin, and the actual controller) every time you add somethign new (or remove something).
If you're concerned about putting auth checking in every controller, you could create a generic controller class with all the auth setup, then have your controllers extend it. In the end the individual controller auth check could be as simple as:
function edit()
{
if(!$this->auth()){
//display auth error, or forward to view page
}
}
Of course some kind of ACL implementation would make this better, but I don't believe CodeIgniter has an 'official' ACL.
It's a good idea to have an admin folder in the controllers folder wherein you can access your administration e.g. yoursite.com/admin/users.
All your administrative needs will be there and all methods will be protected by checking user privileges like so:
if ( ! $this->auth->logged_in(array('login', 'admin')))
{
$this->session->set_flashdata('message', 'You do not have access to view this page');
redirect('admin/users/login');
}
Then all controllers outside the 'admin' folder will - depending on your type of site - will only be for viewing, etc.. no administrative portions.
Idea 2 is better.
system/application/controllers/admin
You keep all your admin controllers here.
Here is an extensive guide to the pro's and con's of each method:
http://philsturgeon.co.uk/news/2009/07/Create-an-Admin-panel-with-CodeIgniter
Depending on what you mean by 'Admin' functionality...typically, this is thought of as an 'Edit' view.
And typically, you use the existing controller to serve the 'Edit' view allowing the authorized users to make the edits (in your case, Admin users only).
Looks like a personal choice, i love having everything centralized so the admin controller would be my bet.
That way i wouldn't have to open up 5 different controllers while modifying admin tasks.