I'm trying to teach myself ZF2 in conjunction with Doctrine 2. I've completed both the Album tutorial and Blog Tutorial on Zend's website successfully. Now I'm trying to go back and convert the Blog Tutorial to use Doctrine 2. I believe I've successfully setup my config for doctrine and used DI to get it inside of my controller (WriteController.php) since I am able to dump the contents of it within my action. I don't get any errors so long as I don't do anything with it.
My question is what roll does Doctrine take in the Controller -> Service -> Mapper -> Backend layered structure which was taught in the Blog tutorial? (Reference To what I mean)
Also, I'm assuming Backend is referring to my Models. Is this correct?
Would I just replace any references to /Blog/Model/Post with /Blog/Entity/Blog?
The Doctrine is the Mapper. And maybe we could say also the Service (through EntityRepository). But usually you will create your own Service Layer.
The Backend is not the entities it self. Entities in one way to map the several options of backend. As backend you can understand the several options of Relational Databases (Mysql, SqlServer, Oracle, etc) NoSql Databases (like MongoDB), file system and so on.
I didn't understand your last question. But when I use Doctrine I always create my entities in /MyModule/Entity namespace. While when I use the standart Zend/Db I always create in /MyModule/Model. I do that by standardizing matters.
Related
I'm working in a project in Symfony 3.0.1 that use five databases with DBAL as data access layer. I always worked in Symfony with ORM and I always used the next MVC model:
Data access:
CONTROLLER -> REPOSITORY (the queries goes here) -> ENTITY
Display results:
CONTROLLER -> render($view,$params) -> VIEW
This model allow short and simple controllers, but now I'm using DBAL so I can't use repositories.
The question is:
How can I achieve a similar model by using DBAL? In others words, Where should I put the queries?
Should I use services instead of repositories?
Note: I only use the select statement in that databases.
Thanks in advance!
You don't need an ORM in order to use entities.
Likewise, you do not need Doctrine to be able to build repositories once a repository is a implementation of design pattern:
Repository
Mediates between the domain and data mapping layers using a
collection-like interface for accessing domain objects.
Read more
Even though you can't use Doctrine ORM you still can to design POPO classes against an abstract model class or/and model interface.
You could inject DBAL Connection object for each model/entity via construct or setter method. After creating repo classes is easy. Returning collection objects, hydrating items or using raw arrays is up to you.
Edit #1
I have added a real worl exemple I have used in the past (few years ago), look:
https://github.com/felipsmartins/misc-and-code-snippets/tree/master/php/model-exemple/src/AppBundle/Model
Edit #2
Regarding services, it would much better if there is specialized and well defined models (as opposed to Anemic Models) working together inside a service which coordinates the whole transaction, in this case it would be what we know by Unit of Work (see Unit of Work Pattern)
I have started to look into Symfony CMF, and I must say it looks good!
However, I can't get my head around the database Schema! I have read up on the basics of PHPCR, and understand it to an extent. The bit that is confusing me are all the extra tables that Symfony CMF installs. I.E
phpcr_binarydata
phpcr_internal_index_types
phpcr_namespaces
phpcr_nodes
phpcr_nodes_references
phpcr_nodes_weakreferences
phpcr_type_childs
phpcr_type_nodes
phpcr_type_props
phpcr_workspaces
What are all these used for? The only table I can make sense of is phpcr_nodes and the XML / property data stored! Some tables have data and are being queried - but I can't see any reference to them in phpcr_nodes!
For example:
Table "phpcr_type_nodes" has data such as
name: phpcr:managed
supertype: nt:base
Table "phpcr_type_props" has data such as
name: copyright
When you see this schema, it means you are using Jackalope Doctrine DBAL, which is one possible implementation of the PHPCR API. This implements PHPCR on top of a relational database. Unfortunately, there is not too much documentation available, but all of those tables are used.
If you want to learn more about PHPCR, i recommend to have a look at this PHPCR Tutorial . If you really want to understand the database schema in detail, you will need to dig through the source code of Hackalope Doctrine DBAL.
Note that you can also use doctrine ORM with the CMF. The RoutingBundle already brings mapping for it, for other bundles it would be doable to implement ORM mappings and we would be glad for contributions.
PS: I never figured out how to get notifications after the initial notification on stackoverflow, so best open an issue on the relevant github repository if you need more information.
How to take care of fetching related objects of one object?
For example object project has some tags. How and when should I fetch those object? In user initialization in mapper? That would be a big overload. The best way would be to load them dynamicly when system ask user for tags, but how to do that if model does not know anything about the mapper? Or just use Doctrine and forgot all about those problems?
Im asking this in relation to PHP Zend Framework. But any technology would suffice I think for this problem.
It is difficult to answer your question because you are not referring to a specific ORM or framework. If you are looking for suggestions, I would recommend using Doctrine as the model API and Zend Framework as a stand-alone library.
If you need a full featured framework you can take a look at any of these:
Symfony2
CakePHP
Zend Framework (as a framework vs stand-alone lib)
CodeIgniter
If you choose to go with Doctrine as your ORM, you can setup the schema file to ensure objects are relationship aware, then you can make references like:
// Joins tags table by way of intermediary object_tag table providing
// a M:1, 1:M relationship
$tags = $object->getTags();
Doctrine (1.2 not sure about 2.x) does employ lazy loading pattern, where the objects are only queried when requested.
What good is a repository pattern when you have an ORM?
Example. Suppose i have the following (fictional) tables:
Table: users
pk_user_id
fk_userrole_id
username
Table: userroles
fk_userrole_id
role
Now with an orm i could simply put this in a model file:
$user = ORM::load('users', $id);
Now $user is already my object, which could easily be lazy loaded:
(would be even nicer if things are automatically singular/pluralized)
foreach ( $user->userroles()->role as $role )
{
echo $role;
}
Now with the Repository pattern i'd had to create a repository for the Users and one for the Roles. The repository also needs all kinds of functions to retrieve data for me and to store it. Plus it needs to work with Entity models. So i have to create all of those too.
To me that looks like alot of stuff do... When i could simply get the data like i described above with an ORM. And i could store it just as easy:
ORM::store($user);
In this case it would not only store the user object to the database, but also any changes i made to the 'Roles' object aswell. So no need for any extra work like you need with the repository pattern...
So my question basically is, why would i want to use a repository pattern with an ORM? I've seen tutorials where to use that pattern (like with Doctrine). But it really just doesn't make any sense to me... Anyone any explanation for its use in combination with an ORM..??
The ORM is an implementation detail of the Repository. The ORM just makes it easy to access the db tables in an OOP friendly way. That's it.
The repository abstract persistence access, whatever storage it is. That is its purpose. The fact that you're using a db or xml files or an ORM doesn't matter. The Repository allows the rest of the application to ignore persistence details. This way, you can easily test the app via mocking or stubbing and you can change storages if it's needed. Today you might use MySql, tomorrow you'll want to use NoSql or Cloud Storage. Do that with an ORM!
Repositories deal with Domain/Business objects (from the app point of view), an ORM handles db objects. A business objects IS NOT a db object, first has behaviour, the second is a glorified DTO, it only holds data.
Edit
You might say that both repository and ORM abstract access to data, however the devil is in the details. The repository abstract the access to all storage concerns, while the ORM abstract access to a specific RDBMS
In a nutshell, Repository and ORM's have DIFFERENT purposes and as I've said above, the ORM is always an implementation detail of the repo.
You can also check this post about more details about the repository pattern.
ORM and repository pattern...depends on setup.
If you use your ORM entities as the domain layer, then please use no repositories.
If you have a separate domain model and you need to map from that model to ORM entities and so perform a save, then repositories are what you need.
More details you find here (but must be logged to linked-in). Also to understand the difference, check out the definition of the repository pattern.
Most people use classes that they call repositories, but aren't repositories at all, just query classes - this is how/where you should place your queries if you decided to go with the #1 option (see answer above). In this case make sure not to expose DbContext or ISession from that query class, nor to expose CUD-methods from there - remember, Query class!
The #2 option is a tough one. If you do a real repository, all the inputs and outputs on the repository interface will contain clear domain classes (and no database related object). It's forbidden to expose ORM mapped classes or ORM architecture related objects from there. There will be a Save method also. These repositories might also contain queries, but unlike query classes, these repos will do more - they will take your domain aggregate (collection and tree of entities) and save them to DB by mapping those classes to ORM classes and perform a save on ORM. This style (#2) does not needs to use ORM, the repository pattern was primarly made for ADO.NET (any kind of data access).
Anyhow these 2 options are the 2 extremes we can do. A lot of people use repositories with ORM, but they just add an extra layer of code without real function, the only real function there is the query class like behaviour.
Also I'd be careful when someone talks about UnitOfWork, especially with ORM. Almost every sample on the internet is a fail in terms of architecture. If you need UoW, why not use TransactionScope (just make sure you got a wrapper which uses other than Serializable transaction by default). In 99,9% you won't need to manage 2 sets of independent changes in data (so 2 sets of OuW), so TransactionScope will be a fine choce in .NET - for PHP i'd look for some open-session-view implementations...
What I have is the following db structure(tables):
lists[name,id]
list_items[title,list_id,content]
I've created the needed files and code(the MVC) needed to manage the first table(lists).
I also added the hasMany to the model class. At that point I am stuck.
What I need is a solution for managing each item (basic CRUD, I assume that complex management is just an advanced CRUD that I will find out how to do by myself).
I will be specific: since it's a content that have no place (but the admin) that it will be used by itself, should I -
create a full mvc structure for it? (can or should I implement it somehow[how?] in the lists package?
if not, how can I attach the tables? (since the use is about to be dropped in version 2)
would an element(cake concept/context) will be the appropriate way to create a view for such situation?
ANY insight will be appreciated.
If I undertant correctly, you want to create a CRUD part of this tables by yourself, without bake.
You need to write all the MVC estrucure and be carefull with the naming combention of cakephp http://cakebaker.42dh.com/2006/02/18/cakephp-conventions/
You need the model into app/models and also a a controller into app/controllers (remember naming combentions) and for each model you need a folder into /app/views.
Alfo, every, every function in your controller needs a view, even if this action doesn´t write anything to screen
I hope this was usefull.
Have you tried using Cake's bake feature? Your CRUD will be automatically created in about 2 seconds. I would also recommend you do the Blog tutorial to get a feel for scaffolding.
CakePHP is all about convention over configuration. Eg naming conventions for tables, controllers, models etc.. So much can be done automagically.