I am using cakePhp to query a MSSQL table from Sharepoint. I have no control over the column names, so I cannot create an auto-incremented 'id' for the PK.
I would like to query the table via my 'Users' controller (which already has its own model). Could someone please guide me in the right direction?
Unfortunately, CakePHP does not support composite primary keys. They usual workaround (add a new column with a simple, singular primary key and put a UNQIUE constraint on the columns that used to be the composite key) doesn't work for you either, because you cannot change the schema.
It looks like your hosed. Couple of things you can do:
Get a better ORM or PHP framework. One that does support composite primary keys (E.g. something that uses Doctrine 2). Honestly, CakePHP's ORM isn't that great.
Use raw queries through the CakePHP database layer. You'll still get back nested arrays like you would when using a true CakePHP model. It may be enough for you, depending on what you are trying to achieve.
Related
I'm trying to set up a project using Doctrine 2.3.2 on a database-first implementation. after generating the xml and the mappings, then calling orm:validate-schema it shows me that the mapping is right but the database validation fails. In using the schema tool to find out where my issues I'm finding 2 issues are repeating over and over:
change all my varchars that aren't already at 255 to varchar(255)
drop my primary key with for example the columns (A, B, C) and then create a new primary key with the same columns in a different order (B, A, C)
Both of these things seem meaningless to change. Why would Doctrine force me to change my schema in ways that seem meaningless?
The solution to both of these without changing the database schema is:
the convert-mapping doesn't appear to add the length property to the id field - add it to the xml
This appears to be caused by a difference between the order of the columns in the table, and the order of the columns in the Primary Key. Re-order the order of the xml entries to match the order of the Primary Key.
Having to 2 #1 I'm assuming is a bug - which I will report soon. However, is #2 above a bug or does changing the order mess with Doctrine's logic in some way?
The more I think about this the more I believe it to be an oversight and not done intentionally. I was thinking there was something I was missing but I think these are issues with the library and have added them doctrine's JIRA.
EDIT: Links per request
http://www.doctrine-project.org/jira/browse/DDC-2280
http://www.doctrine-project.org/jira/browse/DDC-2281
I have web application built on CakePHP 1.2.11. and mysql database. In this application I have two tables, namely, users and actions. Users hasMany actions and the user_id (id in users tables) is the foreign key in actions table. The id field is autoincrement integer.
CakePHP documentation said that setting the id field to be Char(36) will make CakePHP able to generate Unique string for each record to be the id.
My application is running and I don't want to loss the data records that my application already has. I need to know if it is safely possible to migrate from autoincrement integer id to char(36) keeping in mind the related table?
In other word, How could I change integer value to the unique string id that cakephp do? Is there any rules? If there any tool automate this kind of migration, I will be appreciated to know it.
Yes, simply alter the table to use a varchar. An INT column can be translated into a char, so you won't lose the original IDs (you will end up with a mix of both old regular ints and new uuids). You will need to make sure the change is also made to any foreign keys on any other tables that will need to store VARCHAR(36) as well.
Then make sure to push the new code live immediately otherwise the new records will not be able to be created, because a varchar field can't be auto-increment.
Lastly, immediately after pushing the new code, clear your model cache so Cake doesn't still think it's an INT.
Are you sure you want to switch?
Honestly, unless you have a really good reason to change to UUIDs (CHAR(36)), then I would recommend just staying with auto-incrementing IDs. There are plenty of people that tout the benefits of each, but it boils down to auto-incrementing IDs can be faster, and unless you have multiple databases where you're worried about overlapping data, auto-ids are just fine. (And it's not a simple "switch")
Not crazy-simple:
If you still are sure you want to switch to UUIDs, there is no automated process, but be careful - it's not just about switching the field types and voila - you'll have to create a script or something to update the id fields as well as all the associated fields (ie 'user_id' in the 'actions' table won't be updated..etc etc).
If so, here's how:
So - create a duplicate of your database (or tables) as back-up. You'll then probably want to rename the 'id' field to 'autoid', create another id field CHAR(36), run a script to populate all the UUIDs, then another script that populates the associated ids (ie 'user_id' in the 'actions' table) with the corresponding UUID.
CakePHP code that generates UUIDs:
Here's the link to creating a UUID in CakePHP 1.2: http://book.cakephp.org/1.2/en/view/826/uuid
This is for a sort of proof of concept draft to get things working, but don't want to have completely crap code. For my database, I tried to get true foreign key relations going using innoDB, but couldn't get it.
Instead of using foreign keys, I decided to just pull mysql_insert_id() after inserts, saving it as a variable, then putting that variable into the related table.
Is this horrible? Everything seems to work well, and I'm able to connect and relate ID's as needed. What benefits would using foreign keys give me over my method (besides updates/deletes cascading)?
To create a relation (master->detail), you have to always supply the keys by yourself, either using mysql_insert_id, natural keys or key generated by your applications. The FOREIGN KEY is not going to make that work for you.
What FOREIGN KEY does is
Helping you enforce the relationship/the integrity of your data (so the "detail" record does not point to an invalid parent)
Handles deletion or key alterations of master records (ON DELETE ..., ON UPDATE ...).
It's also creating an index in your "detail"-table for the "master_id"-row if it doesn't exist yet (okay, you could also do that without FOREIGN KEY)
Has also some kind of documenting purpose for example an ERM-tool could reengineer the relationship model from your schema (okay, this point is a slight long shot)
The cost of adding the FOREIGN KEY constraint statement is small compared to its benefits.
As I read J.Gilmore Zend Book (Models section):
class Game extends Zend_Db_Table_Abstract
{
protected $_primary='id'; //line 4
}
[..]Line 4 identifies the table's primary key.By default the framework will
presume the primary key is an automatically incrementing integer named id,so
this line is not necessary [..]
I have a question:
Do I need to manually set primary and foreign key while building a table
(Ex. in phpmyadmin with something like "PRIMARY KEY (id),FOREIGN KEY (post) REFERENCES users (id)
ON DELETE CASCADE")?
Or I can handle tables relationships and fields nature just by referring to Zend code using $_primary,$_dependentTable,$_referenceMap and so on?
thanks
Luca
Both. Although you can get away with an ORM dealing with relations, the database ensures at low-level those relations are respected. Always let the database do its job as much as possible, it is built for handling relations and preventing data corruption. What if your ORM has a bug?
As a somewhat related example, say you have a field declared as int in database, you are responsible as a developper for making sure you use int's in your queries, but the database enforces that rule at a lower level, protecting your data in case you don`t.
You should define the primary/unique keys and any other indexes properly when you create the table.
After you've done this in 99% of cases Zend_Db will understand what's going on as it's able to read the table metadata and derive the primary key from that.
What are your methods of linking data spread over multiple databases architectures (think MySQL vs PostgreSQL etc), into a single application?
Would you create giant hashtables/arrays to match content against one another? Are there other, more effective and less memory-consuming options for doing this?
If you were to use data both from a MySQL & PostgreSQL source, with no way of converting one DB to the other (application constraints, lack of time, lack of knowledge, ... ), how would you go about it?
SQL Relay or another sql proxy.
http://sqlrelay.sourceforge.net/
At least in the case of MySQL, you can use data from multiple databases in a single query anyway, provided the databases are hosted by the same MySQL Server instance. You can distinguish tables from different databases by qualifying the table with a schema name:
CREATE TABLE test.foo (id SERIAL PRIMARY KEY) TYPE=InnoDB;
CREATE DATABASE test2;
CREATE TABLE test2.bar (foo_id BIGINT UNSIGNED,
FOREIGN KEY (foo_id) REFERENCES test.foo(id)) TYPE=InnoDB;
SELECT * FROM test.foo f JOIN test2.bar b ON (f.id = b.foo_id);
In PostgreSQL, you can also qualify table references with a schema name. I'm not sure if you can create foreign key constraints across databases, though.
If you're looking to create constraints across RDBMSes - you can't.
I'm facing the same issue with running part of an application off PostgreSQL for where it will benefit, and the rest of MySQL where it's better.
I'm doing multiple inserts keyed off the same format of primary information (in my case a generic user ID), so I'm letting the application handle the logic of making sure to ask for the same ID from both DBs.
There's not really a clean way to do this outside of abstracting it to a class or utility function, though, that I've found.