Unique Id for all the entities from all repositories - php

In PHPCR (NoSQL) there is something like Uuid (it's something different than Id in the table, unique only for the single table) - the Id that is unique to all Documents (Entities) in the whole data base. It's of much help when e.g. using forms, because I can use Uuid without knowing the exact class of an entity, and still being able to access directly a related record just by:
$objectManager->find(null, $uuid);
I'd like to have a similar solution with the RDBMS in the Doctrine ORM, i.e. to find a record when knowing only its unique id (Uuid). Do anyone of you know about such a solution?
From the PHPCR-ODM documentation:
http://docs.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/reference/basic-mapping.html#doctrine-mapping-types
Each document can have a unique identifier for referencing it. While the uuid is also exposed as a read-only string property, the proper mapping for it is mapping it as UUID.
UPDATE:
Here are the Doctrine's sources:
From the general Doctrine common lib https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Persistence/ObjectManager.php#L42
public function find($className, $id);
From the ORM https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/EntityManager.php#L380
public function find($entityName, $id, $lockMode = null, $lockVersion = null)
But I don't stick to find() method.

The equivalent $entityManager->find() method does not allow for the entity parameter to be null. So no, there is no way to do the same using the ORM.
I would surmise the reason for this is that document db's are quite different from relational databases. In a relational database you would need to query every table. To put it another way, using an ORM you would need to query every entity. With a document database, as far as I can tell, each document is a set whereas in a relational database sets are derived.
I hope that helps and makes sense. I've no experience with document databases. The method signature for find() in the ORM seems to explain it though.

Related

Would Entity or Table be better for converting this cakephp controller action?

I am using cakephp 3.1
Suppose I have this simple controller action below.
public function apiGetAccessKey($username)
{
$query = $this->Customers
->find()
->select('access_key')
->where(['username' => $username]);
}
I want to transfer it into the Model since it involves data extraction. With cakephp 3.x, model is divided into Table and Entity. Which should I use? Table or Entity? How should the code look like?
TL;DR
Entities represent data, table objects access and process data.
Like I already recommended you in the other question I'll do it again: Read the manual. You approach of "trial and error and then ask" is not very effective. Read the book, try the code examples. If something remains unclear finally ask about that.
This is taken directly from the book:
Table Objects
Table objects provide access to the collection of entities stored in a
specific table. Each table in your application should have an
associated Table class which is used to interact with a given table.
Entities
While Table Objects represent and provide access to a collection of
objects, entities represent individual rows or domain objects in your
application. Entities contain persistent properties and methods to
manipulate and access the data they contain.

Should models representing a single row return data generated using multiple rows?

Some background:
This is for an MVC application built without using any frameworks, but follows the MVC paradigm.
I am using an ORM library called RedBean to talk to the database.
While RedBean represents data using "beans", it supports wrapping them into a model, so custom functions may be provided by the model:
$account = R::dispense('account');
$account->name = "john";
R::store($account);
$account->getFormattedLastUpdatedTime('America/New_York');
Now the question:
Currently, each instance of the model would represent 1 row in the database. If I have a collection of accounts, then I would have an array of "account" models.
In the application, I have a feature for custom profile fields (don't worry, I am not using EAV though :)). One of the tables stores metadata for those fields (name, description etc) for generating the form fields for those custom profile fields. Once again, each row of the metadata represents 1 form field and each row is represented by 1 model.
I now wish to write a method to convert all those rows into a form object which can then be used for rendering and processing the form. But, where should this method live? My initial thought was to place it in the model representing the custom profile field metadata.
Clarification: This function would not be in the account model, but instead in the profile_fields_meta model.
Problem
As each model should represent 1 row, it seems a bit "dirty" to have the model return an object that would be generated from MULTIPLE rows in the database. Am I correct to say this is not the best way to do it? What do you recommend I do instead?
It would be right to have extended ArrayObject (http://php.net/manual/en/class.arrayobject.php) or other container class to run methods for collection.
Try to modify query methods to return data in your custom collection class instead of array if specified.
There's nothing inherent to MVC that says "each model [instance] should represent one row." Often in MVC frameworks the model (as seen by the controller, at least) is entirely ignorant of the data store and doesn't have any concept of or direct mapping to a "row." This isn't necessarily the case with ORMs but a model needn't adhere to an ORM's constraints.
However, though it's hard to tell without knowing more about your schema and implementation, the functionality you're describing doesn't sound appropriate for your Account model. In fact, it sounds to me like you should consider having a "FormField" model such that, in Rails parlance, Account "has many" FormFields.
And for the record, EAV isn't always bad, it's just often misused.

Is there a way to pass a SQL expression as a entity field value in Doctrine2?

Is there a way to do something like this: (dumb code)
$entity = new Entity\SomeEntity();
$entity->mappedField = new SQLExpression('SOME SQL CODE HEARE');
$entityManager->persist($entity);
$entityManager->flush();
?
[EDIT]
I want to insert ID from sequence in Oracle tablespace.sequence_name.next value, I know that this can be done from trigger, but my access user is not able to create triggers in my env.
It would be a lot more effective if you ask a question about the thing you are trying to achieve.
As far as I know this won't work, Doctrine2 is very peculiar about mixing the domain model with the persistence layer. This would couple your domain layer to your persistence layer.
What is it you're trying to achieve? You're probably best served with an event listener, though I'm not sure what problem you're trying to solve.
No need to, Doctrine can handle Oracle Sequences by itself, see http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifier-generation-strategies.
And see also Doctrine2 doesen't set sequence to default for id column (postgres).
You have to remember that Doctrine2 Entitys map SQL Fields. Every datatype needs to be mappable to your database.
A String becomes a varchar or blob, a integer becomes a int etc. Objects have no corresponding datatype with one exception: Relations! As a Object Relational Data-mapper Doctrine can map a Object (Entity or EntityCollection) to a related table, if defined by you. You really should take a deeper look in the capabilities Doctrine gives you to define these as stated in the official tutorial.
Answer is that is not possible with doctrine2

Using Doctrine with views - dud 'id' field generated

I have a DB (yes, that one) which is proving far easier to access via views than raw tables. In general this plays quite nicely with Doctrine, but there's one issue. Doctrine can't identify a primary key in a view table when generating the YAML from the database schema, so it invents one called 'id'. Generating classes from this means that all queries fail on the lack of this id field.
Is there any way you can hint to the generator script that it shouldn't create this field, and point it to one that's more appropriate? I can see how to do it in the YAML, or in a class with annotations, but no way to do it in the DB.
Suggestions welcome.
(Anyone following my questions (why?) will probably have worked out how much fun I'm having with both Doctrine and this database. I think it's called a "learning experience".)
I have no idea how to do it in the YAML but you can just remove the the definition of the ID column from the generated PHP (Base) file. Not the most "elegant" solution but I think Doctrine's convetnion is to always add a Primary Key.
BTW, is there anything usefull for you at http://www.doctrine-project.org/projects/orm/1.2/docs/manual/component-overview/en#views?
perhaps not exactly what you asked but
another solution is to put this in the model class
public function setUp() {
Doctrine_Core::getTable('your_view_name')->removeColumn('id');
parent::setUp();
}
hope it helps someone with this problem

What does a Data Mapper typically look like?

I have a table called Cat, and an PHP class called Cat. Now I want to make a CatDataMapper class, so that Cat extends CatDataMapper.
I want that Data Mapper class to provide basic functionality for doing ORM, and for creating, editing and deleting Cat.
For that purpose, maybe someone who knows this pattern very well could give me some helpful advice? I feel it would be a little bit too simple to just provide some functions like update(), delete(), save().
I realize a Data Mapper has this problem: First you create the instance of Cat, then initialize all the variables like name, furColor, eyeColor, purrSound, meowSound, attendants, etc.. and after everything is set up, you call the save() function which is inherited from CatDataMapper. This was simple ;)
But now, the real problem: You query the database for cats and get back a plain boring result set with lots of cats data.
PDO features some ORM capability to create Cat instances. Lets say I use that, or lets even say I have a mapDataset() function that takes an associative array. However, as soon as I got my Cat object from a data set, I have redundant data. At the same time, twenty users could pick up the same cat data from the database and edit the cat object, i.e. rename the cat, and save() it, while another user still things about setting another furColor. When all of them save their edits, everything is messed up.
Err... ok, to keep this question really short: What's good practice here?
From DataMapper in PoEA
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. (The
database schema is always ignorant of
the objects that use it.) Since it's a
form of Mapper (473), Data Mapper
itself is even unknown to the domain
layer.
Thus, a Cat should not extend CatDataMapper because that would create an is-a relationship and tie the Cat to the Persistence layer. If you want to be able to handle persistence from your Cats in this way, look into ActiveRecord or any of the other Data Source Architectural Patterns.
You usually use a DataMapper when using a Domain Model. A simple DataMapper would just map a database table to an equivalent in-memory class on a field-to-field basis. However, when the need for a DataMapper arises, you usually won't have such simple relationships. Tables will not map 1:1 to your objects. Instead multiple tables could form into one Object Aggregate and viceversa. Consequently, implementing just CRUD methods, can easily become quite a challenge.
Apart from that, it is one of the more complicated patterns (covers 15 pages in PoEA), often used in combination with the Repository pattern among others. Look into the related questions column on the right side of this page for similar questions.
As for your question about multiple users editing the same Cat, that's a common problem called Concurrency. One solution to that would be locking the row, while someone edits it. But like everything, this can lead to other issues.
If you rely on ORM's like Doctrine or Propel, the basic principle is to create a static class that would get the actual data from the database, (for instance Propel would create CatPeer), and the results retrieved by the Peer class would then be "hydrated" into Cat objects.
The hydration process is the process of converting a "plain boring" MySQL result set into nice objects having getters and setters.
So for a retrieve you'd use something like CatPeer::doSelect(). Then for a new object you'd first instantiate it (or retrieve and instance from the DB):
$cat = new Cat();
The insertion would be as simple as doing: $cat->save(); That'd be equivalent to an insert (or an update if the object already exists in the db... The ORM should know how to do the difference between new and existing objects by using, for instance, the presence ort absence of a primary key).
Implementing a Data Mapper is very hard in PHP < 5.3, since you cannot read/write protected/private fields. You have a few choices when loading and saving the objects:
Use some kind of workaround, like serializing the object, modifying it's string representation, and bringing it back with unserialize
Make all the fields public
Keep them private/protected, and write mutators/accessors for each of them
The first method has the possibility of breaking with a new release, and is very crude hack, the second one is considered a (very) bad practice.
The third option is also considered bad practice, since you should not provide getters/setters for all of your fields, only the ones that need it. Your model gets "damaged" from a pure DDD (domain driven design) perspective, since it contains methods that are only needed because of the persistence mechanism.
It also means that now you have to describe another mapping for the fields -> setter methods, next to the fields -> table columns.
PHP 5.3 introduces the ability to access/change all types of fields, by using reflection:
http://hu2.php.net/manual/en/reflectionproperty.setaccessible.php
With this, you can achieve a true data mapper, because the need to provide mutators for all of the fields has ceased.
PDO features some ORM capability to
create Cat instances. Lets say I use
that, or lets even say I have a
mapDataset() function that takes an
associative array. However, as soon as
I got my Cat object from a data set, I
have redundant data. At the same time,
twenty users could pick up the same
cat data from the database and edit
the cat object, i.e. rename the cat,
and save() it, while another user
still things about setting another
furColor. When all of them save their
edits, everything is messed up.
In order to keep track of the state of data typically and IdentityMap and/or a UnitOfWork would be used keep track of all teh different operations on mapped entities... and the end of the request cycle al the operations would then be performed.
keep the answer short:
You have an instance of Cat. (Maybe it extends CatDbMapper, or Cat3rdpartycatstoreMapper)
You call:
$cats = $cat_model->getBlueEyedCats();
//then you get an array of Cat objects, in the $cats array
Don't know what do you use, you might take a look at some php framework to the better understanding.

Categories