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.
Related
I'm doing a web app here using Laravel + AngularJS and I have a question.Do I need a model for each table that I have in my database? There are 87 tables in my database and I need to query all of them according to with the input that the User wants.
I just want to make sure with all tables must have a model file or if just one is enough.
There are 2 ways by which you can access your DB tables:
Eloquent ORM (dependent on Models)
DB Facade Query Builder(independent on Models)
Former, is more clean and best approach to perform DB query and related task, whereas latter is not clean, and it is going to be difficult for you to manage large application, as you told there are 80+ tables in your application.
Also, if you're using Eloquent way, then it's also a better to have a base model, which will have common code which you can inherit in child models. Like if you want to store "user id" who did some DB changes, then in the boot function, you can write Auth::id() and assign that value to changed_by field on your table.
In DB Facade way, you've to hard code table name every time you're performing DB operation, and which leads to inconsistency when you found that you've to change the name of the table, it's a rare scenario still it'll be difficult to manage if in a file there are multiple tables DB operation going on. There are options like, creating a global table name variable which can be accessed to perform DB operation.
Conclusion:
Yes, creating 80+ model for implementing Eloquent way is painful, but for a short term, as the application grows it will be easy for you to manage, it will be good for other developer if they start working on it, as it will give a overview of DB and it will improves code readability.
It depends on how you'd like to handle queries.
If you'd like to use Eloquent ORM, you need model classes to handle objects and relationships. That is a model for a table, except intermediate relationship tables, which may be accessed through pivot attribute.
Raw SQL queries are also supported. You don't really need model classes for them, as each result within the result array will be a PHP StdClass object. You need to write raw SQL though.
See Laravel documentation.
I am trying to create simple database abstraction layer. I read a lot of articles about Active Record and Table Data Gateway and right now I am very confused.
I think that I understand some theory (small) about them but not how exactly to implement them. I have choosed to implement Data Table Gateway. I will try to explain what I did and if you give me some advices I will be glad. I am not sure why (for example in ZF2) every time I have to use Table Data Gateway like DI in the models.
In my case my AbstractModel just get DbAdapter in the constrictor by IoC container but I am not sure that this is ok.
Ok I will describe my situation.
I have following classes:
DbAdapter -> it creates db connection (using PDO)
IoC (Inversion of Control Container)
AbstractModel -> in constructor I get DbAdapter using IoC. This means that it hold only one instance of DbAdapter. In this class I also have CRUD methods.
Another classes represent the tables in db. For example class User extends AbstractModel and has method getTable which return the name of the table. Another sql queries will be in this classes which represent the tables. These classes have access to DbAdapter.
Is it ok this scheme and how can I improve it?
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.
Put simply about Table Data Gateway (TDG) implementation: you create separate TDG class that contains SQL for CRUD operations with concrete table. So, your models communicate not directly with a datasource (for example database) but via those abstracted ones - TDG classes. So, it's just an approach for making another level of abstraction and it's just a wrapper for communicating with database - get and modify the data. IMHO TDG classes should not contain members, only methods. Here's a good schema that visualizes the use TDG pattern. When using TDG approach, SQL should be moved from model classes to datasource (TDG) classes. And all data that I retrieve from DB through TDG classes are stored in my model members.
Now, what about active record implementation? If I would merge data access and my model class into one model class then would I implement active record? I was unable to find a clear distinction or how those patterns look in PHP and differ from each other.
Often, I'm having one singleton database class and then separate model class for each database table. Each model class has CRUD + several custom (count, avg and etc.) operations. Some classes have members for persisting results from CRUD or custom operations - thats's done upon the need. Could this approach be identified as active record? Also, if I would move SQL from my model classes to TDG classes would this be Table Data Gateway?
From http://martinfowler.com/eaaCatalog/index.html
Table Data Gateway: An object that acts as a Gateway (466) to a database table. One instance handles all the rows in the table.
Active Record: An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.
The obvious main difference is that TDGs wrap access to a table and only returns row data, while ARs wrap access to a row in the table and adds business logic to it.
Unless you have very low impedance mismatch, having a TDG is preferred because with AR your business/domain objects follow the structure in the database, which us usually not how your domain objects should be modeled. A Row may know how to persist itself, but a Person should not know. It is more maintainable in the long run to to separate persistence logic and domain logic.
Regarding your Singleton DB object have a look at Is there a use-case for singletons with database access in PHP?.
I am not suggesting that all models are tables.
What I am asking is whether every single table must also have its own class defined specifically for it when using Zend? Is there any way of getting away from this awkward boiler-plate coding. We're just starting to look into Zend (hoping to leave procedural PHP land!) and my colleague thinks this could end up being pretty time-consuming.
Is this the reason for people using ORM solutions? Is there any other way around this?
Thanks for your replies.
The Zend Table classes follow the Table Data Gateway pattern, which by definition
... holds all the SQL for accessing a single table or view: selects, inserts, updates, and deletes. Other code calls its methods for all interaction with the database.
In the book, Fowler is not that rigid about that, saying that
for very simple cases, you can have a single TDG that handles all methods for all tables. You can even have one for views or even for interesting queries that aren't kept in the database as views.
However, except for being able to use Views, Zend_Db_Table does not accomodate for this. You can create queries to multiple tables, but those would have to be made through the Zend_Db_Adapter directly or - when using joins - by switching off the integrity check. Otherwise, you have to use the API offered by Zend_Db_Table Relationships
So yes, one instance should correspond to one table or view. You do not need to create classes for that though if you dont plan on extending the classes. Zend_Db_Table_Definitions allow you to configure Zend_Db_Table instances on the fly.
Note that TDG is a DataSource Architectural Pattern and not an Object-Relational pattern. It's purpose is not to help with impedance-mismatch, but with separating database access code from business logic.