Unable To Save Data In MySQL From A Custom Magento Module - php

I am making a custom module for Magento 1.7.0. I am facing a problem while trying to insert data into MySQL. I fetch the user information from the session as follows:
$customer = Mage::getSingleton('customer/session')->getCustomer();
$user_id = $customer->getId();
$user_id now carries ID of the current user logged into my Magento system.
Basically the problem is that when I try to save this above ID in my custom table, the value that is saved in my table is always 0.
Previously I faced this problem while trying to save another integer value, which I solved by changing the datatype of my MySQL table column from int(10) to tinyint(4), but in this case I cannot do so for the user ID.
$model= Mage::getModel('voter/competetion')
->setDesignid($designId)
->setUserId($user_id)
->setVote($vote)
->setStartdate($startDate)
->save();
The MySQL column name are as follows along with the install sql script: id, designid, user_id, vote, startdate, enddate
$installer = $this;
$installer->startSetup();
$prefix = Mage::getConfig()->getTablePrefix();
$installer->run("
CREATE TABLE IF NOT EXISTS ".$prefix."vote_competetion (
id int(10) NOT NULL AUTO_INCREMENT,
designid int(10) NOT NULL,
user_id int(10) NOT NULL,
vote tinyint(1) NOT NULL,
startdate datetime NOT NULL,
enddate datetime NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (designid) REFERENCES ".$prefix."vote_design(id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
");
Mage::getModel('core/url_rewrite')->setId(null);
$installer->endSetup();
Is there something wrong with my setter method name. All other values are being saved correctly. I am really not sure what to do about this. Please help.
I appreciate all the help.
Thanks!

If you didn't have user_id in the table from the start, you should clear the cache since Magento keeps it's structure cached and will not set any new columns data.

You have an error in naming of user id field. In table it is named as userid, so in your code you should call it like this:
$model= Mage::getModel('voter/competetion')
->setDesignid($designId)
->setUserid($user_id) // notice lowercase "i" here
->setVote($vote)
->setStartdate($startDate)
->save();
Or you can rename field in table from userid to user_id.

Related

Can't insert record with foreign key in MySQL?

I've got a user table, and a picture table.
The picture table has an uploader id column which is a foreign key.
It refers to the user id column in the user table.
For some reason, when I try to insert a new record into the picture table, it's not working. No error messages pop up. It just doesn't insert the new record.
INSERT INTO picture (pic_url, pic_uploader) VALUES($picurl, $uploader);
$picurl is an image src path from a file upload. The uploaded files are in the right directory, and the exact same code works perfectly for an earlier record without a foreign key.
$uploader contains the foreign key value -- from a session variable that contains the user id of the user account -- but it's not inserting it into the table.
Here's the SQL for the tables, in case that helps...
Picture table
CREATE TABLE IF NOT EXISTS picture (
pic_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
pic_url varchar(200) NOT NULL,
pic_uploader bigint(20) unsigned NOT NULL,
PRIMARY KEY (pic_id),
KEY pic_uploader (pic_uploader)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Picture constraints
ALTER TABLE picture
ADD CONSTRAINT pictures_ibfk_1 FOREIGN KEY (pic_uploader) REFERENCES user (user_id);
User table
CREATE TABLE IF NOT EXISTS user (
user_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
user_name varchar(80) NOT NULL,
user_img varchar(200) NOT NULL DEFAULT 'img/defaultpic.png',
user_email varchar(100) NOT NULL,
user_pword char(60) NOT NULL,
user_stat enum('0','1','A') NOT NULL,
PRIMARY KEY (user_id),
UNIQUE KEY user_email (user_email)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
There can be a reason that $uploader value does not exists in your user table as user_id.
First try to insert in simple way directly in db by any tool like sqlyog putty, mysqladmin etc.
INSERT INTO picture (pic_url, pic_uploader) VALUES('pic1', 'user1');
Make sure user1 should exist in user table. If it works fine then problem in your application other wise mysql will return an error by this we will be able to check the exact problem either it is due to foreign key or else. So do it and share results.
IN your picture table you are using columns NOT NULL.
But you try to insert only two values in the insert command that's why data is not inserted.
Either insert data for all columns or make columns as NULLABLE.
Thanks

How to recreate id column? [duplicate]

I am trying to alter a table which has no primary key nor auto_increment column. I know how to add an primary key column but I was wondering if it's possible to insert data into the primary key column automatically (I already have 500 rows in DB and want to give them id but I don't want to do it manually). Any thoughts? Thanks a lot.
An ALTER TABLE statement adding the PRIMARY KEY column works correctly in my testing:
ALTER TABLE tbl ADD id INT PRIMARY KEY AUTO_INCREMENT;
On a temporary table created for testing purposes, the above statement created the AUTO_INCREMENT id column and inserted auto-increment values for each existing row in the table, starting with 1.
suppose you don't have column for auto increment like id, no, then you can add using following query:
ALTER TABLE table_name ADD id int NOT NULL AUTO_INCREMENT primary key FIRST
If you've column, then alter to auto increment using following query:
ALTER TABLE table_name MODIFY column_name datatype(length) AUTO_INCREMENT PRIMARY KEY
For those like myself getting a Multiple primary key defined error try:
ALTER TABLE `myTable` ADD COLUMN `id` INT AUTO_INCREMENT UNIQUE FIRST NOT NULL;
On MySQL v5.5.31 this set the id column as the primary key for me and populated each row with an incrementing value.
In order to make the existing primary key as auto_increment, you may use:
ALTER TABLE table_name MODIFY id INT AUTO_INCREMENT;
Yes, something like this would do it, it might not be the best though. You might wanna make a backup:
$get_query = mysql_query("SELECT `any_field` FROM `your_table`");
$auto_increment_id = 1;
while($row = mysql_fetch_assoc($get_query))
{
$update_query = mysql_query("UPDATE `your_table` SET `auto_increment_id`=$auto_increment_id WHERE `any_field` = '".$row['any_field']."'");
$auto_increment_id++;
}
Notice that the the any_field you select must be the same when updating.
The easiest and quickest I find is this
ALTER TABLE mydb.mytable
ADD COLUMN mycolumnname INT NOT NULL AUTO_INCREMENT AFTER updated,
ADD UNIQUE INDEX mycolumnname_UNIQUE (mycolumname ASC);
I was able to adapt these instructions take a table with an existing non-increment primary key, and add an incrementing primary key to the table and create a new composite primary key with both the old and new keys as a composite primary key using the following code:
DROP TABLE IF EXISTS SAKAI_USER_ID_MAP;
CREATE TABLE SAKAI_USER_ID_MAP (
USER_ID VARCHAR (99) NOT NULL,
EID VARCHAR (255) NOT NULL,
PRIMARY KEY (USER_ID)
);
INSERT INTO SAKAI_USER_ID_MAP VALUES ('admin', 'admin');
INSERT INTO SAKAI_USER_ID_MAP VALUES ('postmaster', 'postmaster');
ALTER TABLE SAKAI_USER_ID_MAP
DROP PRIMARY KEY,
ADD _USER_ID INT AUTO_INCREMENT NOT NULL FIRST,
ADD PRIMARY KEY ( _USER_ID, USER_ID );
When this is done, the _USER_ID field exists and has all number values for the primary key exactly as you would expect. With the "DROP TABLE" at the top, you can run this over and over to experiment with variations.
What I have not been able to get working is the situation where there are incoming FOREIGN KEYs that already point at the USER_ID field. I get this message when I try to do a more complex example with an incoming foreign key from another table.
#1025 - Error on rename of './zap/#sql-da07_6d' to './zap/SAKAI_USER_ID_MAP' (errno: 150)
I am guessing that I need to tear down all foreign keys before doing the ALTER table and then rebuild them afterwards. But for now I wanted to share this solution to a more challenging version of the original question in case others ran into this situation.
Export your table, then empty your table, then add field as unique INT, then change it to AUTO_INCREMENT, then import your table again that you exported previously.
You can add a new Primary Key column to an existing table, which can have sequence numbers, using command:
ALTER TABLE mydb.mytable ADD pk_columnName INT IDENTITY
I was facing the same problem so what I did I dropped the field for the primary key then I recreated it and made sure that it is auto incremental . That worked for me . I hope it helps others
ALTER TABLE tableName MODIFY tableNameID MEDIUMINT NOT NULL AUTO_INCREMENT;
Here tableName is name of your table,
tableName is your column name which is primary has to be modified
MEDIUMINT is a data type of your existing primary key
AUTO_INCREMENT you have to add just auto_increment after not null
It will make that primary key auto_increment......
Hope this is helpful:)
Well, you have multiple ways to do this:
-if you don't have any data on your table, just drop it and create it again.
Dropping the existing field and creating it again like this
ALTER TABLE test DROP PRIMARY KEY, DROP test_id, ADD test_id int AUTO_INCREMENT NOT NULL FIRST, ADD PRIMARY KEY (test_id);
Or just modify it
ALTER TABLE test MODIFY test_id INT AUTO_INCREMENT NOT NULL, ADD PRIMARY KEY (test_id);
How to write PHP to ALTER the already existing field (name, in this example) to make it a primary key? W/o, of course, adding any additional 'id' fields to the table..
This a table currently created - Number of Records found: 4 name VARCHAR(20) YES
breed VARCHAR(30) YES
color VARCHAR(20) YES
weight SMALLINT(7) YES
This an end result sought (TABLE DESCRIPTION) -
Number of records found: 4
name VARCHAR(20) NO PRI
breed VARCHAR(30) YES
color VARCHAR(20) YES
weight SMALLINT(7) YES
Instead of getting this -
Number of Records found: 5
id int(11) NO PRI
name VARCHAR(20) YES
breed VARCHAR(30) YES
color VARCHAR(20) YES
weight SMALLINT(7) YES
after trying..
$query = "ALTER TABLE racehorses ADD id INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (id)";
how to get this? -
Number of records found: 4
name VARCHAR(20) NO PRI
breed VARCHAR(30) YES
color VARCHAR(20) YES
weight SMALLINT(7) YES
i.e. INSERT/ADD.. etc. the primary key INTO the first field record (w/o adding an additional 'id' field, as stated earlier.
No existing primary key
ALTER TABLE `db`.`table`
ADD COLUMN `id` INT NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (`id`);
;
Table already has an existing primary key'd column
(it will not delete the old primary key column)
ALTER TABLE `db`.`table`
ADD COLUMN `id` INT NOT NULL AUTO_INCREMENT FIRST,
CHANGE COLUMN `prev_column` `prev_column` VARCHAR(2000) NULL ,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`id`);
;
Note: column must be first for auto increment which is why the FIRST command.

Why doesn't automatically create at relation table? (in mysql)

create table Board (
boardID char(30) not null,
readLevel tinyint not null,
writeLevel tinyint not null,
PRIMARY KEY (boardID) ) engine=InnoDB character set=utf8;
create table Post (
postID int not null AUTO_INCREMENT,
title char(50) not null,
content TEXT not null,
writeDate date not null,
readCount int not null,
PRIMARY KEY (postID)) engine=InnoDB character set=utf8;
create table Save_Board_Post(
boardID char(30) not null,
postID int not null,
FOREIGN KEY (boardID) REFERENCES Board(boardID) ON UPDATE CASCADE,
FOREIGN KEY (postID) REFERENCES Post(postID) ON UPDATE CASCADE ) engine=InnoDB character set=utf8;
insert into Board (boardID, readLevel, writeLevel) values ('testBoard', 0, 0);
insert into Post (title, content, writeDate, readCount) values ('testPost1', 'test', CURRENT_TIMESTAMP() ,0);
select * from Board where boardID='testBoard';
select * from Post where tile='testPost1';
select * from Save_Board_Post where boardID='testBoard';
I'm rookie in sql. and I'm not native about English.
So, Please forgive my English skills.
Here's my mysql code.
Last five lines are for test. And select from Board and Post is working fine.
But
select * from Save_Board_Post where boardID= 'testBoard';
It doesn't work. This code has no error. but there is no output result.
I guess it means no data in Save_Board_Post table.
I thought REFERENCES command is automatically creation data when insert parent table.
If it does not, please let me know how to automatically creation in relation data.
No, that's not what REFERENCES does. All that your REFERENCES constraints mean is that every row that is inserted (manually) into the Save_Board_Post table must have a boardID and a postID that exist in the Board and Post tables. Nothing is inserted into that table automatically.
If you are trying to represent what board a post is in, the appropriate way to do this would be to make the board ID be a property of the post, e.g.
CREATE TABLE Post (
postID INTEGER NOT NULL AUTO_INCREMENT,
boardID CHAR(30) NOT NULL,
...
FOREIGN KEY (boardID) REFERENCES Board(boardID)
);
rather than having an entirely separate table just for that data.
You cannot automatically insert data in child table by inserting in the parent table. You got it right when you said it failed because there was no data in the table. Referential integrity exist to remove redundancy in a database. I dont think there is a way for you to automatically insert into the child table by inserting into a parent table. you have to do it manually.

Composite keys with AUTO_INCREMENT and CURRENT_TIMESTAMP working together

Similarly to many other questions about composite keys with AUTO_INCREMENT, I am receiving the following error:
Incorrect table definition; there can be only one auto column and it must be defined as a key
What I'm doing is making a history trail of all changes in the table. Every time a change is made, a new row is inserted with a new timestamp, leaving previous modifications untouched.
My DDL in concern is this:
DROP TABLE IF EXISTS personnel;
CREATE TABLE IF NOT EXISTS personnel
(
modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,
...
PRIMARY KEY (modified, id),
...
) ENGINE=InnoDB;
I presume that I'm getting this error because I am using both CURRENT_TIMESTAMP and AUTO_INCREMENT. So is there a way to resolve this without making PHP do the timestamp generation (so my model can just insert as if it were any other table, letting the controller do the dirty work).
MySQL's error message has more to be desired...
The autoincrementing column has to be at the beginning of an index. In your case you need to add another index - KEY id(id).

InnoDB foreign key difficulty?

Below I have two tables
users and users_profiles
Both are innoDB and collation: utf8_general_ci
They are as follows:
users
CREATE TABLE `users` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`status` char(10) NOT NULL,
`username` varchar(15) NOT NULL,
`email` varchar(50) NOT NULL,
`password` char(32) NOT NULL,
`reg_date` int(11) NOT NULL,
`ip` varchar(39) DEFAULT NULL,
PRIMARY KEY (`uid`),
UNIQUE KEY `username` (`username`,`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
users_profiles
CREATE TABLE `users_profiles` (
`uid` int(11) NOT NULL,
`first_name` varchar(40) DEFAULT NULL,
`last_name` varchar(50) DEFAULT NULL,
`gender` char(6) DEFAULT NULL,
`website` varchar(100) DEFAULT NULL,
`msn` varchar(60) DEFAULT NULL,
`aim` varchar(60) DEFAULT NULL,
`yim` varchar(60) DEFAULT NULL,
`twitter` varchar(15) DEFAULT NULL,
UNIQUE KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
After creating the tables in phpmyadmin I created a foreign key on the users_profiles table, code below is what phpMyAdmin created.
As follows:
ALTER TABLE `users_profiles`
ADD CONSTRAINT `users_profiles_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `users` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE;
basically the users_profiles.uid is a foreign key and references the users.uid
In phpMyAdmin I go to insert and fill in some sample data leaving the uid obviously to auto increment. When i have inserted a record in users table I goes into the users_profiles table and notice the users.uid is not inserted automatically in the users_profiles,
Is this normal?
Reason is when someone for example registers on a form, they will be asked for username, email and password, and i do a query in php to insert that data into users table, i thought that because i have a foreign key that it would also automatically insert a row in the users_profiles table with the uid from users table so there is a link between the user and there profile. But when i insert a record into users table the users.uid is not inserted into the users_profiles table.
I tried another example to see what would happen and this one works as i would expect due to the cascade on update and delete.
If i insert a row in users table and then manually insert the users.uid into users_profiles.uid (they are now linked) and add for example my first_name and last_name then in phpmyadmin delete the user from users table it deletes the row in the users_profiles table. This works like it should obviously as i don't want a user to be deleted and have there profile remain.
This has confused me as when I do create a form and a user signs up, they essentially would not have a profile because on signup no profile is created for them with there users.uid in the user_profiles table (no link between them) although I have a foreign key.
Can some explain why it's not working as I expect, maybe it should be working like I want it to but something is wrong or I am missing the whole point otherwise.
UPDATE
In reference to reply from #Mark Wilkins
I understand what you mean now. But something I am not 100% sure on is this:
User signs up, a record is created in users table; they login and visit profile page where the can fill it in and submit the form.
On processing the form am I right in thinking I would need to do the following:
user filled in profile form and submitted (first time they submitted profile as they are a new user), after validating data etc I first check to see if the uid in the users table match a uid in the users_profile table, if there's a match then UPDATE record with new values (this would mean the user has previously filled in there profile as on signup they don't have one) but if no match is found on uid from both tables then I would perform an INSERT query because no profile yet exists for the user. I take it that obviously I would store the uid from users table in session with other data on successful login and the uid in session would be the uid that is inserted into the users_profiles table in column uid? That way a link is created between two tables and if I now decide to delete the user there profile will also be deleted to.
Foreign key constraints are not designed to create rows. Their purpose is to ensure data integrity by forcing that a value in a child table that references a parent table value actually exists in that parent table and prevents a parent row from being deleted that has references to it in a child table.
On insert, the calling code must write rows into the two tables (first users then profiles).
If I followed the description correctly, it is working as expected. A foreign key relationship basically says that a parent must exist for a given child (a user must exist for a given user_profile in your example). It does not require the opposite (that a user_profile record exist for a user). It will never result in an INSERT being performed on the child table. You have to insert the record into the user_profile table and the foreign key relationship will guarantee that it is maintained.
Edit for the additional OP info: In general, yes I believe that is the thing you want to do. I have not dealt enough with web development to know if that particular process is correct. In either case, though (whether or not a profile record has been created), you will need to know which user to modify. My opinion about this, however, would be to create the associated user_profile record directly after creating the user record (just leave the informational fields empty in it). That way you know it exists when the go to edit it and you don't have to perform a MERGE style operation.

Categories