Laravel skip constraint violation upon first time creating model - mysql

I want to know if it is possible to skip or ignore the constraint violation upon creating a user. I have a user model with a foreign key address_id.
Schema::table('user', function($table) {
$table->foreign('address_id')->references('address_id')->on('address')->onDelete('cascade');
});
Upon creating a user i want to create a user without a address yet which will be added later on.
return User::create([
'first_name' => $data['firstname'],
'last_name' => $data['lastname'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
but hence the constraint violation. It is possible to do this?
EDIT:
Thus i would like to keep the constraints but the example above runs into a constraint violation so what is the best way to work around this? Making a dummy address entry?

You can alter the DB for the time you are adding the model:
protected function turnOffDatabaseChecks()
{
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
Eloquent::unguard();
}
protected function turnOnDatabaseChecks()
{
DB::statement("SET sql_mode = 'STRICT_ALL_TABLES';");
Eloquent::reguard();
}
Then in your user model:
$this->turnOffDatabaseChecks();
$user = User::create([
'first_name' => $data['firstname'],
'last_name' => $data['lastname'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
$this->turnOnDatabaseChecks();
return $user;
However, I'd be very cautious in using this and would ask yourself why you have a foreign key constraint that you wish to ignore.

Related

Yii2 console migration down with a different connection fails

Am trying to perform console migrations to a different connecton but down fails
in my connection i have
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=pos_db',
....other configs
],
'connection_identifier' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=newdbo',
...other configs
],
In my console i have
public function init()
{
$this->db = 'connection_identifier';
parent::init();
}
public function safeUp()
{
$this->createTable('database_connection_domains', [
'id' => $this->primaryKey(),
'domain'=>$this->text()->notNull(),
'connection_id'=>$this->integer()->notNull(),
'created_at' => $this->integer()->notNull(),
'status'=>$this->integer()->defaultValue(0),
'FOREIGN KEY (connection_id) REFERENCES database_connections (id) ON DELETE RESTRICT ON UPDATE CASCADE',
]);
}
/**
* {#inheritdoc}
*/
public function safeDown()
{
$this->dropTable('database_connection_domains');
}
When i run the up migration the database in correctly created on the newdbo database. The problem comes in during down command where the table is not dropped. How do i make this drop the table.
When i run /yii migrate/fresh am getting an error Base table or view already exists: 1050 Table 'database_connections' already exists which means that the table is not dropped
What am i missing?
./yii migrate/fresh does not use migrations to cleanup database, is uses custom implementation which just deletes all tables in correct order. So your settings for DB component are never used. You need to configure database on command call:
./yii migrate/fresh --db=connection_identifier

Checking 2 Column for Duplicate

Currently, I have a system to hold main data
1) The email
2) The owner(user_id)
Every time someone uploads , I need to make sure that it doesn't not exist in the system. The catch is as I upload more and more, the amount of time taken to check for duplicate will grow steeply, just like the graph as shown.
Question
1) How do i check for duplicate efficiently?
2) I indexed the user_id and the email should I Fulltext it? I wont be reading the text but will be searching for it as a whole, so index is more logical?
3) I also read about creating Hash combining email&owner id then index the hash. Will it be a big difference from the current method?
4) Last method i thought of was to create a primary key for both email and user_id , once again idk how the performance would turn out.
Please advice.
Code
$exist = DB::table('contact')->where('email', $row['email'])->where('user_id', $user_id)->count();
if($exist < 1){
DB::table('contact')->insert(
['email' => $row['email'], 'name' => $row['name'], 'user_id' => $user_id]
);
}
Use Laravel Validator:
public function store(Request $request)
{
$this->validate($request, [
'user_id' => 'required|unique',
'email' => 'required|unique',
]);
//some logic here
}
Also you should use unique constraint in your database.

Yii2: Add 'user_id' when create a post

I have a 'post' table with attribute 'user_id' in it to know who have posted that post. I run into a problem, when create a post, the 'user_id' didn't add into database, which can't be null, so I can't continue from there. So how can I add 'user_id' of the user that is currently logging in, automatically.
I'm using Yii2 basic template.
Thanks
Or you could have a look at Blameable Behavior
BlameableBehavior automatically fills the specified attributes with the current user ID.
I use this in alot of my projects (often combined with sluggable and timeable) and its easy to use, just put the following in your Post model:
use yii\behaviors\BlameableBehavior;
public function behaviors()
{
return [
[
'class' => BlameableBehavior::className(),
'createdByAttribute' => 'user_id',
'updatedByAttribute' => false,
'attributes' => [
ActiveRecord::EVENT_BEFORE_VALIDATE => ['user_id'] // If usr_id is required
]
],
];
}
Referencing Behavior validation on validation behaviors.
If you want to do it manually like the other answers suggest, you need to change
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
to
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$model->user_id = \Yii::$app->user->identity->id
$model->save()
return $this->redirect(['view', 'id' => $model->id]);
}
Remember: when you validate before inputting the user id, the user_id can't be required in your model rules!
Apart from what Bloodhound suggest, you can also use the following code to get the currently logged in user ID:
$loggedInUserId = \Yii::$app->user->getId();
you can try this code
//To get whole logged user data
$user = \Yii::$app->user->identity;
//To get id of the logged user
$userId = \Yii::$app->user->identity->id
Look at the documentation for more details: doc .

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!

Problem with sfValidatorDoctrineChoice

The code is:
$query = Doctrine_Core::getTable('Users')->createQuery('u')
->select('u.email')
->where('u.username = ?', $this->getRequest()->getCookie('vL_username'))
->andWhere('u.password = ?', md5($editprofile['password']));
$this->form->setValidators(array(
'password' => new sfValidatorDoctrineChoice(array(
'model'=>'Users',
'column'=>'password',
'query'=>$query,
), array(
'invalid' => 'The password is wrong.',
'required' => 'Required',
)
),
));
But it's not working. It automatically adds AND WHERE password = 'whatever the inputed value is (unencrypted)'
The idea is that I need to encrypt using md5 the input value before checking against the record in the db. If I delete 'column'=>'password', and only leave the $query, it automatically adds the inputed value as id! (Which is the primary key of the table).
In my case I don't need sfValidatorDoctrineChoice to write the query, just to use mine to check if a record exists with the given parameters. How can I do this?
The solution I found and works:
$editprofile=$request->getParameter('editprofile');
$editprofile['password']=md5($editprofile['password']);
$request->setParameter('editprofile', $editprofile);
Maybe there's a better one.