Welcome Guest, Not a member yet? Register   Sign In
Multiple controllers per page + Multiple instances of the same model
#11

Awesome, that's the detail that I needed to know -  I didn't figure that I could put multiple controllers into that MY_Controller.php file and that CI would still load them correctly.

mwhitney Wrote:They are intended to provide functionality to controllers which extend them, so their methods are usually declared as protected instead of public (except the constructor)
Will the methods be routable and accessible if I declare them as public (No private/protected keyword and no underscore at the beginning of the method name), even though the controllers are in the core folder? Basically, can I also define a "working", "actual" controller in the MY_Controller file, or only controller baseclasses? If not, can I somehow use a "normal" controller as a baseclass?
Reason for this is that my site has multiple pages, with one of them kind of acting like a "parent page". Some code across the pages will therefore be the same, but there are enough differences to not use only one controller for them all. That's why I would like to use my base controller not only as a controller, but also as a "parent". If this is not possible I can just extend all of my pages with one basecontroller, and not implement any specific code into the "parent" page.
Reply
#12

You can define public/routable methods in one of the core controllers, but I generally wouldn't recommend it. (Similarly, you can use a "normal" controller as a base class, but I wouldn't recommend that, either.)

Putting multiple controllers into the MY_Controller.php file is basically just a hack to get CI to load the controllers before your child controller is defined (because you'll get an error when PHP comes across the parent class' name after the extends keyword if the controller hasn't been loaded and can't be autoloaded). You can set them up in separate files within your /application/core directory and load them in a slightly more intelligent fashion, but I don't recall what else is required to get this working properly.

Using a "normal" controller as a base class requires you to ensure that the "normal" controller is loaded before the child class is defined, just as would be the case with any base controller defined in the core directory. In most cases, it's slightly more difficult to load a "normal" controller than a core controller, especially if your core controllers are just loading out of MY_Controller.php.

However, when it comes down to it, there's nothing technical stopping you from putting a routable method in a base controller. Just remember that routable methods are accessible via the URL, regardless of whether they're inherited from a parent controller, so you should limit the number of public methods you're inheriting.

I happen to use a base controller in development for quick mock-ups of admin controllers which include public methods to demonstrate common functionality (index, create, edit, and it is mostly functional if a model is defined and the database table(s) setup), but I don't feel like I've spent enough time considering all of the potential problems with that code to use it in production, and it tends to be confusing to open up a controller and find that the method(s) you're looking for aren't defined.
Reply
#13

(This post was last modified: 07-22-2016, 03:01 PM by Call-Me-Captain.)

(07-22-2016, 11:00 AM)PaulD Wrote: It is! Welcome to CI
Thanks!

(07-22-2016, 11:00 AM)PaulD Wrote: Excellent plan! But do the tutorials first, a lot will become very clear.
Yeah, I've read a lot on the user guide. Mostly because I did jump right in and needed clarification, but, hey, "trial by error" can be seen as an established learning concept Tongue

(07-22-2016, 11:00 AM)PaulD Wrote: You don't normally but you can. The controller can call libraries. So you would call your user_library to do users authorisations etc. A controller would normally call many libraries.
I've actually solved this by using the HMVC extension (As suggested by InsiteFX) and creating my own controller for user related stuff. I figured that the only data I need to know on pages and page parts that aren't directly user-related is the logged in user's ID, so this has been working fine for me for now. Was it a bad way of doing things? Because whereever I go, people are talking about using your own library, and not a controller. After being done with my user system, though, I don't see the benefits of the former, since it's also going a little bit against the MVC concept, or isn't it?

(07-22-2016, 11:00 AM)PaulD Wrote: A CI model is normally used to deal with the database. So if I want a user details in the controller I would call my user_library with the method get_user_details and it would do whatever logic is needed, then call the user_model that would interogate the database and return the requested data. This means that should I change my database structure I need only change the user_model, and all calls to it will still work fine.
Yeah, I'm using the models like that now. It still seems a little weird to me though, haha (I mean, CI is so flexible that I could even do it the way I'm used to do it, but I chose to do it the CI way, since good practice usually means good results, too)

