PHP MVC: Multiple databases, multiple data mappers? - php

I am working on my HMVC project.
Right now I am using data mappers in order to move data between the models (domain objects) and a MySQL database. Each mapper receives a MySQL adapter as dependency. The injected adapter receives a PDO instance (a database connection) as dependency and runs sql queries on the database.
I also use a dependency injection container (Auryn).
I'd like to be able to simultaneously retrieve data from storages of different types (MySQL database, PostgreSQL database, XML feeds, etc).
Let's say, I want to retrieve User data from a PostgreSQL database (by using PDO data-access abstraction), to change it, and to save it into a MySQL database (by using mysqli data-access abstraction) on another server. So, there will be different data-access calls for the both database types.
My question is:
Should I create a different mapper for each storage type, like
UserMapperPgsql(PgsqlAdapter $adapter)
UserMapperMySql(MySqlAdapter $adapter)
, or should I create only one mapper with more adapters (one for each data type) as dependencies, like bellow?
UserMapper(PgsqlAdapter $adapter1, MySqlAdapter $adapter2, ...)
Thank you all for your suggestions!

What an odd project you have there.
Anyway. I would go with two separate mappers for separate storage mediums. Because trying to juggle those adapters inside a mapper might end up quite complicated.
That said, depending on how complicated the persistence logic actually ends up, you might benefit from looking up repositories as approach to streamline the API, that gets exposed to where your "application logic" is actually done.

Related

Native DB queries in a Domain Model MVC

I have a built an MVC application with a model layer containing entities, data mappers and service classes. So far so good. But now I have a controller that need to show a report containing data from multiple db tables with no relation to any entities in my model. The report is built from a advanced MySQL query containing joins, SUM/AVG-selects. All I want is an array of the data so be shown in the VIEW.
Can I mix methods in my service layer, some that returns entities ("getById()") and some that just returns array of data from my database query ("getAdvancedReport()")?
Is it OK to put the db-queries right in the service layer? If not, where should they go? The data mapper feel wrong because its job is just to map my entites to the db, not to retrieve custom data.
Maybe just "Coding bureaucracy" but i need to do this right.
Cant find anything on the net other than simple CRUD examples of the domain model.
Not really an answer .. more like pontifications with bottle of beer
You seem a bit confused about the point in having data mappers and even about domain object in general.
Data mappers are responsible for the information exchange between storage (which sometimes is an SQL database) and domain object. If you have even a bit normalized DB structure, the database entities and domain objects will not map 1:1. Mappers are made for specific domain object , not for the database tables. A single domain object can even have multiple mappers (for example: one mapper which stores data in DB, and one in session).
If your Report object has no domain logic, you can even use an active record. The pragmatic approach is to use them when the potential domain object has only CRUD with no domain logic. If there is some computation, stick with domain object + data mapper pair.
Service layer is for application logic, not storage logic. There should be no SQL in it. Service should mostly be governing the interaction between undetermined mix of domain objects and mappers. With the exception of mailing services and similar structures.
Also, usually on-line reports are dynamic. You can order the data, filter it and otherwise manipulate. You would end up with a service, which can manipulate the Report object, apply filter to it or extract data from said object. All this tinkering is "application logic".
that's it ... I run out of beer
Can I mix methods in my service layer, some that returns entities ("getById()") and some that just returns array of data from my database query ("getAdvancedReport()")?
Yes, but I would correct your sentence as such: some that returns entities and some that just returns array of data
=> the user of the service doesn't care where the entity/data comes from. So, yes your service can return entities and raw data (array of primitive types).
Is it OK to put the db-queries right in the service layer?
No
If not, where should they go?
In the Repository/DAO. It is OK to perform native queries in the Repository. And the Data Mappers are not used here, simply because we don't need to map entities.
To sum up:
Service->getMyData() > Repository->getMyData() > DB query
Is it OK to put the db-queries right in the service layer? If not,
where should they go?
DB queries should be always placed in data-mapper, because "Service" shouldn't know, where are data from.

in Zend, Why do We use DB Model class and Mapper class as two separate?

I am working on the zend project, I am referring on other zend project to create the new Zend Project.But I don't like to blindly follow that project without understanding. In the Zend Directory structure, In Model class there are mainly two type of classes I see, like as in
- models
- DbTables
- Blog.php //Extends Zend_Db_Table_Abstract
- Blog.php // Contains methods like validate() and save()
- BlogMapper.php // Also Contains methods like validate(Blog b) & save(Blog b)
Why this specific structure is followed?
Is this is to separate Object class and Database model class?
Please explain.
DataMapper is a design pattern from Patterns of Enterprise Application Architecture.
The Data Mapper is a layer of software that separates the in-memory objects from the database. Its responsibility is to transfer data between the two and also to isolate them from each other. With Data Mapper the in-memory objects needn't know even that there's a database present; they need no SQL interface code, and certainly no knowledge of the database schema.
How you store data in a relational database is usually different from how you would structure objects in memory. For instance, an object will have an array with other objects, while in a database, your table will have a foreign key to another table instead. Because of the object-relational impedance mismatch, you use a mediating layer between the domain object and the database. This way, you can evolve both without affecting the other.
Separating the Mapping responsibility in its own layer is also more closely following the Single Responsibility Principle. Your objects dont need to know about the DB logic and vice versa. This gives you greater flexibility when writing your code.
When you dont want to use a Domain Model, you usually dont need DataMapper. If your database tables are simple, you might be better off with a TableModule and TableDataGateway or even just ActiveRecord.
For various other patterns see my answer to
ORM/DAO/DataMapper/ActiveRecord/TableGateway differences? and
http://martinfowler.com/eaaCatalog/index.html
The idea of a Model is to wrap up the logical collection of data inside of your code.
The idea of a DataMapper is to relate this application-level collection of data with how you are storing it.
For a lot of ActiveRecord implementations, the framework does not provide this separation of intent and this can lead to problems. For example, a BlogPost model can wrap up the basic information of a blog post like
title
author
body
date_posted
But maybe you also want to have it contain something like:
number_of_reads
number_of_likes
Now you could store all of this data in a single MySQL table to begin with, but as your blog grows and you become super famous, you find out that your statistics data is taking an awful lot of hits and you want to move it off to a separate database server.
How would you go about migrating those fields of the BlogPost objects off to a different data store without changing your application code?
With the DataMapper, you can modify the way the object is saved to the database(s) and the way it is loaded from the database(s). This lets you tweak the storage mechanism without having to change the actual collection of information that your application relies on.

