Good Practices MVC - php

Assume I had a database with two tables:
customer
payment_info
The table customer had fields: name, address, payment_info_id
payment_info_id is a foreign key that links to a row in payment_info. payment_info has fields: id (which is linked to payment_info_id), bank, account number.
Because of my application's logic, each time a customer is created their payment information is stored in a separate row in the payment_info field which is linked to their row in the customer table.
I am using an MVC architecture.
Does it make more sense to keep this 'pure' and make two separate models, one for each table, and then crossload them and call methods from payment_info_controller in customer_controller, or to make a hybrid one which as soon as it creates a row in customer also creates one in payment_info?
Hope this makes sense!

You shouldn't be relying on controllers to do this. Put the logic in your model, behind a service layer(if desired), and call that from your controllers.
You should also reverse the FK setup. Stick customer id in payment_info and remove it payment_info_id from customer. That will make it so a customer can have multiple payments.
in the controller:
$user = new User(name, etc...);
$payment = new Payment(payment details...);
$user->applyPayment($paymentInfo);
$userService->save($user)
in the service:
function save($user){
//save user and update it with an id)
$user = $userDal->save($user);
//now that user has an id, you can generate/save payments.
$payment->save($user->getPayments());
}
You could then have the userService load the Data access layer for both user and payment.
Service/Facade info: http://www.dofactory.com/net/facade-design-pattern
NOTE: - you might want to come up with a better naming convention so its obvious that the payment will be saved/generated by that particular service. e.g SaveUserAndPayment($user)

Always keep it pure you dont need more unused methods to load than you could also from customer you do stuff while you have some customer params and need get something related to it, from payment you do stuff when you have some payment params and need dig something from that. You can always use payment or customer or any other models from any controller so keep it as pure as you can gl and hf ;)

Related

Multiple Projectors on same ReadModel in Broadway CQRS

I have a Customer Readmodel that contains some properties including an active property.
Now suppose I would want to fill 2 tables with customer information: for example, one table with just the customer id and active status, and another table containing all info.
Should I make a seperate Projector, Readmodel and Repository to achieve this?
EDIT:
Example scenario:
CustomerCreatedEvent -> contains all customer data
CustomerActivatedEvent -> only contains customer id with enabled status = true
Readmodel = Customer class
A Projector handles both events.
The CustomerActivatedEvent handler will load the customer and update the 'active_users' table through the CustomerRepository (or ActiveCustomersRepository?) based on the data in CustomerActivatedEvent.
No.
The event handlers of your read-side are the ones responsible for updating what you call Readmodels the way you want.
For instance you can have a CustomerCreatedEventHandler which updates the 2 tables you need, or you can have two separate event handlers, both subscribers of the same event, each one updating a different table.

Data model for subscriptions, single purchase products and variable services