Quote:Tons of ways to approach this. The easiest is to construct the page with several views. So load->view(header), then sidebar, then page_content, then footer, as many views as you need to construct your page.
Alternatively, you can create your own theme_library and call that to construct your page. Alternatively you can use an integration of a template engine like Twig, which is relatively easy to integrate, or use an existing integration library you can google for.
Well, that question was mostly for situations where I'd need to include the same view multiple times depending on a for loop in another view. But after looking around a little bit I realized that I can actually do $this->load->view inside of another view. (While writing this I'm suddenly not so sure anymore, but, eh, I'll just try once I get to that point.)


Quote:Only use Ajax if it improves the user experience. You can use multiple different methods in a single Ajax_controller, or you can create seperate controllers for each ajax call, that is up to you. I usually have one Ajax controller for each page or page-group, but sometimes have done it with an seperate controller for users, one for posts etc. Although I do like to group page functions into one controller. I only seperate out the Ajax to a seperate controller so I can set the route as CSRF free in the config file.
Responsiveness is something I associate with screen size manipulations, but that is an HTML and media-query css issue.
My bad, I always seems to use the term 'responsiveness' when I actually mean, uhm, "dynamism" or something. Basically, the whole "No need to refresh that page pal, I got your back" part. AJAX.
May I ask what benefits there are to creating a new controller per page for AJAX, as to creating another set of actions in the same controller? Right now, I'm even using the same action for the AJAX and non-AJAX version, delivering a different output depending on an argument. Obviously, I have no clue what can be considered good practice and should be used.
The thing is, that I do not want to force the AJAX on the user, meaning that the site should still work fine even when the user doesn't have javascript. (So instead of a login popup, or some data-list dynamic refresh, the whole site refreshes/changes URL.)

Quote:Your welcome. I would suggest that many of these questions would be best answered by getting a domain, getting CI up and running and having a play. I would not plough into a serious build of something too soon, but work towards it maybe. From experience, you will probably have to rebuild a few times anyway as your plans for the site change and mature. By keeping your code with good seperation using librariies and models, you should be able to re-use lots of stuff even if your plans change.

Good luck,

Paul.
Well, I am kind of using my "serious build" to learn everything, so maybe I'll kill two birds with one stone - Let's hope, haha.
And thank you very much! (edit: huh, where did your post go?)



@mwhitney
Okay then, thank you very much! I guess I'll just define my "base functionality" in the MY_ core controller, and extend it with my real controllers - One of them therefore containing close to no code. Right Big Grin?
Reply
#14

(This post was last modified: 07-22-2016, 04:31 PM by PaulD.)

Quote:Well, I am kind of using my "serious build" to learn everything, so maybe I'll kill two birds with one stone - Let's hope, haha.
And thank you very much! (edit: huh, where did your post go?)

How did it come back Smile

I deleted it because I thought it didn't really offer any help and the conversation had moved on so much. Sorry.

Quote:Well, that question was mostly for situations where I'd need to include the same view multiple times depending on a for loop in another view. But after looking around a little bit I realized that I can actually do $this->load->view inside of another view. (While writing this I'm suddenly not so sure anymore, but, eh, I'll just try once I get to that point.)

Yes you can do that, lots of people like having views called from within views. Personally I do not like to do that myself but no good reason why. Just feels a bit anti-view to me.

Quote:May I ask what benefits there are to creating a new controller per page for AJAX, as to creating another set of actions in the same controller? Right now, I'm even using the same action for the AJAX and non-AJAX version, delivering a different output depending on an argument. Obviously, I have no clue what can be considered good practice and should be used.

Again just my preference. I normally have a directory called ajax and files in there like, Tasks_ajax.php, and all the ajax functions that for tasks live in that file. For me it means that I can CSRF ignore that one route, and also I know where all my ajax stuff is happening. I use libraries heavily now with very thin controllers (as thin as possible) which I have found works really well. So even that ajax file will be pretty thin.

Quote:The thing is, that I do not want to force the AJAX on the user, meaning that the site should still work fine even when the user doesn't have javascript. (So instead of a login popup, or some data-list dynamic refresh, the whole site refreshes/changes URL.)

I must admit that I just say dammit, if you have not got js enabled you cannot use the web app. Graceful degradation all the way down to pure HTML (without even css files) is simply an impossible burden, and I never see it really, so I admit I just ignore it. (I know, I am a terrible person for doing so).

Quote:Well, I am kind of using my "serious build" to learn everything, so maybe I'll kill two birds with one stone - Let's hope, haha.

