Custom Error in Active Record Codeigniter - php

I am using HMVC. My question is very simple. how we can catch the error in active records?
how we can return custom error to controller from model(active records)?
Actually, msn column is unique so, when i enter duplicate value then its show error like
Error Number: 1062
Duplicate entry '3696003284' for key 'msn'
but i want to show custom error instead of this.
my simple code is:
function insert_data($msn_number, $date_val, $min_val, $max_val, $avg_val,$counter)
{
for($i=0;$i<$counter;$i++)
{
$data = array(
'msn' => $msn_number[$i],
'date' => $date_val[$i],
'min_val' => $min_val[$i],
'max_val' => $max_val[$i],
'average' => $avg_val[$i]
);
$result = $this->db->insert('storage_data', $data);
if(!isset($result))
{
echo "custom Error";
}
}
}
}
i am wondering for the answer of this question please help me!

You may try this:
$result = $this->db->insert('storage_data', $data);
if (!$result) {
$data['msg'] = $this->db->_error_message();
$this->load->view('viw_db_error', $data); // Create a viw_db_error.php view
}
Make sure DB_DEBUG is set to FALSE in the application/config/database.php file, or execution will be halted if a mysql error occurs.
Update:
Alternatively you may query for that before every time you insert a new record but it would be very expensive because you are doing it inside a loop and it'll send many query/requests:
$q = $this->db->query("select msn from storage_data where msn = $msn_number[$i]");
if( $q->num_rows() ) {
// It already exists so maybe display a message
}

Related

Mysql record missing when server lag

Customer use the app which create the order to deliver goods. In the database, it will generate the order_delivery table;
And then generate the goods_stock_vary_history table that record the changes of goods stock;
They are in one transaction.
The order_delivery has one goods_stock_vary_history.
But one day the customer created the order when server lag. And then he exist the app and create order again.
After a while, he say he cannot see his order.
I found the record of goods_stock_vary_history and its field order_delivery_id has value 2;
So I try to find order_delivery that primary key is 2.
And I cannot find it. There have primary keys 1 and 3 etc. The primary key is auto increment;
order_delivery has soft delete only; Nobody can delete that record.
The project use Laravel5.1 and the codes like below:
DB::beginTransaction();
foreach ($order_goods_matrix as $order_id => $goods_matrix) {
$goods_amount = OrderServices::countGoodsColorSizeMatrixAmount($goods_matrix);
if($goods_amount==0){
DB::rollback();
Redis::del($user_id . '_good_delever');
return $this->fail(self::ERROR_CODE, "Deliver Fail. The count cannot be zero");
}
if (intval($order_id) > 0 && $goods_amount > 0) {
$goods_matrix = json_encode($goods_matrix, true);
// Create order delivery
$ret = OrderServices::createDelivery($exist_flag, $user_id, $store_id, $order_id, $goods_matrix, OrderDelivery::DELIVERY_TYPE_COMMON, $created_at);
if ($ret['code'] < 0) {
DB::rollback();
Redis::del($user_id . '_good_delever');
return $this->fail(self::ERROR_CODE, "Deliver Fail" . $ret['msg']);
}
$get_history_id_arr[] = $ret['get_stock_histtory']['goods_stock_vary_history_id'];
}
}
$store_goods_sku = GoodsServiceV3::getGoodsSku($store_id);
foreach ($get_history_id_arr as $get_history_id_info) {
$get_history_detail[] = GoodsStockServiceV2::getGoodsStockVaryHistoryDetail($store_id, $get_history_id_info);
}
DB::commit();
in the function createDelivery:
$order_delivery = array();
$order_delivery['order_id'] = $order_id;
$order_delivery['customer_id'] = $order_base["buyer_user_id"];
$order_delivery['delivery_goods_color_size_matrix'] = $delivery_goods_color_size_matrix;
$order_delivery['delivery_goods_amount'] = $delivery_goods_amount;
$order_delivery['operate_user_id'] = $user_id;
$order_delivery['delivery_type'] = $delivery_type;
$order_delivery['exist_flag'] = $exist_flag;
$order_delivery['deliver_timestamp'] = $created_at;
$order_delivery_id = OrderDelivery::insertGetId($order_delivery);
if ($order_delivery_id == false) {
return array('code' => -3, 'msg' => 'Deliver fail');
}
$reverse_delivery_goods_color_size_matrix_array = GoodsStockServices::reverseGoodsColorSizeMatrix($delivery_goods_color_size_matrix_array);
// create goods_stock_vary_history
$get_stock_histtory = GoodsStockServices::addStockVariation($exist_flag, $user_id, $store_id, $reverse_delivery_goods_color_size_matrix_array, GoodsStockServices::STOCK_TYPE_DELIVER, GoodsStockServices::STOCK_TYPE_DELIVER_DEFAULT_REMARK, $order_delivery_id, null, $order_base["buyer_user_id"], $created_at);
return array('code' => 0, 'order_delivery_id' => $order_delivery_id, 'get_stock_histtory' => $get_stock_histtory);
I found the reason.
I created a trigger to track each order_delivery records after be deleted.
And then I found that order_delivery record is still missing, and the track table doesn't have any records.
So the missing order_delivery record is not deleted by someone or some method.
So I think the missing record is not missing, it just rollback, and another order_delivery inserted before it rollback, that make it like missing.
And then I try to log every database operation result for getting details.
I found there is a line not deal with the fail operation.
These code is written two years ago, the transaction part is smelly, you need to manually rollback the fail operation. and return fail message.
The better way is like this:
DB::beginTransaction();
try {
...
OrderServices::createDelivery($exist_flag, $user_id, $store_id, $order_id, $goods_matrix, OrderDelivery::DELIVERY_TYPE_COMMON, $created_at);
...
DB::commit();
} catch(\Throwable $e) {
DB::rollback();
throw $e;
}
After I change it, the missing record phenomenon not showing again.

