I'm still learning Codeigniter/PHP/Database/SQL.
Whenever i encounter new problems, i usually learn something to solve them that may/may not apply to my previous methods.
If they do apply to previous methods or if i make changes to my database design, i usually have to edit/update my CRUD methods relevant to the tables changed.
The problem lay there, since i write my methods as i need them and i don't follow any plan so they're all over the place.
It's not that its not solveable but its very hassle and it just saps away any anticipation i had towards improving my codes then i end up just doing other stuff(procrastinating), its a very vicious cycle, whenever i try to get into it, i end up procrastinating then days pass by then weeks.
I also want to implement thin controller/fat model idea ive read online. Up to now, this is also a part of the problem. I'm trying to solve them all right now but i have a question/doubt before i can truly do it.
I separated my controller into two. 1. needs authentication 2. no authentication.
For now, i have my main controller with methods that needs a user logged in.
for example, user/story dashboard, submitting stories. etc.
The other one is my pages controller, i put there the methods that don't need any user authentication. Like viewing homepage, viewing story profile, reading a chapter, viewing user profile. etc.
In my models, i have separated them into two. account_model and story_model. Any method related to account like registration,logging in etc. and story like publishing story,fetching story data, etc.
My problem with that is that there are some methods that fall into a gray area. or some methods that i would like to group but get separated.
For example: I have a review system(my previous question), users can review other users(author) who have published their stories, stories and chapters.
In my models, the review_author method would go into account model, the review_story and review_chapter would go into story model.
Is it correct for me to just make a review_model and put them all there?
In line of that thought, can i also make separate models for separate groups of methods for example, Pagination model for any method related to pagination(user/story). dashboard model for any method related to my user/story dashboard.
The essence of my question is that i want to be as efficient as possible(of my level of knowledge) so that whenever i get far into my project i don't lose enthusiasm if i have to make changes because of the headache inducing wall of codes.
Related
I have watched many youtube guides/tutorials but those only tackle the coding part.
Whenever i start a project, i always start with a simple controller called main.
and 2 models.
For example: if i were to start an online store project. Then my models would be 'product_model' and 'user_model'. All database functions for users, i always put them in the 'user_model' and all database functions for products, i always put them in the 'product_model'.
user_model:
public function register(){
}
public function login(){
}
//more functions for user
product_model:
public function create_product(){
}
public function review_product(){
}
//more functions for product
My problem is that i easily get confused with my project and/or dissatisfied with how unorganized it is. especially when im more than halfway into the project and i accumulate hundreds of lines of codes.
I could try to organize them myself but at the end of the day, i'm just an amateur so i end up doubting myself. so i get no work done for 1 day(or doing work but redoing it again and again). then that snowballs to tomorrow and the day after that and so on and so forth.
So i want to ask to experienced programmers a basic guideline for me, when to create a new model and a new controller?
How do i group up functions and make them into a separate model?
Do i make a new model per table? and all database functions to that table i just write in the new model created for that table?
Or
Do i group up database functions based on what they do? for example: purchasing a product involves many separate database functions. so save them all inside purchase_model?
The answer to all of these questions is: it depends. Personally I think that kindof of flexibility is what makes coding so interesting.
As a general rule of thumb I try to keep all my classes less than 500-700 lines of code and functions less than 20 lines of code. If my class becomes larger than that I usually start a new one. With that being said, controllers I am fine with being larger as form validation and response logic can take up quite a few lines.
So let's take an example: user authentication system
I would have a controller that contains functions for login, registration, forgot password, and activation; another controller for user management that contains functions to delete, ban, unban, activate, and create new users; and then another controller for the users' profile that contains functions for editing their details and profile picture.
Now as user management and auth systems are typically reusable a library is better then using a model or models; but let's say we use models. I would have a model for each of the controllers outlined in the aforementioned paragraph and then a model for general "utility" functions like checking if the user is logged in .etc.
Generally
You have to decide:
How much code is too much for a controller/model?
(with above) Do I expect my code to grow? If so then I have to take into account how much when determining (1).
How should I group together functions? For this keep in mind separation of concerns e.g. auth functions shouldn't be grouped with database backup functions.
Am I doing too much in a particular function/model? If so, how should I separate these items so that I conform with DRY principles (chances are some code is reusable elsewhere even though its functionality is inherently different).
(with above) If this code is really that useful elsewhere, should I make it into a library/helper?
(and there are countless other things to take into consideration).
I think it is important to realize (especially as a beginner) that your coding style and the "techniques" and organization skills you use will be constantly evolving and so will your code. While it is nice to see that you want to learn the best practices - a lot of this will be dependent on what you want to achieve with your app and what level of mastery you are at in your coding career. Try and look at the bigger picture and realize in a year or two when you look at your code again you will probably say "what was I even thinking here?".
Side note: you could research the ORM approach to models (Laravel and a host of other frameworks use it) but CI has a more "whatever" approach to just about everything. If being forced to work a certain way makes you feel more secure, you might want to learn other "more advanced" and "newer" frameworks.
A topic about single action controllers is in the laravel documentation:
https://laravel.com/docs/5.5/controllers#single-action-controllers
My question is, what is the use case where you will use this controllers? How will you structure your controllers if you opt to use single action controllers for all your controllers?
Michale Dyrynda seems to sum up the pupose of Single Action Controllers in his blog: https://dyrynda.com.au/blog/single-action-controllers-in-laravel
Conclusion
Single action controllers are an effective way to wrap up simple functionality into clearly named classes.
They can be used in instances where you're not necessarily following a RESTful approach; be careful not to separate multiple actions for a single entity across multiple controllers.
Where you might have previously used a single controller for multiple static pages, you could consider separate named controllers for each static pages.
You can add other methods to this class, but they should be related to the single action this controller is responsible for.
He also states that, you should only use these when you only need a single action for an entity:
You may consider naming the controller ShowPost as a way of being explicit about the controller's intent but I'd suggest caution with this approach; if you start seeing ShowPost, EditPost, CreatePost, etc controllers creeping into your codebase, I'd reconsider the RESTful approach. More controllers never hurt anybody, but we should be smart about when this is done!
This is an intresting question and my answer is not related to laravel, but to the single vs multiple actions per controller.
I have found when trying to find the use case for a pattern that is new, is to ask the inverse questions, in this case, when is the use case of multiple actions per controller make sense?
The answer usualy comes to:
You have an object that has crud operations (because your using sql)
and its convenient to place all the stuff related to that object in
one spot.
This is akin to the answer of "I have a hammer, so everything is a screw" and IF your domain is as simple as a thin layer over a crud database, then that is the use case for multiple actions per controller.
What I have found is that any amount of complexity blows up the controllers, no matter how good your model is. The reason is CRUD opperations are apart of your model, not your controller.
We usually think that we will map nicely to a CRUD model in our controller, there are many front end frameworks that work amazing at that, untill....
Look at the most common aspect of applications, users. In the setup your going to have index of users, which I don't know who would look at that page besides admins, and they usualy want extra information. so for the index action, you need admin custom authentication.
Then creation, well, it does not make sense to have an user create an user, you need to ensure the user is not authentication.
Now we talk about reading. What data an admin, other users, current user, and anon user can see is massivily differnt, and will slowly build up in complexity.
Then delete, this is normally rare action, and on some models not needed, but you still put it up, because, well you have a hammer.
The update, do you put password updates in here too? what if the user forgot there password? do you put that in here? No, you make a new action called forgot password.
Well now you need update password action. What goes in the update is usually a gigantic mess of hell after a year.
Each pattern has its pros and cons, my general advice is to do multiple actions per controller when your system is trully CRUD OR you will not have to maintain the project for more than a year. If you have any amount of complexity that will have to maintained, avoid the model leaking into the controller and keep them seperate.
I have this idea of generating an array of user-links that will depend on user-roles.
The user can be a student or an admin.
What I have in mind is use a foreach loop to generate a list of links that is only available for certain users.
My problem is, I created a helper class called Navigation, but I am so certain that I MUST NOT hard-code the links in there, instead I want that helper class to just read an object sent from somewhere, and then will return the desired navigation array to a page.
Follow up questions, where do you think should i keep the links that will only be available for students, for admins. Should i just keep them in a text-file?
or if it is possible to create a controller that passes an array of links, for example
a method in nav_controller class -> studentLinks(){} that will send an array of links to the helper class, the the helper class will then send it to the view..
Sorry if I'm quite crazy at explaining. Do you have any related resources?
From your description it seems that you are building some education-related system. It would make sense to create implementation in such way, that you can later expand the project. Seems reasonable to expect addition of "lectors" as a role later.
Then again .. I am not sure how extensive your knowledge about MVC design pattern is.
That said, in this situation I would consider two ways to solve this:
View requests current user's status from model layer and, based on the response, requests additional data. Then view uses either admin or user templates and creates the response.
You can either hardcode the specific navigation items in the templates, from which you build the response, or the lit of available navigation items can be a part of the additional information that you requested from model layer.
The downside for this method is, that every time you need, when you need to add another group, you will have to rewrite some (if not all) view classes.
Wrap the structures from model layer in a containment object (the basis of implementation available in this post), which would let you restrict, what data is returned.
When using this approach, the views aways request all the available information from model layer, but some of it will return null, in which case the template would not be applied. To implement this, the list of available navigation items would have to be provided by model layer.
P.S. As you might have noticed from this description, view is not a template and model is not a class.
It really depends on what you're already using and the scale of your project. If you're using a db - stick it there. If you're using xml/json/yaml/whatever - store it in a file with corresponding format. If you have neither - hardcode it. What I mean - avoid using multiple technologies to store data. Also, if the links won't be updated frequently and the users won't be able to customize them I'd hardcode them. There's no point in creating something very complex for the sake of dynamics if the app will be mostly static.
Note that this question doesn't quite fit in stackoverflow. programmers.stackexchange.com would probably be a better fit
In an upcoming project, we will be creating forms for citizen's to fill out to start the process of applying for the requested license or permit. As one can imagine, a form tends to change often. I would prefer to plan this into the application to avoid making changes on a yearly/monthly/"the big boss want's it yesterday" basis.
My searching has shown me some examples based on the object passed to the view, but those would require coding changes. Others use XML, but never seems to go through the entire process from creating the from to storing the inputted data into the database. It isn't that I need hand holding the entire way; it's that this is something completely different for me and I want some guidance to get me in the right direction. I am thinking along the lines of how these survey sites (like SurveyMonkey) create dynamic polls.
Is there any tools, utilities, tutorials, or books that may cover this quite well?
I would imagine you would probably want to take advantage of Display / EditorTemplates. You would define an interface IQuestion or something, and then have a bunch of different form options that implement that interface. So your model would have a List<IQuestion>, and then for each question in the list, Html.EditorFor(item) or so.
Then some kind of standardized way of storing the answers into a table (perhaps a unique save / load method on IQuestion. That's my take anyways. You could define the questions via DB and then your models could have varying counts (and elements) in the List<IQuestion>. Just run a DB script (or some kind of admin page) and you could dynamically change the form displayed.
I just read a blog post that explains MVC with a banking analogy. I have a few months of experience with web application development with an MVC framework (CakePHP), so I get the basics, but I began to see a theme that made me think I'm taking a flawed approach to where I put my logic:
Fat models, skinny controllers
Keep as much business logic in the models as possible
In my app, models are anorexic and controllers are obese. I have all business logic in the controllers and nothing besides associations and validation rules in the models.
Scanning through my controllers, I can now identify a lot of logic that should probably go in a model:
The app has lists, which contain items, and the items can be ranked. The sorting logic which puts the list in ranked order is in a controller.
Similarly, items (Item model) also have images (Image model). Each item may have a default image (designated by image_id in the items table). When an item is displayed with its images, the default image should appear first. I have the logic that does this in a controller.
When a list is displayed, related lists are displayed in the sidebar. The logic to determine which lists are related is in a controller.
Now to my questions:
With the examples I gave above, am I on the right track in thinking that those are instances of logic presently in a controller that belongs in a model?
What are some other areas of logic, common to web apps, that should go into models?
I'm sure identifying this problem and changing my design pattern is half the battle, but even if I decide to take those examples I gave above and try to move that logic to a model, I wouldn't know where to begin. Can anyone point me in the right direction by posting some code here, or linking to some good learning resources? CakePHP specific help would be great, but I'm sure anything MVC will suffice.
It's a bit tough to give you the "right" answers, since some of them deal with the specifics of the framework (regardless of the ones you are working with).
At least in terms of CakePHP:
Yes
Anything that deals with data or data manipulation should be in a model. In terms of CakePHP what about a simple find() method? ... If there is a chance that it will do something "special" (i.e. recall a specific set of 'condition'), which you might need elsewhere, that's a good excuse to wrap inside a model's method.
Unfortunately there is never an easy answer, and refactoring of the code is a natural process. Sometimes you just wake up an go: "holy macaroni... that should be in the model!" (well maybe you don't do that, but I have :))
I'm using at least these two 'tests' to check if my logic is in the right place:
1) If I write a unittest, is is easy to only create the one 'real' object to do the test on (= the object that you are using in production) and not include lots of others, except for maybe some value objects. Needing both an actual model object and an actual controller object to do a test could be a signal you need to move functionality.
2) Ask myself the question: what if I added another way to use these classes, would I need to duplicate functionality in a way that is nearly copy-paste? ... That's also probably a good reason to move that functionality.
also interesting: http://www.martinfowler.com/bliki/AnemicDomainModel.html