Lol, I know and I do that too! Again, it can have benefits, learning on a real world case, but you might have a re-write or two to do when you suddenly realize an assumption you had made somewhere down the line is not working, safe or appropriate.

Anyway, good luck again, I won't delete this post this time Smile

Best wishes,

Paul.


PS As a top tip, use a crud model for common things.
On the site I am doing at the moment, for the first time I built myself a simple Crud_model.php that has proved a real time saver. Clearly it is not as powerful or careful as some that are available on github, but it is worth writing one. So now to get a result from any table I can just

PHP Code:
$data $this->crud_model->get_row('table''field''value');  // single row
or
$data $this->crud_model->get_rows('table''field''value'); // multiple rows 

It has been a massive time saver and I will be doing this forever now. Because it is my own, it does exactly what I need it to and I cannot believe I have not used a crud model up to now. My own one is already fairly complicated as I have different methods for more complex settings, like
PHP Code:
$data $this->crud_model->get_rows_where('table'$where$join$page$offset); 

Anyway, top tip, use a generalized crud model.

Paul.
Reply
#15

Quote:Again just my preference. I normally have a directory called ajax and files in there like, Tasks_ajax.php, and all the ajax functions that for tasks live in that file. For me it means that I can CSRF ignore that one route, and also I know where all my ajax stuff is happening. I use libraries heavily now with very thin controllers (as thin as possible) which I have found works really well. So even that ajax file will be pretty thin.
I have to admit that I don't know what CSRF is. I found a small explanation by googling, but I can't say that I fully understood it.
About the use of libraries: For myself, I just don't know what I should do. On one hand I totally see where you're coming from, and I agree that thin controllers sound very attractive, but on the other hand I think that this kind of practice kind of defeats the purpose of MVC, since most actions will now simply be handled by libraries instead of a controller designed specifically with that task in mind.
(Then again, I do seem to encounter some problems where I'd like to use more than just the User's ID - which is set globally through the session - so I'm kind of leaning towards restructuring my app to use libraries more heavily.

Quote:I must admit that I just say dammit, if you have not got js enabled you cannot use the web app. Graceful degradation all the way down to pure HTML (without even css files) is simply an impossible burden, and I never see it really, so I admit I just ignore it. (I know, I am a terrible person for doing so).
Heh, I guess you can see it that way too Big Grin



Oh, and thanks!

Quote:PS As a top tip, use a crud model for common things.
On the site I am doing at the moment, for the first time I built myself a simple Crud_model.php that has proved a real time saver. Clearly it is not as powerful or careful as some that are available on github, but it is worth writing one. So now to get a result from any table I can just

Hm, I don't know, isn't this also kind of completely defeating the use of MVC principles? I mean, I get that with how models are commonly used, one can avoid having to change code in the controller, but with such a model, that last assumption wouldn't be true anymore, either.
Where's the benefit of that crud-model in comparison to directly using the Query-Builder or basic database request? I honestly can't see that much of a difference between the two.
(Btw, how does this work in english: "The benefit of X in comparison to Y" somehow sounds wrong. Is there a specific idiom to be used? Not an english native speaker.)



Random, totally off-topic question about database design: Let's assume I have one table for users, and one for user groups. How would you go about linking different permissions to the usergroups? I just can't think of an elegant way to do this right now.
Reply
#16

Hi,

You have a table of users, and a table of user groups. If users can only be in one group, just add a column on the user table indicating which group they are in.

If a user can be in multiple groups, you need an additional table linking user_id to group_id, so a user can have multiple group affiliations.

As for the crud model idea, don't worry about it, I have just found it really helps speed up things. For instance, I add a table called 'Plants', and I can immediately read from, update to and delete from that table using my crud model, never having to write a single query, checking return values or writing if($query->num_rows() > 0) ever again! For more complex queries on the plants table, I can then make a plants model and put the query and logic in there. However it is amazing how much of the time my previous models were filled with the same repetitive code again and again.

As for thin controllers, and heavy libraries, it makes sense to me. So my controller says, who are they (auth library), what do they want to do (permissions library), did it work (another library), what do I display (theme library). My business logic is nicely seperated, each library is individually testable, my code is simple to read, it is very DRY, maintainable and easy to develop further. It is also easy then to port different libraries between sites. But the beauty of CI is you can it any way you want. When I first started out I had everything in my controllers including database calls.

Best wishes,

Paul.
Reply
#17

Thanks for your answer again!

(07-23-2016, 09:54 AM)PaulD Wrote: You have a table of users, and a table of user groups. If users can only be in one group, just add a column on the user table indicating which group they are in.
If a user can be in multiple groups, you need an additional table linking user_id to group_id, so a user can have multiple group affiliations.
I actually came that far too - The part that I'm not sure about is how to correctly implement permissions. I thought of having another many to many, uh, thing, by linking together UserGroup and Permission in another table. Two 'problems' with that, though:
1. It would just be so much more beautiful if I could somehow have User permission inheritance (By letting user groups inherit from each other, and then only define the additional permissions each user group gets. Obviously, this is the bad approach when having a relational DATAbase, where it is more important to keep the queries simple and with as few "control structures" as possible, than the amount of data. So, yeah, no problem, just me being stubborn about the design again.
2. I talked with a non-programmer friend about this, and he was like "Dude, why do you need to make everything flexible? You know what you want to do, so just do it.". Which, translated into technical language (he did say a bit more than this), basically means that I should just include one row per permission in the users table, thus making user groups totally irrelevant. Thing is: He has a point. It would work. Pretty well, even. But it's just so uuuuglyyyyyyyyyy. Dx

Quote:As for the crud model idea, don't worry about it, I have just found it really helps speed up things. For instance, I add a table called 'Plants', and I can immediately read from, update to and delete from that table using my crud model, never having to write a single query, checking return values or writing if($query->num_rows() > 0) ever again! For more complex queries on the plants table, I can then make a plants model and put the query and logic in there. However it is amazing how much of the time my previous models were filled with the same repetitive code again and again.
Yeah, I get where you're coming from - And I can also see why it's useful. (But I still think that crud model pretty much is the same as database helper class Tongue).

Quote:As for thin controllers, and heavy libraries, it makes sense to me. So my controller says, who are they (auth library), what do they want to do (permissions library), did it work (another library), what do I display (theme library). My business logic is nicely seperated, each library is individually testable, my code is simple to read, it is very DRY, maintainable and easy to develop further. It is also easy then to port different libraries between sites.
Yup, actually seems like a really good idea. Time to refactor that learning code I already wrote, lol
(One little specific question: You said you separate auth and permissions library. How exactly do you go about that? My guess would be auth is for the users themselves and permissions, well, for the permissions/groups only? Actually, nevermind. No questions here.)

Quote: But the beauty of CI is you can it any way you want. When I first started out I had everything in my controllers including database calls.
Aah, the blessing and curse that is flexibility Big Grin!


Thanks & kind regards,
-
Reply
#18

(This post was last modified: 07-23-2016, 03:36 PM by PaulD.)

Actually the whole permissions thing is a whole ball game in itself.

Just as a note:
  • Authentication - are they allowed access
  • Authorisation - are they logged in
  • Permissions - are they allowed to do that
I deal with these in three different libraries, hence the permissions separate from the other two.

I used to do permissions as something like roles:
  • Guests
  • Users
  • Super Users
  • Admins
With each role having their own set of allowed actions or not. Nice and easy but not flexible.

Later I needed more fine grain control. So a super user could assign exactly what other users in their group could or could not do. That meant having a permission setting for every action or group of actions. People had roles, and belonged to groups of their fellow users, and could admin roles below them but not above.

So I had a table of actions (view profile, edit profile, delete profile, approve profile change etc.) and another table of default settings for a group, (so a member of the user group by default can view profiles, but not edit, delete or approve).
Then, with another table that overrode the default permissions if set, a person can adjust settings for roles below them for users in their own group.

This worked really well, was super flexible, but a real PITA. But it tied in really well with the history model that had to record actions anyway.

Anyway, just a bit bored and rattling on.

I hope we get to see a link to your site when you are ready :-)

Paul.

PS the problem with the inheritance idea is that you will quickly find that it removes control, so you have to be able to override it anyway for instances where you do not want the inheritance to be applied, so the whole inheritance functionality becomes moot anyway.
Reply
#19

Thank you very much!



Wow, you got quite the user system there Big Grin!


Quote:I hope we get to see a link to your site when you are ready :-)
Haha, I hope so too! Need to get it done first, though. <.<
Reply




Theme © iAndrew 2016 - Forum software by © MyBB