Database data field check before Data insertion

I have a data coming from the HTML Page. And i want to check whether the date and the place values already exists. If they exists, it should throw an error saying Data is already present, if those date and place data is not there it should allow the user to save it.
Here is the code which i have written to save it,
public function StoreSampling(Request $request)
{
$date = Carbon::createFromFormat('d-m-Y', $request->input('date'))->format('Y-m-d');
$doctorname = Input::get('doctorselected');
$product = Input::get('product');
$product= implode(',', $product);
$quantity = Input::get('qty');
$quantity =implode(',',$quantity);
$representativeid = Input::get('representativeid');
//Store all the parameters.
$samplingOrder = new SamplingOrder();
$samplingOrder->date = $date;
$samplingOrder->doctorselected = $doctorname;
$samplingOrder->products = $product;
$samplingOrder->quantity = $quantity;
$samplingOrder->representativeid = $representativeid;
$samplingOrder->save();
return redirect()->back()->with('success',true);
}
I searched some of the Stack over flow pages. And came across finding the existence through the ID And here is the sample,
$count = DB::table('teammembersall')
->where('TeamId', $teamNameSelectBoxInTeamMembers)
->where('UserId', $userNameSelectBoxInTeamMembers)
->count();
if ($count > 0){
// This user already in a team
//send error message
} else {
DB::table('teammembersall')->insert($data);
}
But i want to compare the date and the place. And if they are not present, i want to let the user to save it. Basically trying to stop the duplicate entries.
Please help me with this.
There are very good helper functions for this called firstOrNew and firstOrCreate, the latter will directly create it, while the first one you will need to explicitly call save. So I would go with the following:
$order = SamplingOrder::firstOrNew([
'date' => $date,
'place' => $place
], [
'doctorname' => Input::get('doctorselected'),
'product' => implode(',', Input::get('product')),
'quantity' => implode(',',Input::get('qty')),
'representativeid' => Input::get('representativeid')
]);
if($order->exists()) {
// throw error
return;
}
$order->save();
// success
You need to modify your query to something like this:
$userAlreadyInTeam = SamplingOrder::where('date', $date)
->where('place', $place) // I'm not sure what the attribute name is for this as not mentioned in question
// any other conditions
->exists();
if (userAlreadyInTeam) {
// Handle error
} else {
// Create
}
You do not need to use count() as your only trying to determine existence.
Also consider adding a multi column unique attribute to your database, to guarantee that you don't have a member with the same data and place.
The best way is to use the laravel unique validation on multiple columns. Take a look at this.
I'm presuming that id is your primary key and in the sampling_orders table. The validation rule looks like this:
'date' => ['unique:sampling_orders,date,'.$date.',NULL,id,place,'.$place]
p.s: I do not see any place input in your StoreSampling()

