I have a User model, with properties (id, username, email, password) and methods (is_unique, get_by_id, save).
As I understand the MVC pattern, my User model has to represent one given user.
So, if I want to get a list of all users, should I implement a method for this in User model, or in a controller?
You would have to build a UserCollection model, containing a collection of User models if you want to do it the proper MVC way. Your controller can never interact with the database directly, hence why we have to create a model ;)
You should make a model class which represent a list of users, e.g. UserList.
Neither of both.
Create a new Model called something like userbaseor clientbase and use it to list users by criteria, retrieve information about your users in general (count, top 10, user of the month, etc...) and for operations that affect a group of users (that may have no direct relation one to another) like building a certain demographic collection of users to send them a mail.
Cheers
Related
I know this is a duplicate question but i think it will help others because there are a lot of similar apps that have these kind of table relationships:
So the question is what would be the optimal solution for all relationships in this schema using the Eloquent?
How many Models and Controllers to make?
First of all, you need to understand that not all tables in a database represent an entity.
For example, tables like users, posts, comments are entities. Whereas posts_users, comments_posts are not: they are here for technical reason, to materialize the relation between 2 entities.
Only entities need a model: it makes no sense to have a model for a relation table.
Even if a table holds information like date_created, it does not make it an entity. This is just a data related to the relation. For example, the table users_roles may have a column named date_assigned, to know when a given user was assigned a given role. It's not entitity for all that.
Second, you need to understand what a controller is for. The role of a controller is to handle a request and provide a result. Result can be a view, an error (HTTP 404), or just the fact that an action has been successfully done.
You must also make the difference between the class called Controller (or any child that extends this base class) and an actual controller. The actual controller is the code that will handle the request. A Controller class can have more than one method to handle requests.
It's all a question of organization: generally, Controller classes are used to group methods within the same scope: user login, logout, subscription, password reminder are all the same scope. All these controllers could be in different classes or functions. It does not matter. Each method is a controller. They are grouped in the same class because they have the same needs (check user is logged in, to know if login is required, if subscription page can be displayed, etc.) and they are in the same scope, which just make sense when you think of it. That's just logical: you know where to search when you need to change something about user identification (even if you are new on the project).
So you need a model for these entities:
User
Offer
Invoice
Category
The controllers you'll need depends on what you want/need to do with this data. There's no ready-to-use answer to this part of your question.
Use a Controller class for:
user authentication (if you need some)
user management (backoffice)
invoice management (edit, mark paid, list of late payments, etc.)
categories management (create, edit, delete)
offers management
But depending on your application, you may need more. Only you can really say. There's no bad answer to this question: if you think some controllers should be separated for better organization, do it. If you think you should group 2 or more, do it. There's no rule. You have to keep your code clear and well organized. It must suit your needs. That's all.
I have an application that has only two tables: products and type - where each product can have multiple types as attributes. I decided to normalize the database and created another table where I intend to keep the relations between the products and types.
(Disclaimer: I'm relatively new to object oriented programming). I have a class for products, and a class for types. I have been told that I should have a class for every table that I have in the database. Does this also apply to a table created for normalization purposes? If so - what is the best way of dealing with this - should I somehow call both other classes in this third class, or keep it an independent class, and just manage the exchange of information through actual forms on the webpage, etc?
If your product_types table only holds foreign keys there is no need to map it to its own class. Since this is defining a many to many relationship between the tables you can just provide a method in your product class to get the types.
getTypes() {
// retrieve the types for this product and return
}
Then add the opposite method in the types object to get the products.
getProducts() {
// retrieve the products for this type and return
}
I have been told that I should have a class for every table that I have in the database. Does this also apply to a table created for normalization purposes?
Usually when you're designing a database, the first thing you need to do is create a conceptual data model. This will allow you do define your entities as well as defining relationships between them. Then you create a logical data model to characterize and refine your entities. The last step is the physical data model, which is the closest model there is to a database. Now in this model your entites are now tables, and some of them may or may not relate to your application domain.
For example you could have a travel agency application, where you'd have tables for destinations, flight companies etc... These would map directly to your application because they represent concrete classes. On the other hand you'd also have configurations, sparse data (billing...) or associative tables (like you have here). They don't map to your current application. This concept is called impedance mismatch. See this diagram I found online :
Finally to answer your question : no you don't need to map it to a class, because it has nothing to do in the application domain. Of course you still need to handle it some way (using DAO and SQL basically). You could also use an ORM, like suggested in the comments by #RobW, which can abstract and map directly your database.
All,
Building a small web app using PHP. I don't have much programming experience.
In my app, I have created a class to access DB records which I call DAO_DBrecords. The class includes basic functions to create new records, update existing records, etc. Currently, the class satisfies all my DAO needs for all my DB tables. In the functions, I pass as one of the argument a string that represents the DB table (users, articles, etc).
At this point I could do either of 3 things:
Use this class throughout my program whatever the type of record (i.e., table) I'm dealing with.
Create specific classes for each type of record (e.g., DAO_Users), which inherit from DAO_DBrecords but are otherwise empty.
Create specific classes for each type of record (e.g., DAO_Users), which inherit from DAO_DBrecords and specify the DB table the class can access via a variable (e.g., private $table = 'users'). In the parent class, the variable would be null, or an empty string.
Again, at this point I am not envisioning the need for table specific functions (but that might change).
Which of those (if any) is the right approach?
Thanks,
JDelage
Edit: I have edited option 3 which previously read:
3. Create specific classes for each type of record (e.g., DAO_Users), which inherit from DAO_DBrecords and specify the DB table the class can access via a constant (e.g., const TABLE = 'users'). In the parent class, the constant would be null, or an empty string.
I will choose the 3rd option. In DAO_Users you can eventually put methods to do specific things on the user record itself (for example, create and store a salted password, send verification email, fetch all user's friends from the database as DAO_Users collection, fetch all user's comments, etc).
In this way you can both use a DAO pattern and organize all app "actions" in classes by action target.
Let's say I have three tables: users, books, and users_books.
In one of my views, I want to display a list of all the books the current user has access to. A user has access to a book if a row matching a user and a book exists in users_books.
There are (at least) two ways I can accomplish this:
In my fetchAll() method in the books model, execute a join of some sort on the users_books table.
In an Acl plugin, first create a resource out of every book. Then, create a role out of every user. Next, allow or deny users access to each resource based on the users_books table. Finally, in the fetchAll() method of the books model, call isAllowed() on each book we find, using the current user as the role.
I see the last option as the best, because then I could use the Acl in other places in my application. That would remove the need to perform duplicate access checks.
What would you suggest?
I'd push it all down into the database:
Doing it in the database through JOINs will be a lot faster than filtering things in your PHP.
Doing it in the database will let you paginate things properly without having to jump through hoops like fetching more data than you need (and then fetching even more if you end up throwing too much out).
I can think of two broad strategies you could employ for managing the ACLs.
You could set up explicit ACLs in the database with a single table sort of like this:
id: The id of the thing (book, picture, ...) in question.
id_type: The type or table that id comes from.
user: The user that can look at the thing.
The (id, id_type) pair give you a pseudo-FK that you can use for sanity checking your database and the id_type can be used to select a class to provide the necessary glue to interact the the type-specific parts of the ACLs and add SQL snippets to queries to properly join the ACL table.
Alternatively, you could use a naming convention to attach an ACL sidecar table to each table than needs an ACL. For table t, you could have a table t_acl with columns like:
id: The id of the thing in t (with a real foreign key for integrity).
user: The user the can look at the thing.
Then, you could have a single ACL class that could adjust your SQL given the base table name.
The main advantage of the first approach is that you have a single ACL store for everything so it is easy to answer questions like "what can user X look at?". The main advantage of the second approach is that you can have real referential integrity and less code (through naming conventions) for gluing it all together.
Hopefully the above will help your thinking.
I would separate out your database access code from your models by creating a finder method in a repository class with an add method like getBooksByUser(User $user) to return a collection of book objects.
Not entirely sure you need ACLs from what you describe. I maybe wrong.
I have a domain for users that connects to my user table, which includes information like username, first name, and last name.
Then I have a domain for emails, that connects to the email table because a user can have more than one email. The email table consists of a fk to connect the user with their emails, and other fields like address, status, etc.
Should I have different domains for the separate tables, but combine functions, that call the domains, in the models? Or maybe you can but it's not best practice.
I am new to this MVC thing and it's hurting my brain right now. Maybe, it just someone hasn't explained it well enough.
Question: when you mention having a "Domain", are you referring to a User model, and an Email model? or to the design pattern?
Also, initially (but depends on your application) having the email database logic inside the users model is more logical (to me), since I don't think you are going to add email addresses without creating a user. That is, the email model really depends on the user model, and perhaps only on the user model, so maybe they should be combined?
The way I would do it:
Put all the database logic inside the models which I assume is the way you have done it.
Create a library or class to place the business logic of the application that concerns users. (For example, uploading an image, or connecting to a web service, should not be in the model if you follow the standard that CodeIgniter models should only contain database logic, so that's why I create another class to handle those cases)
Now, when you want to create an user, you just inject the models in the library (you could do this at the controller level), and call your abstract method create_user()
class Users extends Controller {
public function create() {
// these could be in the constructor!
$this->load->model('users');
$this->load->library('users_logic');
$this->users_logic->set_model($this->users);
// and/or: $this->users_logic->set_email_model($this->email_model);
if ($this->input->post('name')) {
$this->users_logic->create();
}
}
}