Codeigniter transaction query cannot rollback - codeigniter

I can input data type date with string
$data = array(
'date_added' => $this->input->post('category')
);
$this->um->add_data($data);
redirect('/subcategory');
but why invalid data cannot rollback, value data still insert to my table
function add_data($data){
$this->db->trans_begin();
$this->db->insert('subcategory', $data);
if($this->db->trans_status() === FALSE){
$this->db->trans_rollback();
}else{
$this->db->trans_commit();
}
}

Try this:
function add_data($data){
$this->db->trans_start();
$this->db->insert('subcategory', $data);
$this->db->trans_complete();
}
It will make automatically rollback your transaction if there's something wrong in your input process.
Reference Here

Related

CodeIgniter's insert_id() function is always returning 1

I have the following:
function insert_data($table=0,$data)
{
if($table !== 0)
{
if ($this->db->table_exists($table))
{
$this->db->insert($table,$data);
return $this->db->insert_id();
}
}
return 0;
}
I call it using
...
$insert_info = array(
'event_id' =>$id,
'checklist_name'=>$_POST['event_name'].' Checklist',
'checklist_type'=>2,
'status' =>1,
'created_by' =>$this->session->userdata('superadmin_id'),
'created_date' =>date('Y-m-d H:i:s'),
'updated_by' =>$this->session->userdata('superadmin_id'),
'updated_date' =>date('Y-m-d H:i:s')
);
$new_checklist_id = $this->db->insert('checklist_event',$insert_info);
echo $new_checklist_id;
die();
...
However, 1 is always echo'd. I can confirm there are a dozen or so records in the table so unsure why it's returning 1 each time. Any suggestions?
This is the structure of the table
However, 1 is always echo'd
you actually echo'ing out the return of the Query Builder Class insert() function, which is either true or false.
use this approach:
$this->db->insert('checklist_event',$insert_info);
$new_checklist_id = $this->db->insert_id();
echo $new_checklist_id; die();
You seem not to be calling the function insert_data($table=0,$data) at all

display message for database insert operation

Is there any mechanism that we can know that the data sent from app is successfully inserted to database, as in stored procedure, we use output parameter.
How can we be sure that the data is inserted into database and in case if the data insertion operation is failed, how to catch the error cause and display in a user friendly way?
// controller code
public function store(Request $request)
{
$validatedInput = $request -> validate([
'NBookName' => 'required|string|min:3|max:100',
'NBookId' => 'required|string|min:2|max:10|unique:books,BookID', // unique:table_name,column_name
'NBookUnitPrice' => 'required|max:5|'
]);
$book = new Book;
$book -> BookName = $request->input('NBookName');
$book -> BookID = $request->input('NBookId');
$book -> BookUnitPrice = $request->input('NBookUnitPrice');
$book->save();
return view('pages.about');
}
The Eloquent method save returns either true or false, thus checking the return of the save will let you know if the operation was successful.
You can alternatively use the method saveOrFail which will also return true / false, but may also give a Throwable
From the documentation: https://laravel.com/api/5.3/Illuminate/Database/Eloquent/Model.html#method_save
Examples:
if( $book->save() ){
return response()->json($book, 200);
} else {
return response()->json(['error' => 'Could not save'], 400);
}
or
try {
$book->saveOrFail();
return response()->json($book, 200);
} catch( \Exception $e ){
return response()->json(['error' => $e->getMessage()], 400);
}
save() will return a boolean, saved or not saved. So you can either do Like:
$saved = $book->save();
if(!$saved)
{
App::abort(500, 'Error');//Or return any message to view
}
For more details:check-if-laravel-model-got-saved-or-query-got-executed
I'd start off by separating the layer, I don't like watching validations, Eloquent queries and view related output in the same place.
Before reading the answer below, take a look at
https://laravel.com/docs/5.6/validation#form-request-validation
I'd make middleware to authenticate and authorize users, then use formrequests to validate the input data, and by the time it reaches the controller, the user is authenticated, authorized, data validated and all it's needed is call someone that is responsible for the insert operation and return something to the UI.
"How can we be sure that the data is inserted into database and in
case if the data insertion operation is failed"
Generally, a try catch will do:
public function store(Request $request)
{
try {
$validatedInput = $request -> validate([
'NBookName' => 'required|string|min:3|max:100',
'NBookId' => 'required|string|min:2|max:10|unique:books,BookID', // unique:table_name,column_name
'NBookUnitPrice' => 'required|max:5|'
]);
$book = new Book;
$book -> BookName = $request->input('NBookName');
$book -> BookID = $request->input('NBookId');
$book -> BookUnitPrice = $request->input('NBookUnitPrice');
$book->save();
} catch (\Exception $e) { 
// return your pretty response
// If the operation saving to the database fails, you'll get the information here on whatever it is about,
// as the generic exception catchs it. It should catch the stored procedure output aswell
}
return view('pages.about');
}
If you plan on having a series of insertions and updates/deletes and you don't want them to break logic (insert some and stop at inserting when 1 is wrong), you can use DB; and use DB::beginTransaction(), DB::commit() and DB::rollback() on your code
https://laravel.com/docs/5.6/database