Codeigniter 3 model function no return variable

I'm making a project where a user can publish/post their own stories and read others' stories. Very simple.
This is my controller method named publish:
public function published()
{
$story = array('author' => $this->session->userdata('username'),
'title' => $this->input->post('title'),
'synopsis' => $this->input->post('synopsis'));
$new_storyid = $this->story_model->new_story($story);
if($new_storyid != NULL)
{
$genre = $this->input->post('genre');
for($temp=0;$temp<count($genre);$temp++)
{
$genres[$temp] = array('story_id' => $new_storyid,
'story_genre_name' => $genre[$temp]);
}
$insert_genre = $this->story_model->new_story_genre($genres);
$tag = $this->input->post('tags');
for($temp=0;$temp<count($tag);$temp++)
{
$tags[$temp] = array('story_id' => $new_storyid,
'story_tag_name' => $tag[$temp]);
}
$content_warning = $this->input->post('content_warning');
for($temp=0;$temp<count($content_warning);$temp++)
{
$content_warnings[$temp] = array('story_id' => $new_storyid,
'story_content_warning_name' => $content_warning[$temp]);
}
//$chapter = array('story_id' => $new_storyid,
//'chapter_number' => 1, 'chapter_title' => $this->input->post('chapter_title'),
//'chapter_content' => $this->input->post('chapter_content'),
//'chapter_number' => 1, 'date_added' => mdate('%Y-%m-%d %h-%i-%s',time()));
//$result = $this->story_model->add_chapter($chapter);
//if($result){
//redirect('account/userprofile_published_stories');}
}
}
This is my model methods for the above controller method:
public function new_story($story)
{
$this->db->select('user_id');
$query = $this->db->get_where('users',array('username' => $story['author']))->result();
foreach($query as $row)
{ $userid = $row->user_id; }
$publish = array('user_id' => $userid,
'story_title' => $story['title'],
'synopsis' => $story['synopsis']);
$this->db->insert('story',$publish);
return $this->db->insert_id();
}
public function new_story_genre($genre)
{
foreach($genre as $row)
{
$this->db->insert('story_genre', $row);}
}
public function add_chapter($chapter){
$this->db->where('story_id', $chapter['story_id']);
return $this->db->insert('chapters', $chapter);
}
I haven't added the other 2 functions for my tags and content warning inserts because i am confused right now. It all works fine, my genre is inserted.
My tables looks like this:
Story tables
In inserting a story in my above method, the first thing i do is insert a new story row in my story table and returns the new_storyid variable.
after that with the new storyid i add the genre,tags,content warning then the chapters.
My question is, what should i return in my methods for inserting the genre,tags,contentwarning?
I forgot this part because every model method ive written so far always returns a variable i needed in my controller. My first thought was to return a TRUE/FALSE variable if insert is successful/fail but barring special circumstances since ive already processed the data its 100% sure to insert successfully. Should i be returning TRUE/FALSE and adding an if statement like:
if($insert_genre){
//insert tags here
if($insert_tags){
//insert content warning here
if($insert_content_warning){
//insert chapters here
//redirect to view here
}
}
}
Or can i just not return anything? and if so, is this a proper/right way?
EDIT: I forgot to mention i haven't yet added form_validation rules before all the inserts. So my function will be nested in multiple if statements.
I just edited my model method:
public function new_story_genre($genre){
$inserted = 0;
foreach($genre as $row){
$this->db->insert('story_genre', $row);
$inserted += $this->db->affected_rows();}
if($inserted == count($genre)){
return TRUE;}else{ return FALSE; }
}
Above compares the number of inserted rows with the number of rows passed into the method. Everytime a row is inserted it adds 1 to the inserted variable. So if my controller passes 3 rows into the method, the inserted variable should also be 3 for a successful insert.
I think you are correct in always returning something. Errors can and do happen for whatever reason, and its a good idea to account for them even if you already validated your data (you never know). Coding practices suggest that more than a couple of nested ifs is bad practice. A personal preference of mine is to check for failure rather than success all the way down the chain until the last lines of the function (if it got that far than everything is good to go).
A scheme like this I usually use:
public function something() {
if (!$insert_genre) {
// add flash error message
// redirect to controller
}
if (!$insert_tags) {
// add flash error message
// redirect to controller
}
if (!$insert_content_warning) {
// add flash error message
// redirect to controller
}
// yay, something went right!
}
In this kindof circumstance it is very procedural. The most important conditions should be first, and if C depends on A, then A should be the first condition.
Unrelated:
It is hard to follow some of your text here, but it also seems like you should look into how you are doing the genres. If the entered genre already exists in the database do you really need to add it? Shouldn't you just use a relationship there storing the id in the main table and joining when displaying?

