Drupal 7 Mysql query (Insert) - mysql

I'm new to Drupal.
So I was wondering if you can help me.
I saw a lot of documents regarding the Drupal API mysql thing-y and It's been bugging me that I have to study once more to finish my work done.
And here's the documentation that I'm applying to my problem
Regarding my problem about the INSERT function, I have this table entitled embed
and here is my data from the table embed.
Then on my basic page I'm trying to insert a query.
$id = db_insert("embed")
->fields(array(
'uid' => 1,
'fbp_id' => 22222,
'prom_stat' => 3333,
'status' => 1,
))
->execute();
Instead of inserting a data to the table, it outputs an error like this.
Anyone knows the solution for this stuff? I'm really confused about this right now.

As #steve has suggested in the comment, the issue is not on drupal side but on MySql side. You need to modify your insert code to
$id = db_insert("embed")
->fields(array(
'uid' => 1,
'fbp_id' => 22222,
'prom_stat' => 3333,
'status' => 1,
'prom_id' => 0,
'sweep_stat' => 0,
'sweep_id' => 0,
'comp_id' => 0,
'comp_stat' => 0,
'polls_stat' => 0,
'polls_id' => 0
))
->execute();
Since i can see that your MySql table already contains value, i assume the earlier inserts where done by explicitly providing all values, instead of relying on default values for the field in MySql configuration.
Whenever you have a PDOException you should read it carefully for clues. These kind of errors are really very verbal and gives lots of pointers to resolve the issues. For example in your case,
'prom_id' doesn't have a default value
explains a lot.

Related

Custom functions for non-select queries Cake Query Builder

