I have a question regarding how to populate objects from the Data base, it's more about the architecture than populating it self.
Let's say I have a table called receipts which has: receipt_id, user_id, issue_date, business_id, product_id abd type.
Now I want to create a Receipt class which will be populated from that table, I would do something like this:
class Receipt {
public function __construct($receipt_id = null) {
if(!is_null($receipt_id))
$this->populate($receipt_id);
}
public function populate($receipt_id){
//Get data from data base
}
public function save(){
//Saves the current receipt into the data base.
}
public static function getReceiptsFromUser($user_id){
}
}
My question is about getReceiptsFromUser, should it be static?. It makes sense for the User class to have a method called getReceipts which would return an array of receipts objects calling this static method. I think it should be static because it doesn't make any sense to create an empty receipt to generate the user's receipts. Is there any flaws in this architecture or better aproaches?
Yes, it should be static. As you already mentioned yourself, you don't need a Receipt object in order to retrieve other Receipts.
From the PHP documentation:
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class.
By the way, what you're doing here is called the Active Record pattern. If you're going to use this approach, it's a good idea to create a base class (you can call it Record or something similar) that defines the shared methods (such as save, find, etc.) and let your models extend them (class Receipt extends Record, class User extends Record, etc.). This way, you don't need to repeat this code in all of your models.
A nice (PHP) example for this approach is given by the PHP ActiveRecord project. A look into their documentation should give you some ideas about how it works.
Another approach is the Data Mapper pattern. The benefit is that your models don't know anything about how they're being saved, so you have great flexibility in how you want to persist your data, instead of being tied to the limitations of ActiveRecord.
Related
One of the things that I don't fully understand about the MVC model is loading multiple data tables from the model.
Let's say we have a Model called user.
public class User{
protected $username;
protected $email;
protected $id;
public function setUsername($name, $id) {
$db->set->name($name)
$db->set->id($id)
}
public function getUsernameById($id) {
return $db->get->name($id);
}
As far as I've learned, the model is equivalent to a single row in the database (called user).
Now I have written two functions. The first is for setting the username and the other is for retrieving the username through an ID.
Suppose you want to retrieve all users. Let's say through the getAllUsers() method. This method does not fit on the Model as it is not a single object.
Now I understand that for example, you can call this method (function) in your controller itself. But where can you define this method (function)? Since you don't do this on the model.
I also like to hear it if I am wrong :)
Basically your definition is correct:
Model objects hold data and define the logic for manipulating that
data. For example, a Student object in the Basic sample application is
a model object. It holds data describing facts about the object like
the first and last name of the student and has methods that can access
and change this data (getters & setters). Model objects are not
directly displayed. They often are reusable, distributed, persistent
and portable to a variety of platforms.
(from: http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/mvc.html)
So where to put the getAllUsers() function in case you do not just put it into the model?
Well first of all when we are talking about the term "model" we do not always mean model. In MVC the model (M) contains all of the business logic. This means it contains the domain model which is the model you are meaning in this question. But it also contains the service layer.
The service layer usually consists of various classes which provide functionalities like for instance getAllUsers() or getAllUsersWhichOwnAGreenTruck().
Here is a great graphic demonstrating this:
(Source: Domain Model and Service Layer patterns in P of EAA)
In modern applications e.g. built with the Laravel PHP Framework you usually generate the database as well as the model and the database mapping/communication automatically (Example Eloquent ORM: https://laravel.com/docs/5.8/eloquent). But you start implementing complex application logic within the service layer.
I can't find an answer to this anywhere. I've seen code examples in C# with ASP.NET MVC, but nothing in PHP outside of a CMS or framework.
If I have two tables, students and classes, how do I get that data rendered in the view?
If I query two different tables in one model (same function/method, however), does that somehow violate the principles of MVC? What about 20 different tables? That sounds like a lot of overhead for nothing a one off table you might only query once or twice. Do I really need 20 models?
Can someone please show me this in straight PHP with no frameworks and no CMS?
EDIT: This is for building my own MVC, so "straight" PHP means me building this component.
My approach would probably be to use a repository for classes and users in this case.
StudentRepository
Retrieves instances of students class based on some criteria. This might have a method called getStudentsByClass($classID) that would retrieve the students for a class by it's class id.
SchoolClassRepository
Retrieves instances of a school class based on some criteria. For instance, classes for a semester.
getClassesBySemester($semesterID)
Then in your regular "SchoolClass" class, I would have a function that uses the StudentRepository to retrieve classes for the current class. For instance:
<?php
class SchoolClass(){
private $id;
private $students;
public function getStudents(){
$repo = new StudentRepository();
return $repo->getStudentsByClass($this->id);
}
}
?>
This would mean that your queries to find students for a class would not be exposed in your SchoolClass model. The only thing that the SchoolClass knows about is that the StudentRepository returns the users that it needs.
You would then pass a SchoolClass model as your data model to grab information in your view.
I use Eloquent to implement my models. It has a lot of methods that makes working with models much easier. However, in some cases I have to implement functionality that is accessing the database, but doesn't return an Eloquent model.
For example, imagine a common User model. Eloquent helps me a lot in CRUD operations for the User model, but what if I have to implement a method that returns some statistics about users (ex. how many total users, how many active users, etc.).
Where should I implement this functionality? In the Eloquent model, as a public static function, (e.g. User::getStats()), or should have a different class for this.
It seems a little bit unnatural to have these methods on a Eloquent model, because they are not Eloquent related.
It's really up to you, but it's a good idea to decide on a convention and stick to it.
My rule of thumb is this:
if it's related to a single item that is normally represented by an Eloquent model, do it as a public static method on that model. For example, in my current project, I have a Contract model. I needed a method that would generate a contract ID string (for compatibility with legacy systems) for new contracts. This is related to a single item (a contract) but for technical reasons needed to be generated separately from the Eloquent model (ie. it was based on a separate database with a different connection). So I created a public static method: public static function generateContractIdentifier($id, $salesRep). If you're using a repository for access to your database, you could put it there.
If it's more general (ie. not tied to an instance of the Eloquent model), I put it into a separate library. For example, in the same application I have a queue for processing items for printing (an industrial process). The application has a dashboard and I needed to show the current queue status for management. For this I created a ProcessStatus library and implemented a method: public function getStatus() which runs a query and provides the results as an array for display in a view. This is not related to any particular item in the queue, so I put it in a separate library.
As always, it depends on your project and what role the user plays in it.
But basically, no, I don't think the logic for building reports belongs on the user model. While it may be related to the user, regarding the SOLID-principle the User class should only have one responsibility, which in this case is to handle the User entity.
This contains getting and setting properties on an instance, in a simple project it's probably also fine to define some scopes on the model, e.g. to select only active users, like User::getActive();
But as your project grows, you should consider using more specific classes.
For instance, you could abstract the Eloquent functionality into a User-Repository. So now you have a handler for operations on the entitiy itself, like
$userRepo->getAll();
$userRepo->getActive();
$userRepo->getInactive();
and a handler for a User instance:
$user->getName();
$user->setStatus();
Creating reports and statistics is yet a completely different topic. So you could have something like a UserReportBuilder oder UserStatisticsService:
$userStats->getMostActive();
$userStats->getRegistrationsPerDay();
A simple example:
// UserRepository:
class UserRepository
{
protected $model = $model;
public function __construct($model)
{
// you pass in an instance of the actual Eloquent model
// so you have the whole power of eloquent in here
$this->model = $model;
}
public function getActive()
{
// this returns a collection of models
return $this->model->where('status', 'active')->get();
}
}
$userRepo = new UserRepo(new User);
And that's pretty much it. You can still work with Eloquent, but you have separated the functionality in parts with a clewar responsibility. So your UserStats class would only be resposible for building user statistics:
class UserStats
{
// You could pass in the Repository through the constructor
// or just use the Eloquent model directly
public function getRegistrationsPerDay()
{
return User::groupBy('day')->get(
[
DB::raw('DATE(created_at) as day'),
DB::raw('count(*) as registration_count')
]
);
}
}
The User instance or the UserStats-builder do not need to know how to fetch all users, and the User instance or the UserRepository do not need to know how to calculate registrations per day, so it makes sense to split that functionality into separate, independent parts that do exactly one thing.
I think you get the idea and I hope it makes sense. Maybe you should make yourself more familiar with the SOLID-principles and try to keep them in mind when you get stuck on problems like that.
I'm struggling with this kind of issue and I can't find direct answer to my question through Google.
Let's say we have a table 'users' in the database and it has the following columns: id, username, password, real_name.
Then my problems starts after that.
I know we can make an independent class for that like:
class User
{
private $_id;
private $_username;
private $_password;
private $_real_name;
// getters
// setters
}
Now, should I add functions like fetchById on that class? I mean, is it a good practice?
public function fetchById($id)
{
// validate param
// query database
// copy results to appropriate properties
}
Or should it be done by another class, like UserManager? Then for every result, we convert the array result to of that object?
Also, where should I put functions like fetchUsers where it will fetch multiple users from the database? Functions which deals with multiple records of the same entity.
I am looking for code efficiency and performance.
I know 'some' ideas but I can't justify it. I need help.
I'm currently working with CodeIgniter but I think this problem is PHP OOP in general.
For me personally, I have my models (objects that represent database tables) extend an abstractModel object that has the ID attirbute and shared static functions like fetchById(). This abstract model also has methods like save() which use the ID of the object to save.
You don't have to have an 'id' field in the table, the id of the model just has to be one of the unique key fields in the table.
Instead of fetchUsers() I have a generic loadAll() static function in the abstract class. Thus you could call Users::loadAll() to get all the models of your users. This means that most of your models can be interfaced with in the same way and reduces duplication of code. Of course if there are methods specific to the model, then you will need to define them in child model.
Build a class for table management and another for entity.
see other ORMs like doctrine, propel, or frameworks ORM like cakephp.
I asked this question a while back but now I'm looking to implement an actual separation between my database access layer and the domain layer. I am also going to be working to move business logic into the domain where it belongs and out of the controller scripts.
I'm using Zend Framework which implements the Table Data Gateway and Row Data Gateway patterns for the data access layer, but it apparently fails to really define how to build a domain layer that is separate from the data access layer. I've considered using an Active Record pattern where the domain logic coexists with the data access logic, but I have the following situation that occurs at least once that I don't think Active Record will handle:
I have a single table "Person" which contains person_id and userType fields.
Each userType (admin, buyer, associate, supervisor) has specific business logic associated with it and all types inherit some basic functionality from a Person object.
I don't want to bloat the Row Data Gateway object with business logic that belongs specifically to just one type of user but I'm not certain how to construct the domain layer to represent the different types of users. For example, do I make a Person object that contains the PersonGateway object and then write wrapper functions that pass calls to the gateway object, or do I write the Person object to extend the PersonGateway object and then only implement the specific functions that I need?
Likewise, I would typically think that this is (in part) a factory problem where I need a factory method that will instantiate the correct sub-class based on userType. Is that still the best method here with Zend Framework's Zend_Db class?
Any suggestions or links to tutorials that talk about how to properly create a domain model on top of Zend_Db would be greatly appreciated.
Domain Models extend nothing. They're just plain classes you use to encapsulate business logic. They may use data access objects, so there may be a protected instance of a row data gateway object inside the class. A Row object usually represents an instance of the domain more closely than a Table object. Besides, you can always get the Table object with the Row's getTable() method.
Typically DM classes have an interface with methods corresponding to higher-level operations you can do with that class. But you don't necessarily want to surface all data access operations.
class Person {
// Zend_Db_Table_Row object
protected $data;
public function subscribeToService(Service $service) { ... }
public function sendMailTo(Person $recipient) { ... }
public function changePassword($newPassword) { ... }
}
I also blogged about this subject last spring, and wrote about it on the ZF mailing list recently.
As far as tutorials and resources, try http://domaindrivendesign.org/