I am designing a database for a system that will handle subscription based products, standard one off set price purchase products, and billing of variable services.
A customer can be related to many domains and a domain may have many subscriptions, set priced products or billed variable services related to it.
I am unsure whether to seperate each of these categories into their own 'orders' table or figure out a solution to compile them all into a single orders table.
Certain information about subscriptions is required such as start date or expiry date which is irrelevant for stand alone products. Variable services could be any price so having a single products table would mean I would have to add a new product which may be never used again or might be at a different cost.
What would be the best way to tackle this, and is splitting each into seperate order tables the best way?
Have you looked at sub-typing - it might work for you. By this I mean a central "order" table containing the common attributes and optional "is a"/one-to-one relationships to specific order tables. The specific order tables contain the attributes specific only to that type of order, and a foreign key back to the central order table.
This is one way of trying to get the best of "both" worlds, by which I mean (a) the appropriate level of centralisation for reporting on things common and (b) the right level of specialisation. The added nuance comes at the cost of an extra join some times but gives you flexibility and reporting.
Although I am a little biased in favour of subtypes, some people feel that unless your order subtypes are very different, it may not be worth the effort of separating them out. There is some seemingly good discussion here on dba.stackexchange as well as here. That being said, books (or chapters at least) have been written on the subject!
As with any data model, the "best" way depends on your needs. Since you don't specify a lot of details regarding your specific needs, it's difficult to say what the bets model is.
However, in general you need to consider what level of detail is necessary. For example if all subscriptions cost the same and are billed on the 1st of the month, it may be sufficient to have a field like is_subscription ENUM ('Y', 'N') in your orders table. If billing dates and prices for subscriptions can vary however, you need to store that information too. In that case it may be better to have a separate table for subscriptions.
Another consideration is exactly what an "order" represents in your model. One interpretation is that an order includes all the purchases included in one transaction, including both one-off purchases, variable services and subscriptions. A completed order would then result in a bill, and subscriptions would be automatically billed on the proper day of the month without a new order being made.
You should aim to have one database design that is not hardwired into specifics regarding its contents, and if it does (have to) it does in such a way that it seperates the specialization from the core DB design.
There are certain fields that are common for each order. Put these in one table, and have it refer to the other rows in the respective (specialized) tables. Thats DB normalization for you.
You could have main table contain ID, OrderID, ItemType, ItemID when ItemType determines the table ItemID refers to. I advise against this, but must admit that i use this sometimes.
Better would be to have these tables:
Clients: ID, Name, Address, Phone
Sellers: ID, Name, CompanyAlias
Orders: ID, ClientID, SellerID, Date, Price
OrderItems: ID, OrderID, DiscountAmount, DiscountPercentage,
ProductDomainID, ProductBottleID, ProductCheeseID, ..
Now OrderItems is where the magic happens. The first four fields explain themselves i guess. And the rest refers to a table which you do not alter or delete anything ever:
Products_Cheese ID, ProductCode, ProductName, Price
And if you do need a variant product for a specific order add a field VariantOfID thats otherwise NULL. Then refer to that ID.
The OrderItems table you can add fields to without disturbing the established DB structure. Just constrict yourself to use NULL values in all Product*ID fields except one. But taking this further, you might even have scenario's where you want to combine two or more fields. For example adding a ExtraSubscriptionTimespanID or a ExtraServicelevelagreementID field that is set alongside the ProductCheeseID.
This way if you use ProductCheeseID + ExtraSubscriptionTimespanID + ExtraServicelevelagreementID a customer can order a Cheese subscription with SLA, and your database structure does not repeat itself.
This basic design is open to alterative ideas and solutions. But keep your structure seperated. Dont make one huge table that includes all fields you may ever need, things will break horribly once you have to change something later on.
When designing database tables, you want to focus on what an entity represents and having two or more slightly different versions of what is essentially the same entity makes the schema harder to maintain. Orders are orders, they're just different order types for different products, for different customers. You'd need a number of link tables to make it all work, but you'd have to make those associations somehow and it beats having different entity types. How about this for a very rough starting point?
What would be the best way to tackle this, and is splitting each into seperate order tables the best way?
That depends. And it will change over time. So the crucial part here is that you create a model of the orders and you separate the storage of them from just writing code dealing with those models.
That done, you can develop and change the database structure over time to store and query all the information you need to store and you need to query.
This for the general advice.
More concrete you still have to map the model onto a data-structure. There are many ways on how to solve that, e.g. a single table of which not all columns are used all the time (flat table), subtype tables (for each type a new table is used) or main table with the common fields and subtype tables containing the additional columns or even attribute tables. All these approaches have pros and cons, an answer here on Stackoverflow is most likely the wrong place to discuss these in full. However, you can find an insightful entry-level discussion of your problem here:
Entity-Attribute-Value (Chapter 6); page 61 in SQL Antipatterns - Avoiding the Pitfalls of Database Programming by Bill Karwin.

How do you setup relationships with many foreign keys from the same table in PHP ActiveRecord?