yii1 update DB query giving error

I want to update one field in my db. I have the below query, but I am getting error in this.
$list = Test::model()->find(array(
'select'=>'name',
'condition'=>'id=:id AND name=:name AND provider="fb"',
'params'=>array(
':id'=>Yii::app()->user->id,
':name'=> $name,
),
));
$list->name = $user_name[$k]['name'];
if($list->save())
{
echo "done";exit;
}
else
{
$error = $list->getErrors();
var_dump($error);exit;
}
Error:
'Column name must be either a string or an array
This happens when you don't have a primary key in your table and you try to save some data in table. check if you have set primary key and it set properly. more details

How to check records already exist in database when u save new record?

I want to add the new records in table if proudct_id and plan_id is already exist in same row then the error occur otherwise it save the record. I have written following lines of code but no success, if there is any help so please, thanks. I am doing it in cakephp
function admin_product_plan_add(){
$exists = $this->ProductPlan->find('all');
$this->set('exists',$exists);
foreach ($exists as $exists){
$plan_id = $exists['ProductPlan']['plan_id'];
$product_id = $exists['ProductPlan']['product_id'];
}
$conditions = array('ProductPlan.product_id' => $plan_id, 'ProductPlan.plan_id' => $product_id);
$data = $this->ProductPlan->find('all' , array('conditions'=>$conditions));
if (isset($data) && !empty($data))
{
echo '<p>User have already add this product plan!</p>';
}else{
if ($this->ProductPlan->save($this->data)){
$this->Session->setFlash('You have successfully add the product plan');
$this->redirect(array('controller' => 'productplans','action' => 'admin_product_plan_list'));
}
}
}
Use hasAny()
something like:
public function admin_product_plan_add(){
if($this->ProductPlan->hasAny(array("product_id" => $this->data['ProductPlan']['product_id'],'plan_id' => $this->data['ProductPlan']['plan_id']))){
// USER ALREADY HAVE THIS PRODUCTPLAN
} else {
//CREATE NEW PRODUCTPLAN
}
}
or something like that.
Hope this helps
One solution is to use a uniq index over these two rows. So when someone tries do add another row with the same data on these two rows, mysql throws an error and the data is not inserted.

Categories