I would like to use the mariadb INET_ATON() on an insert query with Cakephp Query Builder.
INSERT INTO failed_logins
SET email = 'example#test.com', ip_address = INET_ATON('192.168.0.1'), sent_email = 1;
Then I'd like to retrieve the data with INET_NTOA() in a select query.
SELECT id, email, INET_NTOA(ip_address) AS ip_address, sent_email FROM failed_logins;
How do I use these functions with an insert and select on the Cake Query Builder?
I saw Using SQL functions but couldn't solve my issue.
After a lot of playing around I managed to make it work.
$this->connection->newQuery()->into('failed_logins');
$newIp = $query->func()->inet_aton([$ip]);
$query->insert(['email', 'ip_address', 'sent_email'])->values(
['email' => $email, 'ip_address' => $newIp, 'sent_email' => $sentEmail]
)->execute()->lastInsertId();
Quite complicated and my IDE and PHPStan show me warnings that the function "inet_aton" is not defined.
I would have loved it if in the values() array I could have just done it like ['ip_address' => "INET_ATON($ip)"]. Edit: This is not a good idea see comments. But something similar that stays safe can be done with ->bind() (code snippet below).
Edit: Removed 'literal' from the code snippet (thanks #ndm)
IDE and Analysis Tool - friendly solution
$this->connection->newQuery()->into('failed_logins');
$query->insert(
[
'email',
'ip_address',
'sent_email',
]
)->values(
[
'email' => $email,
'ip_address' => $query->newExpr("INET_ATON(:ip)"),
'sent_email' => $sentEmail,
]
)->bind(':ip', $ip, 'string')->execute()->lastInsertId();

Newly added field to table is completely ignored

I am completely new to Drupal. I inherited a very ugly and incorrect code, unfortunately. In fact I would like to implement a proper login-with-facebook feature, which was totally mis-implemented. It tried to identify users by their email address, however, for some reason, upon login with Facebook, users logged in with the wrong user. I would like to identify the user based on Facebook ID, however, there was no column for that purpose in the database.
As a result, I have implemented a small script, which added a facebook_id and a facebook_token to the table representing the users. However, these new columns are not seen by the drupal_get_schema function in bootstrap.
If I do this:
$schema = drupal_get_schema("users");
echo var_dump($schema["fields"]);
It shows the fields except the two newly created fields. This way a SchemaCache object is initialized. I assumed that the schema might be cached. So I tried something different:
$schema = drupal_get_schema("users", true);
echo var_dump($schema["fields"]);
to make sure that drupal_get_complete_schema(true) will be called. However, the fields are not seen this way either. Is there a way I can tell Drupal to acknowledge the existence of the two newly created columns? If not: what should I do? Should I remove the two columns from the database table and use db_add_field("users", "facebook_id") and db_add_field("users", "facebook_token") respectively? If so, where should I call these?
Sorry if the question is too simple or I am misunderstanding these technologies, but I have tried to solve this for hours and I am at a loss, because this is my first drupal/bootstrap project and the source-code using these does not help me at all.
EDIT:
Since, at the time of this writing I have not received any answers apart from a tool recommendation which did not address my question, I have continued my research in the area. I removed the columns from the database to create them in a Drupal way. I have implemented this function in user.module:
function user_schema_alter() {
db_add_field('users', 'facebook_id', array(
'type' => 'varchar', //was initially a bigint, but Drupal generated a query which always crashed
'length' => 20,
'not null' => TRUE,
'default' => ".", //was initially -1, but Drupal generated a query which always crashed
));
db_add_field('users', 'facebook_token', array(
'type' => 'varchar',
'length' => 300,
'not null' => TRUE,
'default' => 'unavailable',
));
}
and I invoke it from altconnect.module, like this:
$schema = drupal_get_schema("users");
if (!isset($schema["fields"]["facebook_id"])) {
user_schema_alter();
}
It creates the columns, but later the existence of those columns will not be known about and subsequently an error will be thrown as the code will try to re-create them. Besides the fact that I had lost a lot of time until I realized that Drupal is unable to support bigint fields having -1 as their default value I had to conclude that with this solution I am exactly in the same situation as I were initially, with the difference that with this Drupal solution I will always get an exception if the columns already exist, because the schema will not be aware of them and subsequently, the code will always enter that if.
I fail to understand why is this so difficult in Drupal and I totally fail to understand why trying
db_add_field('users', 'facebook_id', array(
'type' => 'bigint',
'length' => 20,
'not null' => TRUE,
'default' => -1,
));
throws an exception due to syntax error. Maybe I should just leave this project and tell anyone who considers using Drupal to reconsider :)
I was able to find out what the answer is, at least for Drupal 6.
In user.install we need to do the following:
//...
function user_schema() {
//...
$schema['users'] = array(
//...
'fields' => array(
//...
'facebook_id' => array(
'type' => 'varchar',
'length' => 20,
'not null' => TRUE,
'default' => ".",
),
'facebook_token' => array(
'type' => 'varchar',
'length' => 300,
'not null' => TRUE,
'default' => 'unavailable',
),
//...
),
//...
}
//...
/**
* Adds two fields (the number is some kind of version number, should be the biggest so far for the module)
*/
function user_update_7919() {
db_add_field('users', 'facebook_id', array(
'type' => 'varchar',
'length' => 20,
'not null' => TRUE,
'default' => ".",
));
db_add_field('users', 'facebook_token', array(
'type' => 'varchar',
'length' => 300,
'not null' => TRUE,
'default' => 'unavailable',
));
}
When this is done, log in with the admin user and go to http://example.com/update.php
There you will see the thing to be updated. Run it. If you wonder why do we have to do all this, why don't we run some scripts directly, then the answer is that this is how Drupal operates. It simplifies your life by making it complicated, but do not worry, while you wait for update.php to do the updates which would take less than a second if it was your script, you can ponder about the meaning of life, quantum-mechanics or you can try to find out the reason this is so over-complicated in Drupal and you can go out for a walk. When you focus again, if you are lucky, update.php has completed its job and the two columns should be in the database.

CakePHP 1.3 not saving to database but sql statement is correct and insertID is increased correctly

I already searched many forums for my really strange issue, but I still can't figure out whats going wrong during my save process... The issue: Cake says, my data was saved, creates an autoincrement-ID but no record is stored in the database.
The environment
I have a cake-1.3.13 app running for some time and now needed to add another database table, which is of course related to other tables. My problem is saving records for the habtm-relation table, which looks like this:
CREATE TABLE IF NOT EXISTS `employees_projects_rejectreasons` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`employees_project_id` int(10) unsigned NOT NULL,
`rejectreason_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `employees_project_id` (`employees_project_id`,`rejectreason_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6;
I scaffolded the simple model only with basic validation criteria.
<?php
class EmployeesProjectsRejectreason extends AppModel {
var $name = 'EmployeesProjectsRejectreason';
var $validate = array(
'employees_project_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'rejectreason_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'EmployeesProject' => array(
'className' => 'EmployeesProject',
'foreignKey' => 'employees_project_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Rejectreason' => array(
'className' => 'Rejectreason',
'foreignKey' => 'rejectreason_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
I created several records for Rejectreasons and EmployeesProjects, so I have some valid entries here in the database. Now I want to link them together by creating a new record in the given employees_projects_rejectreasons table. I try to do this from another controller (the EmployeesProjectsController). Here is my latest attempt to save the data:
$this->EmployeesProject->EmployeesProjectsRejectreason->create();
$eprData = array(
'EmployeesProjectsRejectreason' => array(
'employees_project_id' => (int)$id,
'rejectreason_id' => (int)$rrId
)
);
if($this->EmployeesProject->EmployeesProjectsRejectreason->save($eprData)) {
debug('successfully saved EPR with ID '.$this->EmployeesProject->EmployeesProjectsRejectreason->__insertID);
} else {
debug('could not save EPR with employees_project_id='.$id.' and rejectreason_id='.$rrId);
}
Now what happens
After I make an attempt to save a record, my debug gives me the following success report:
successfully saved EPR with ID 4
So the save() call returned true, a new ID was created by the auto_increment function of mySQL. So far so good. But when I check my database, there was no record created. But the auto_increment_counter was increased by 1, as if a record was stored, but it wasn't.
Running the app with debug-level 2, I can see the generated SQL-statement from cake, which looks perfectly fine to me:
INSERT INTO `employees_projects_rejectreasons` (`employees_project_id`, `rejectreason_id`) VALUES (3, 3)
If I run this statement directly on the sql server, the record ist inserted correctly.
What I already tried
I already tried different approaches with the save procedure. I tried working with setters instead of a data-array:
$this->EmployeesProject->EmployeesProjectsRejectreason->set('employees_project_id', $id);
as well, but it made no difference. After I wrote a custom save-method in the EmployeesProjectsRejectreason-Model, calling it from the controller, but it always produced the same result.
I tried
deleting the model-cache
restarting the server-instances and the server itself
Deleting the table and creating it again
disabling validation in the model
removing the unique foreign-key index
Saving with hard-coded and existing ids as foreign key
Some more strange behaviour
The last tests with hard-coded IDs in my controller code confronted me with more riddles: If I try storing existent foreign_key-IDs, the data is not saved as before. But if both IDs are hardcoded and NOT EXISTING (I used invented IDs 345 AND 567, which are definetely not existing in the database) a record was finally inserted!
Moreover I scaffolded Models, Views and Controllers for the new tables. When I run the scaffolded view "myApp/employees_projects_rejectreasons/add" and add a new record, everything works just fine.
I'm just not able to save the record from other controllers. Since I already have a huge headache, solving this problem, I highly appreciate any hint for a solution!!
Thanks in advance guys!
I finally found a solution to solve the issue. I still don't know, why the save code before did not work, but here is how I changed my code to make it work:
From my form, the data array comes in the following format:
Array
(
[EmployeesProject] => Array
(
[id] => 10
[user_id] => 0
[additional_information] => some comment text
[state] => absage
[Rejectreason] => Array
(
[0] => 1
[1] => 8
)
)
)
I searched for some solutions to save habtm relations in cakePHP directly with one call, but that does not seem to be possible in cake-1.3. So I created this pretty simple save routine in my EmployeesProjectController, which works perfectly fine for me:
if (!empty($this->data)) {
if ($this->EmployeesProject->save($this->data)) {
if(array_key_exists('Rejectreason', $this->data['EmployeesProject'])) {
foreach($this->data['EmployeesProject']['Rejectreason'] as $key => $rrId) {
$this->EmployeesProject->EmployeesProjectsRejectreason->create();
$this->EmployeesProject->EmployeesProjectsRejectreason->set('rejectreason_id', $rrId);
$this->EmployeesProject->EmployeesProjectsRejectreason->set('employees_project_id', $this->data['EmployeesProject']['id']);
if($this->EmployeesProject->EmployeesProjectsRejectreason->save()) {
}
}
}
}
}
Thanks #Yoggi for supporting me solving this issue!

How do i deploy a schema correctly with DBIx::Class?

i'am new to Databases and to DBIx:Class. So please forgive me if this is a total newbie fault.
I just followed a tutorial and then i tried to deploy the schema to my database. According to the tutorial i split the modules up in several files. After i ran createTable.pl 'mysqlshow bla' shows me a empty database.
Database is up and running. Creating a table via the mysql CREATE TABLE statement does work.
Skript file which should create a table according to the schema ../createTable.pl
#!/usr/bin/env perl
use Modern::Perl;
use MyDatabase::Main;
my ($database, $user) = ('bla', 'flo');
my $schema = MyDatabase::Main->connect("dbi:mysql:dbname=$database", "$user");
$schema->deploy( { auto_drop_tables => 1 } );
Main.pm for loading the namespaces ../MyDatabase/Main.pm
package MyDatabase::Main;
use base qw/ DBIx::Class::Schema /;
__PACKAGE__->load_namespaces();
1;
Schema file for the table ../MyDatabase/Result/Album.pm
package MyDatabase::Main::Result::Album;
use base qw/ DBIx::Class::Core /;
__PACKAGE__->load_components(qw/ Ordered /);
__PACKAGE__->position_column('rank');
__PACKAGE__->table('album');
__PACKAGE__->add_columns(albumid =>
{ accessor => 'album',
data_type => 'integer',
size => 16,
is_nullable => 0,
is_auto_increment => 1,
},
artist =>
{ data_type => 'integer',
size => 16,
is_nullable => 0,
},
title =>
{ data_type => 'varchar',
size => 256,
is_nullable => 0,
},
rank =>
{ data_type => 'integer',
size => 16,
is_nullable => 0,
default_value => 0,
}
);
__PACKAGE__->set_primary_key('albumid');
1;
I already spent some hours on finding help through google but there isn't much related to the deploy() method.
Can anyone explain me what my mistake is?
Thank you
You can find the documentation for all CPAN Perl modules on metacpan.org (newer, full-text indexed) and search.cpan.org.
Read the docs for DBI, you'll find an environment variable called DBI_TRACE that when set will print every SQL statement to STDOUT.
DBIx::Class has a similar called DBIC_TRACE.
The first one should help you to see what the deploy method is doing.
Is no password required for connecting to your database?
Ok today i played again with perl and database stuff and i found out what the mistake was.
First of all i started with DBI_TRACE and DBIC_TRACE, it produced a lot of messages but nothing i could handle, for me it seemed like nothing gave me a hint on the problem.
Then i searched google for a while about this problem and for more examples of the deploy method. At some point i noticed that my folder structure is wrong.
The Schema file for the table should be placed in
../MyDatabase/Main/Result/Album.pm
instead of being placed in
../MyDatabase/Result/Album.pm
After moving the Schema file to the correct folder everything worked well.
Shame on me for this mistake :( But thank you for your help

codeigniter mysql query problem

I execute a simple insert query, however this insert is done multiple times sometimes unexpectedly. The code for insert is :
$query=$this->db->query("INSERT INTO clientaccesshistory (jobid, clientid,firstname,lastname,clientname,menu,submenu,starttime) VALUES ('$time','$userID','$firstname','$lastname','$clientname','Monitor/Verify', '$this->job_name',current_timestamp() )");
When i look in the database though this information is sometimes there 3 times, sometimes its just once like it is supposed to be. I think this is some issue with connecting to mysql, and then retries till it inserts three times?
I tested the front end to see if the function is actually be called more than once by putting an alert there, but no problem there whatsoever.
Your code almost certainly has to be in a variable loop of some kind. This code, like wonk says, will not add more than one record, ever.
This won't be of much help, but you can try using this-
$arr = array(
jobid => $time,
clientid => $userID,
firstname => $firstname,
lastname => $lastname,
clientname => $clientname,
menu => 'Monitor/Verify',
submenu => $this->job_name,
starttime => current_timestamp()
);
$this->db->insert('clientaccesshistory', $arr);