Rollback not working in laravel multiple database in 5.2

Rollback not working in laravel multiple database in 5.2. What can i do? please help me. Advance thanks.
public function TestingRegistration(){
$now=date('Y-m-d H:i:s');
$faculty_user_account=array(
'user_id' =>'466297',
'name' => 'Hello',
);
\DB::beginTransaction();
try{
$save_registration=\DB::table('users')->insert($faculty_user_account);
$view2= \DB::connection('mysql_2')->table('users')->insert($faculty_user_account);
$view3 = \DB::connection('mysql_3')->table('users')->insert($faculty_user_account);
\DB::commit();
return \Redirect::back()->with('message',"Faculty Registration Successfull!");
}catch(\Exception $e){
\DB::rollback();
$message = "Message : ".$e->getMessage().", File : ".$e->getFile().", Line : ".$e->getLine();
return \Redirect::back()->with('errormessage',$message);
}
}
The easy way to do transaction is to use it as a callback, this way it will be handle it automatically for you.
public function TestingRegistration(){
$now = \Carbon::now(); // Where is this use?
$faculty_user_account = [
'user_id' => '466297',
'name' => 'Hello',
];
$success = \DB::transaction(function () use ($faculty_user_account) {
$save_registration = \DB::table('users')->insert($faculty_user_account);
$view2 = \DB::connection('mysql_2')->table('users')->insert($faculty_user_account);
$view3 = \DB::connection('mysql_3')->table('users')->insert($faculty_user_account);
return (bool) $view2 && $view3;
});
if (! $success) {
return \Redirect::back()->with('errormessage', 'Unable to save.');
}
return \Redirect::back()->with('message',"Faculty Registration Successfull!");
}
PS: I can't remember what insert returns, let me check later to make sure it can be use like that for testing success.

How to check if the record exist using codeigniter

I'm creating a registration form using codeigniter. I understand that there is a validation for each field in CI but what I want to do is to validate a multiple field exist.
SELECT emp_id FROM emp_record WHERE firstname = 'firstname' AND lastname = 'firstname' AND birthdate = 'firstname'
If the query above find a match I want to alert on my view page that the record already exist.
Please help.
Appreciate it. Thanks.
Declare a custom callback function
function _check_firstname()
{
$firstname = $this->security->xss_clean($this->input->post('firstname'));
$array = array('firstname' => $firstname, 'birthdate' => $firstname);
$result = $this->db->select('emp_id')->from('emp_record')->where($array)->get();
if($result->num_rows())
{
$this->form_validation->set_message('_check_firstname', 'Record already exists');
return false;
}else
{
return true;
}
}
Set rules including (callback__check_firstname)
$this->form_validation->set_rules('firstname', 'First Name', 'trim|required|callback__check_firstname');
Now, when you'll check validation like
if ($this->form_validation->run()){
// passes
}
else{
// not passes, so show the view again
}
In the view, if you have something like this
<?php echo form_error('firstname') ?>
This will show the error message set in the custom callback function.
You could use num_rows() to do such things.
By using active record you can achieve this by doing the following
$qry = $this->db->select('emp_id')->from('emp_record')
->where('firstname', $firstname)
->where('lastname', $lastname)
->where('birthdate', $birthdate)
->get();
if ($qry->num_rows() > 0)
return TRUE;
else
return FALSE;
This will return TRUE if it finds at least one row in your database or FALSE if it finds nothing.
some people can/may have the same firstname,lastname and birthdate
But still if you want to have it that way you could create a callback validation
here is a snippet.
public function checkinput()
{
// you may want to sanitize the input
$data['fname'] = $this->input->post('fname');
$data['lname'] = $this->input->post('fname');
$data['mname'] = $this->input->post('fname');
//your model for checking data must return TRUE or FALSE
if($this->model->method_for_checking($data))
{
this->form_validation->set_message('checkinput', 'Duplicate data exists.');
return TRUE;
}else{
return FALSE;
}
}
Now you can use it on your validation rules i.e
$this->form_validation('fname','fname',callback_checkinput);
Other options are
Extend a form validation and create a validation rule there as not
to clutter the controller
Or ,After Submitting the form before inserting the data, you can check whether it is a duplicate and do the logical things their.