Should I be making this a model?

I have a family of complex select queries which I need to call from different parts of the application. I think I should group them all into a model class, but would like to verify this.
The queries all work off the same set of 5 tables. Each of these tables has its own Table Data Gateway class and Row Data Gateway class, but my new class for the queries would not be implementing any such pattern (since it doesn't wrap a table or row). My new class would be calling on the Table and Row Data Gateways already established.
In addition, the values that come from users can't be susbstituted into the queries directly, so I plan to do some pre-processing in the new class as well. This pre-processing includes accessing the DB for lookup values, etc.
Does this sound fair? I think it's exactly how models should be used, but I can be spectacularly wrong about such things so would appreciate any comments or advice. (FYI, I'm using Zend Framework).
Queries don't go in the Model part. They are persistence related (the model doesn't handle persistence).
These complex queries should be in the Persistence layer, which is here the Table Data Gateway classes.
I would name the Table Data Gateway classes "DAO" (Data Access Object). A Table Data Gateway is a kind of DAO, since you can have a DAO that help you get things from files, webservices...
So you can keep your actual classes, and add a DAO to manage these complex queries. This DAO is not providing you access to a specific DB table, but it is still providing you access to a data source (composed by several DB tables).
Edit :
I suggest you to create a DAO interface (it may be empty). You DB Tables will implement this interface. Your new class will also implement this interface, but not extend Zend_Db_Table.
In short, you are redefining/renaming your persistence layer, from "Zend Db Table" to "DAO" (which makes it more generic). Zend Db Table is a kind of DAO.

PHP database abstraction: Define the model once, generate the code but deal with plain data instead of active record objects

I am searching for a database abstraction layer in future PHP projects. Until now I have worked with plain SQL-commands and arrays on the one hand fully featured ORMs like Doctrine on the other hand.
I don't like ORM because most of the time the job is to get a list of data from the database and to send it to the template engine. Both work fully fine with arrays and there's no need to make it all complicated by capsule the data in an object when the template just needs the plain array. I don't like the plain-SQL approach either because for the simple CRUD stuff I have to write everything myself and also I don't like to maintain two models of my data (one in the DB and the other within my database access object).
Is there something which let's me define the model one time only and generates the elementary stuff for me (like in Doctrine) but which saves me from the active record pattern?
The db is not a model, its the raw data source, and the model is, in thoery, more than just the data fields, it should also be the methods that affect the model's data.
You are always going to have to tell the program what to insert and where into the db, even if you use a library that encapsulates the sql or if you write it yourself.
If you find yourself writing the similar "insert" and "select" commands over and over, then its time to design some functions or classes.

What is an ORM in a web application?

I recently got a reply from a server company asking if we are using an ORM in our application which does all the work of sifting application side (like Rails) or if we write reams of SQL, embedded functions etc which would make the database server do the processing for you.
Can anyone explain what is meant by this. Our web application is made up of PHP scripts with functions that make calls to the database to retrieve rows of data, then PHP processes these rows as needed to return results to the user.
thanks
It basically makes your database tables appear like objects on the PHP side of your site so you can easily manipulate data.
For example if you have a User table, getting this user's name is as easy as doing: $myUser->getName();
adding a new user in your database would be:
$myUser = new User();
$myUser->setName('John Doe');
$myUser->save();
Of course this is pseudo code (actually PHP Symfony/Doctrine code), but it's a simple example so you get the point.
An ORM is an abstraction that is supposed to simplify working with a relational database in an object oriented language. It's basically a set of classes and methods that let you create, retrieve and update data without using SQL directly.
For instance instead of writing
$result=mysql_query('select * from sandwiches where color='green' and size='2');
you can use an interface like
$result=$sandwiches->get('color'=>'green',=>'size'=>'2');
and the ORM turns this into SQL and executes the query, taking care of joins, etc.
Popular PHP ORMs are Doctrine and Propel
If you don't know whether you're using one, than it's pretty unlikely that you are!
It is an Object Relational Mapping. See link to wikipedia below.
http://en.wikipedia.org/wiki/Object-relational_mapping
ORM is Object Relational Mapper. which maps the java objects to the database tables and lets you perform some database transactions thorough your code.
EX of ORM tools are like Hibernate, Ibatis ..
ORM is used for Mapping your database objects to your application objects.
In a simple application using ORM, you should have functions that gets/sets data from/to DB should return appropriate application object/objects.
ORM is a Wikipedia article on Object Relational mapping.
Object Relational Mapping is an easy way of mapping Database objects ( tables, views ... ) to classes/objects in OOPL.
Hibernate and NHibernate are a few examples of ORM. it does all the tedious task of handling and mapping result sets..

Categories