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
Related
I was given this project to work on with absolutely no documentation or contact developer. I noticed in the database dump that they are storing what looks like PHP Namespaces for Eloquent models in a couple tables. For example an address table has a string column named "object_type" with the value always being "App\Entities\Client". I searched through the whole project for the PHP code that would use this value. Hopefully to give me insight to it's purpose. Not to my surprise, the project never uses this value. I just see it hard-coding these values upon insert into the DB.
My question is, is this some sort of Database and/or ORM modeling design practice? If so, could you explain how this could be used in a simple practical sense?
Maybe this was some concept the developer had and it never evolved. It's interesting idea but, the idea of joining through MySQL on a string conditional sounds like torture.
Sounds like Laravel polymorphic relationships:
Custom Polymorphic Types.
By default, Laravel will use the fully qualified class name to store the type of the related model.
And, yes, this is a valid modeling technique, though purists rightly argue this technique abuses normal form.
I am not sure what the developers where thinking.
But imagining we are in a forum with thread and replies to each thread. We maybe want to have a Favourites table where we can save replies and threads.
A way to do it would be to have a column in the favourites table called "object_type" (just to use the same term you have in your case) and then when we save an object into the database with eloquent we can use:
$favourite->object_type = get_class($thread); //or get_class($reply) in case we want a reply
$favourite->save();
This way will save the namespace of that class into the database. But laravel will recognise it when we get it from the database.
Hope this cold be helpful.
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.
This isn't much of an issue with MySQL per-se.
The Full Story
I'm writing a very small PHP framework. It isn't like existing frameworks where they force you to use a certain methodology. It isn't either like a CMS framework. Trust me, I've seen Zend framework and I've used CMSes like Joomla and WordPress extensively, none of them come close to what I'm doing.
Introducing The Issues
I'm writing the Database abstraction part. You get class methods like ::table_exists() etc.
It is designed in a way that people can easily add different database classes and use them instead (eg; mysql, mssql, oracle, flatfile...).
They simply need to write a class which satisfies a base abstract classes'.
The Real Issue
I'm writing the functionality for ::table_create(), but have one main problem: MySQL doesn't like empty tables (ie, without a column).
I have several proposed fixes:
For each new table, create a commonly used column, such as 'id' (type=INT)
For each new table, create a temp column which doesn't use any space as much as possible (perhaps a boolean column?)
Somehow delay table creation until at least one column can be created
This approach is most certainly new, and I'd like to here some unbiased comments about it (anything on the lines of "but no one does it that way" won't do).
Well I would either go with option 1), Adding a generic ID column, which you might find you need anyway, or with option 3) Delaying the table creation. I'm assume after they call ::table_create() they will be calling table_add_col(), etc. So just delay creation until there is at least one column, OR until they actually try and use the table for the first time.
Your proposed fixes look quite good. But I would recommen them in a diffrent order. If you are able to delay the creation, tht's probably the best. My second favorite would be to have a table with only an ID, although you might be delete this column, if you want to create a many-to-many relations table with two foreign keys only.
last of your points.
its really very strange what you are doing here. creating tables on the fly? dynamically or something?
well... whatever you are trying to accomplish. you should have a look at document/object oriented databases like couchdb http://couchdb.apache.org/ ! you can create a document and dynamically add whatever fields you want. those are the closest thing to your "columns"
but as you like it...
your first attempt is ugly because it might lead to conflicts.
the second attempt is clumsy. but if you do so create a col with uniqueprefix_random so you can delete it afterwards.
but its well... i dunno what to say about that.
theird approach seems the only senseful!
lacking a fellow programmer to talk over the right approach for my problem, I decided to ask you. What is your preferred approach of mapping dictionary tables to a model in MVC paradigm, regardless of the MVC framework / environment you are using?
My problem is I have a couple of database tables that only serve as dictionaries and are related to other tables as foreign keys. A good example would be a table request having a status_id where statuses are kept in a separate status table.
Now, the latter table needs to be mapped to a model on the code-side of the application. I can either:
Define all the statuses as constants so they can be referenced in the code without poking those dreaded 'magic numbers' here and there. However, any change to the dictionary (database-side) would require a code modification.
Omit the `status` table at all and just define meaningful constant to be used across the code. Pros: one place to rule them all. Cons: all changes require diving into the code, now the database features 'magic numbers' not really being foreign keys
Try to translate statuses into the model automagically, adding a field like 'const_name' to the 'statuses' table and them creating the constants on the fly while loading the model. This one seems to have the most sense for me.
Would you mind to share your usual approach to this issue?
Best,
Bartek
If it's just going to be a set of constants that are contained in the database instead of code, you could have a static class load the status constants for everyone else to use. That way there's no duplication between db and code, and no magic numbers.
edit: since it's a static class, you could have it lazy load the constants. Don't hit the database until the first time someone asks for a status value.
I'd say if you going to change it often it's better to go with table. Otherwise static class is fine (for example no point having table to store sex, or list of states).
I have a mysql database table called UserDegree, when i try to import back to PHP using Doctrine it generates a model name Userdegree, is there a way to solve this?
i really can't find any good doctrine documentation.
thanks!
I am not sure about your specific problem, but for the "good doctrine documentation" part, did you try the manual ? See Doctrine ORM for PHP -- I think it's actually quite good, especially compared to what you get with some other projects, that don't have much documentation, or totally outdated.
About your problem (as I said before, not sure) : I suppose Doctrine takes each "word" from the table name in the DB, and converts that to a "name" for PHP. Quite often, "words" in table names are separated by an underscore '_', and are all in either lower or either case.
I suppose, if you name your table "user_degree", instead of "UserDegree", that Doctrine should detect it's composed of two "words", and create a PHP class called "UserDegree" -- actually, I tested with a table called post_has_tag, and it generates a class called PostHasTag.
Pascal Martin is correct. The table should be named like user_degree, in this case Doctrine will generate UserDegree class.
I also recently figured out that it is possible to keep all database identifiers to be under_scores, while having Doctrine to generate camelCase'd code. It happens automatically for table names, as said above. As for field names, they can be mapped to camelCase using alias feature of YAML schema file (name: user_id as userId). Moreover, you can automate field aliasing by developing custom task for Doctrine.