I have three classes to define objects: Users, Members and Projects.
The User class defines details such as id, email_address and
name.
The Member class defines details such as the id, user_id,
project_id and datetime_accepted.
The Project class defines details such as id and title - this
isn't important though.
The system has Users and Projects. A Member is a User working on a Project. In other words, the Member class defines a link between two objects.
My question is this:
I want to get a list of members belonging to a certain project, and I want to collect variables from both classes (Member and User - such as User:name and Member:datetime_accepted) in my result set.
Do I need to define a new class that has all the variables from both classes, or is there some other, more efficient structure that I can use to handle this neatly and in an object oriented manner?
You can easly cast StdObject into array by:
$result = array_merge((array)$user, (array)$member);
then you will have an array of variables you need. Add this to new function in Project class,
or consider using Member as child of User class.
When working with Active Record Models, you would generally have a method in one object to get related objects. If you wanted to simplify the SQL to one query, you're getting away from the Active Record Model. This is fine, it just changes the way you approach the problem.
What I have done in the past is one of two approaches:
To add 'virtual properties' to an AR, for example, my Login (User) class has a property "Roles" which is populated by a JOIN in its standard loading query.
To create a Report object which I extend for more complex situations. The Report subclasses have a property that is the multi-table query, and other properties which represent parameters for the WHERE clause. The class produces an array of arrays.
What I ended up doing to solve this issue was to create a Project and a User object inside the Member. The objects were created when the member was constructed. Works okay.
Related
I'm currently working a tournament organization project, I would like to what's the best technique to have different implementation for the same model, for example I have model called matches, than retrieves data related to matches, but these matches may have different types depending on match_type field specified in matches model, what I did is creating parent class /Match , and having different types of matches extend this parent class. Ex:
Class SinglElimination/Match extends /Match{}
Class GroupStage/Match extends /Match{}
so with this design I have to get the parent match first to get the match_type then re-run the query to get a match with the needed child model
$match=Match::find($id);
$type = $match->match_type;
$childMatch = new $match_type.'/Match'();
$match = $match->where('_id', $this->_id)->first();
which I know is nowhere near clean, so how would you implement this ?
If I were you I would separate those 3 classes and exclude any extending. Take a look at Polymorphic relationships in Laravel, here is the quick link. It will be a cleaner approach and in my opinion it would be the best approach here, all you'll have to do is design the tables properly and do relationships properly too.
Lets say that i have an aggregate root named User the user can have multiple Vehicle, the Vehicle entity has types such as (suv, truck, sedan, etc ...).
In that case if i want to get the User vehicles of type sedan only do i have to design my aggregate to get the sedans directly from the aggregate like User->getSedans() ?
Or can i get that throw the UserRepository->getVehiclesOfTypeSedan() and the aggregates only hold the Vehicles ?
To keep your interface and inheritance hand in hand, I think it is better to separate your logic:
UserRepository->getVehicles("sedan");
Or you can utilize method-chaining:
UserRepository->getVehicles()->sedan;
In the above code, getVehicles(), returns a collection object which has NOT a property named sedan.
You have to use php __get() to do the operation.
Why then I do this? Because if you were able to fetch the cars by type though a property (remember properties are not functions, there is no execution), then it literally means that you have fetches all types and have them ready:
WRONG WAY AND MEMORY-KILLER APPROACH is that you fetch all of the user's car and put each type in its associated property.
Better way is returning an object, the object then is shipped with a function __get() to be invoked on each property retrieval:
$object->sedan;
sedan does not exist, so you have already predicted that:
function __get($param)
{
$this->__getByType($param);
}
Though I prefer my very first suggestion.
I'm not sure if I'm using the MVC architecture correctly so go easy on me if I'm going wrong.
I have a model Account that grabs a load of valuations from a Holding model. These 2 models are linked as Account hasMany Holdings.
In my Account model I have a function that retrieves the sum of the holdings from the account and arranges it in a $date=>$value type array.
I have another, separate, model called FxRate whose table is a load of FX rates and dates. In my Account model I want to retrieve an array of fx rates by running a find on the FxRate table so I can convert the valuations array I retrieved earlier.
FxRate is not linked to either of the other models and I can't seem to find any data from it from within my Account model. What's the correct way to achieve this?
If you are in your Model file you can use this:
App::uses('FxRate', 'Model');
$FxRate = ClassRegistry::init('FxRate') // and not $FxRate = new FxRate(), see comments;
$FxRate->find('all');
in your controller instead you can use loadModel
$this->loadModel('FxRate');
$this->FxRate->find('all');
Recently started working with OOP in PHP. Following the "code to an Interface" principle, i got confused as to the type hint to use when passing a single object or multiple as argument to a method.
Currently, i have a "Student" class - represents a row in my students table, i also have a "Students" class that holds multiple student objects in an array.
To fetch the profile of one student, i pass the Students object (holding a single student object) to the profile class. I set a Students type hint in the profile class.
Now i feel this is bad code as i have lines like this
student = new Students();
and students = new Students();
question is,
am i on the right path?
if i remove the Students class and work with Student alone, based on the principle, how do i pass multiple Student objects (assuming array) to the profile class if it accepts a Student type hint?
what options do i have?
Thanks.
If by Students you mean a collection of Student objects, perhaps a better name would be StudentCollection or StudentSet.
There are two ways around the type hint problem:
Introduce a method on StudentCollection called ->getProfiles(); it would return an array of profiles for each Student instance it's managing by calling methods on Profile.
Introduce a (static) method on Profile that operates on a StudentCollection instance.
The first option has feature envy, which is why I've included a workaround.
Instead of reinventing the wheel you might want to try Doctrine or at least take a look at its architecture.
I'm not sure if I get your exact issue... But if you want to go for your own code I would first abstract the DB layer as well and have some base classes like Database, Table, Row, Field that an describe the DB stack and extend them as needed with some magic methods. So when you do Student extends Table it would automatically check for a "students" table or whatever else convention you like to implement. Alternatively you could just pass the table name as arg.
Whatever Object is returning the result set from the database would have to construct a single Row object for each row and add it to a collection of rows that I would name ResultSet and contains all the row objects and return that collection.
I have an object model that contains a class with several subclasses.
The subclasses share a few fields from the parent, but they each have
their own fields as well.
I'm using the column_aggregation inheritance type to do this because I
want to be able to polymorphically store objects of the parent class
type, but retrieve objects of the subclass types.
So far, I can retrieve the objects with their subclass types intact.
My problem is that when I call getColumns() on any of the subclass , I
get all the fields for the aggregated table, so I see every field from
all the subclasses together.
Is there a way to only get the fields that actually belong the
subclass?
Design-wise the output of getColumns() is correct (it merely returns all columns of the aggregated table). I think Doctrine_Table->getColumns() is oblivious to the fact that the table in question has sub-classes. Try to use Doctrine_Table->getColumnDefinition() or as a last resort Doctrine_Table->getColumnOwner($column) to infer which columns belong to which sub class.