CodeIgniter ActiveRecord problems

I'm trying to build my first app on CodeIgniter. This is also my first time trying to stick to OOP and MVC as much as possible. It's been going ok so far but now that I'm trying to write my first model I'm having some troubles. Here's the error I'm getting:
A Database Error Occurred
Error Number: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Castledine' at line 3
SELECT * FROM (authors) WHERE author = Earle Castledine
Which, as you'll see below, relates to the following line in my model:
$this->db->get_where('authors', array('author' => $author));
I'm not quite sure why it's throwing the error. Is it because Earle Castledine isn't in quotes? If so, why doesn't CI put them in there? I would doubt that's the issue, rather to think it's my fault, but I'm not sure.
I'm having another issue as well. Neither tags nor authors are getting inserted into their respective tables. Their insert statement is wrapped in a conditional that's supposed to be making sure they don't already exist, but it seems to be failing and the insert never happens. I assume it's failing because the tags aren't getting put in the database and it's down in the author section before it tosses the error. I know how to do this with pure PHP but I'm trying to go about doing it the pure CI ActiveRecord way.
Here's the statement I'm using:
if ($this->db->count_all_results() == 0)
And I'm using that instead of what I'd normally use:
if (mysql_num_rows() == 0)
Am I doing it wrong?
Here are my model and controller (only the functions that matter), commented as best I could.
Model:
function new_book($book, $tags, $authors, $read) {
// Write book details to books table
$this->db->insert('books', $book);
// Write tags to tag table and set junction
foreach ($tags as $tag) {
// Check to see if the tag is already in the 'tags' table
$this->db->get_where('tags', array('tag' => $tag));
// trying to use this like mysql_num_rows()
if ($this->db->count_all_results() == 0) {
// Put it there
$this->db->insert('tags', $tag);
}
// Set the junction
// I only need the id, so...
$this->db->select('id');
// SELECT id FROM tags WHERE tag = $tag
$query = $this->db->get_where('tags', array('tag' => $tag));
// INSERT INTO books_tags (book_id, tag_id) VALUES ($book['isbn'], $query->id)
$this->db->insert('books_tags', array('book_id' => $book['isbn'], 'tag_id' => $query->id));
}
// Write authors to author table and set junction
// Same internal comments apply from tags above
foreach ($authors as $author) {
$this->db->get_where('authors', array('author' => $author));
if ($this->db->count_all_results() == 0) {
$this->db->insert('authors', $author);
}
$this->db->select('id');
$query = $this->db->get_where('authors', array('author' => $author));
$this->db->insert('authors_books', array('book_id' => $book['isbn'], 'author_id' => $query));
}
// If the user checked that they've read the book
if (!empty($read)) {
// Get their user id
$user = $this->ion_auth->get_user();
// INSERT INTO books_users (book_id, tag_id) VALUES ($book['isbn'], $user->id)
$this->db->insert('books_users', array('book_id' => $book['isbn'], 'user_id' => $user->id));
}
}
Controller:
function confirm() {
// Make sure they got here by form result, send 'em packing if not
$submit = $this->input->post('details');
if (empty($submit)) {
redirect('add');
}
// Set up form validation
$this->load->library('form_validation');
$this->form_validation->set_error_delimiters('<h3 class="error">', ' Also, you’ll need to choose your file again.</h3>');
$this->form_validation->set_rules('isbn','ISBN-10','trim|required|exact_length[10]|alpha_numeric|unique[books.isbn]');
$this->form_validation->set_rules('title','title','required');
$this->form_validation->set_rules('tags','tags','required');
// Set up upload
$config['upload_path'] = './books/';
$config['allowed_types'] = 'pdf|chm';
$this->load->library('upload', $config);
// If they failed validation or couldn't upload the file
if ($this->form_validation->run() == FALSE || $this->upload->do_upload('file') == FALSE) {
// Get the book from Amazon
$bookSearch = new Amazon();
try {
$amazon = $bookSearch->getItemByAsin($this->input->post('isbn'));
} catch (Exception $e) {
echo $e->getMessage();
}
// Send them back to the form
$data['image'] = $amazon->Items->Item->LargeImage->URL;
$data['content'] = 'add/details';
$data['error'] = $this->upload->display_errors('<h3 class="error">','</h3>');
$this->load->view('global/template', $data);
// If they did everything right
} else {
// Get the book from Amazon
$bookSearch = new Amazon();
try {
$amazon = $bookSearch->getItemByAsin($this->input->post('isbn'));
} catch (Exception $e) {
echo $e->getMessage();
}
// Grab the file info
$file = $this->upload->data();
// Prep the data for the books table
$book = array(
'isbn' => $this->input->post('isbn'),
'title' => mysql_real_escape_string($this->input->post('title')),
'date' => $amazon->Items->Item->ItemAttributes->PublicationDate,
'publisher' => mysql_real_escape_string($amazon->Items->Item->ItemAttributes->Publisher),
'pages' => $amazon->Items->Item->ItemAttributes->NumberOfPages,
'review' => mysql_real_escape_string($amazon->Items->Item->EditorialReviews->EditorialReview->Content),
'image' => mysql_real_escape_string($amazon->Items->Item->LargeImage->URL),
'thumb' => mysql_real_escape_string($amazon->Items->Item->SmallImage->URL),
'filename' => $file['file_name']
);
// Get the tags, explode by comma or space
$tags = preg_split("/[\s,]+/", $this->input->post('tags'));
// Get the authors
$authors = array();
foreach ($amazon->Items->Item->ItemAttributes->Author as $author) {
array_push($authors, $author);
}
// Find out whether they've read it
$read = $this->input->post('read');
// Send it up to the database
$this->load->model('add_model', 'add');
$this->add->new_book($book, $tags, $authors, $read);
// For now... Later I'll load a view
echo 'Success';
}
}
Could anyone help shed light on what I'm doing wrong? Thanks much.
Marcus
Where you are using count_all_results(), I think you mean to use num_rows(). count_all_results() will actually create a SELECT COUNT(*) query.
For debugging your problems...
If you want to test if an insert() worked, use affected_rows(), example:
var_dump($this->db->affected_rows());
At any point you can output what the last query with last_query(), example:
var_dump($this->db->last_query());
You can also turn on the Profiler so you can see all the queries being run, by adding in the controller:
$this->output->enable_profiler(TRUE);
I managed to figure this out on my own. The controller didn't really change, but here's the new model:
function new_book($book, $tags, $authors, $read) {
// Write book details to books table
$this->db->insert('books', $book);
// Write tags to tag table and set junction
foreach ($tags as $tag) {
// Check to see if the tag is already in the 'tags' table
$query = $this->db->get_where('tags', array('tag' => $tag));
// trying to use this like mysql_num_rows()
if ($query->num_rows() == 0) {
// Put it there
$this->db->insert('tags', array('tag' => $tag));
}
// Set the junction
// I only need the id, so...
$this->db->select('id');
// SELECT id FROM tags WHERE tag = $tag
$query = $this->db->get_where('tags', array('tag' => $tag));
$result = $query->row();
// INSERT INTO books_tags (book_id, tag_id) VALUES ($book['isbn'], $query->id)
$this->db->insert('books_tags', array('book_id' => $book['isbn'], 'tag_id' => $result->id));
}
// Write authors to author table and set junction
// Same internal comments apply from tags above
foreach ($authors as $author) {
$query = $this->db->get_where('authors', array('author' => mysql_real_escape_string($author)));
if ($query->num_rows() == 0) {
$this->db->insert('authors', array('author' => mysql_real_escape_string($author)));
}
$this->db->select('id');
$query = $this->db->get_where('authors', array('author' => mysql_real_escape_string($author)));
$result = $query->row();
$this->db->insert('authors_books', array('book_id' => $book['isbn'], 'author_id' => $result->id));
}
// If the user checked that they've read the book
if (!empty($read)) {
// Get their user id
$user = $this->ion_auth->get_user();
// INSERT INTO books_users (book_id, tag_id) VALUES ($book['isbn'], $user->id)
$this->db->insert('books_users', array('book_id' => $book['isbn'], 'user_id' => $user->id));
}
}

Resources