I am building a real estate related website that real estate agents and investors can use to track properties submitted in the system and keep track of who is owed what profits. I have the following tables that I am having trouble figuring out how to setup the relationships for in my models using PHP ActiveRecord:
properties
id
primary_profit_sharing
secondary_profit_sharing
commission
referral_payment
users
id
name
email
payments
id
type (commission, referral_payment, etc.)
property_id
user_id
What is the proper way to setup these relationships using PHP ActiveRecord? I would like to be able to access the user information for each payment by something like $property->commission and $property->referral_payment but I can't figure out how to setup the relationships in the models to allow that.
I currently have payments belonging to users and properties, and users/payments have many payments. All the information I was is returned in the query, but not in an accessible ways. I have $property->users but no way of getting the user information for a particular payment type.
The only way I can think of to accomplish what I'm looking for is to setup a table for each payment type, but that doesn't seem like the best way to do it.
In the payments table, instead of using property_id and user_id, maybe you should use fk_object as the foreign key and do your joins using that field. fk_object represents the id of the user or the id of the property.

Should dependent rows be fetched in the Model or the Controller?

Let me start with a simple example to show how my data is structured. There are four tables, Employee, Store, Department, and Employee_Department_Permissions.
Departments belong to Stores (for example, the Department table might contain a record for the dairy department of store 5). Employees are given the right to work in Departments through the Employee_Department_Permissions table, which contains the Employee id and Department id.
Let's say an employee can log in to my application and view a list of every store in the database. Next to each store, I want to print out how many departments they can work in at each store. I have an Employee model with a mapper that provides the fetchAll method to accomplish the first part.
But, where should I find out how many departments an employee can work in? In my model wrapper, I can call findDependentRows to do this. Or, I could do it in my controller with raw Zend_Db_Select calls. A third option I was considering would to be just add a column to the Employee table that holds this information, but then I'd need to update a second table when Employee_Department_Permission is modified.
Thank you in advance for any advice.
As a very general rule of thumb, I would suggest you try keep the controller as free as possible from fetching information for the views. This is a task best handled in the model.
Sure it's easy to just fetch from controller, I mean, since we are there processing a request, it would be so simple to just do a quick fetch and push that off to the view. This is where dicipline comes into play. As your application grows you will appreciate having the clean separation this methodology offers you if applied.
My 2 cents, happy coding to you friend.

CakePHP - conditions on associated model

Problem in short: I want to set
conditions on an associated model. How
do I do it?
I'm having a problem with the associations in my CakePHP application.
The associations looks like this:
Event has many EventSum belongs to Account has many AccountUser belongs to User
Event has many EventDebt ... (the rest is the same as above)
Event also belongs to User
The application is a private econonmy program in PHP and uses the CakePHP framework.
An Event is a financial event, a purchase, transaction between accounts etc. It only holds information about date, title and user.
An EventSum holds information about an Account and how much to debit or credit (in one column, just positive or negative).
Account holds information about title of the account.
AccountUser holds an id of an Account and a User. This indicates that
So, now I want to fetch Events based on what accounts a User is associated to. How can I do this?
I want to fetch the following info:
Event, together with the EventSum. The Events are fetched from Accounts where the User has access.
Thanks for any help,
/Magnus
It seems like you want to be able to query your Event class with the following conditions:
'Account.user_id =' => $userId
Is my assumption correct?
When doing queries which require conditions on associated models, you can use either the Containable behaviour (comes with CakePHP 1.3) or the 'Linkable' behaviour (which can be found here).
What happens when you try this (be sure to attach the Containable behaviour to your models first):
$condition = array('Account.user_id =' => $userId);
$contain = array('EventSum' => array('Account'), 'EventDebt' => array('Account'));
$result = $this->Event->find('all', compact('condition', 'contain'));
Note that you might experience issues when 'containing' both EventSum and EventDebt if both of their associations to Account use the same alias name.

Categories