How to force data update on laravel validation custom unique - laravel-5.4

I'm new in laravel. I have a table with menu_id and title I tried to make this title field unique when have the same menu_id. I found the solution here
But I got problem when update it. Can anyone help please?
My code
Validator::extend('unique_custom', function ($attribute, $value, $parameters)
{
// Get the parameters passed to the rule
list($table, $field, $field2, $field2Value) = $parameters;
// Check the table and return true only if there are no entries matching
// both the first field name and the user input value as well as
// the second field name and the second field value
return \DB::table($table)->where($field, $value)->where($field2, $field2Value)->count() == 0;
});
public function updateSubmenu( Request $request) {
$this->validate( $request, [
'menu_id' => 'required',
'title' => 'required|unique_custom:posts,title,menu_id,'.$request->menu_id,
'order_by' => 'required|integer',
'description' => 'required'
],
[
'title.unique_custom' => 'This title already token'
]
);
}

Can you explain what problem have you got on update? Some exception?
Edit:
If you couldn't update record if title not changes, you need to add one condition to Validator:
Validator::extend('unique_custom', function ($attribute, $value, $parameters)
{
// Get the parameters passed to the rule
list($table, $field, $field2, $field2Value) = $parameters;
// If old value not changed, don't check its unique.
$current = \DB::table($table)->where('title')->first();
if( $current->{$field} == $value) {
return true;
}
return \DB::table($table)->where($field, $value)->where($field2, $field2Value)->count() == 0;
});

Related

checkbox data not insert in mysql using codeigniter

I try to insert my checkbox data in CodeIgniter. but data did not inserted in the database.
here is my view file:
<input type="checkbox" name="feature[]" value="WIFI" >
<input type="checkbox" name="feature[]" value="TV">
I am trying to use implode to convert the array into the string, but then I don't how to add in $data array, so they inserted in together
here is my controller:
public function save()
{
$this->load->model('Partner_model');
$feature = $this->input->post('feature');
$fea=array(
'feature'=>json_encode(implode(",",$feature))
);
$user_data= array(
'pname' => $this->input->post('pname'),
'type' => $this->input->post('type'),
'address' => $this->input->post('address'),
'about' => $this->input->post('about'),
'city' => $this->input->post('city'),
'code' => $this->input->post('code')
);
if($this->Partner_model->save($user_data,$fea))
{
$msg = "save sucesss" ;
}
else
{
$msg = "not save";
}
$this->session->set_flashdata('msg', $msg);
$this->load->view('partner_profile');
}
& here is my model:
public function save($data,$fea)
{
return $this->db->insert('property', $data,$fea);
}
Your model is faulty.
You are passing three arguments to insert() but the third you use is not appropriate.
That argument should be a boolean that indicates whether to escape values and identifiers or not. You need to incorporate $fea into $data which should probably be done in the controller.
There is an easier way to create the array $user_data since it is essentially a copy of $_POST just use $this->input->post().
Also, there is no obvious reason why you use json_encode. Unless you need it that way when you retrieve it from the DB there is no reason to bother with it. Consider removing json_encode.
First, change the model
public function save($data)
{
return $this->db->insert('property', $data);
}
Here's a revised save method
public function save()
{
$this->load->model('Partner_model');
$user_data = $this->input->post(); //makes a copy of $_POST
$feature = $this->input->post('feature');
if($feature) //because $feature will be null if no boxes are checked
{
$user_data['feature'] = json_encode(implode(",", $feature));
}
$msg = $this->Partner_model->save($user_data) ? "save sucesss" : "not save";
$this->session->set_flashdata('msg', $msg);
$this->load->view('partner_profile');
}
An explanation as requested via comments.
A call to $this->input->post('pname') returns the value of $_POST['pname'] if it is exists, but returns null if it does not exist.
When you create $user_data you make six calls to $this->input() with a different "key" each time to make a copy of $_POST.
$this->input->post() without any arguments returns the whole $_POST array. (See documentation)
$user_data = $this->input->post();
Makes a copy of $_POST using one line of code. It will include $_POST['feature'] if any boxes are checked, but $_POST['feature'] will not be set if no boxes are checked.
There are two ways to test if any boxes were checked. First we can test if isset($_POST['feature']) == true or we can test if $this->input->post('feature') == true. I use the second with the call
if($feature)
Which is pretty much the same as any of the following lines
if($feature != false)...
if($feature != null)...
if( ! empty($feature))...
if( ! is_null($feature))...
In other words, if($feature) evaluates as true if $feature is set and is anything except null, false, 0, "0", "" (an empty string), array() (an empty array)
public function save()
{
$this->load->model('Partner_model');
$feature = $this->input->post('feature');
$user_data= array(
'pname' => $this->input->post('pname'),
'type' => $this->input->post('type'),
'address' => $this->input->post('address'),
'about' => $this->input->post('about'),
'city' => $this->input->post('city'),
'code' => $this->input->post('code'),
'feature'=>json_encode(implode(",",$feature))
);
if($this->Partner_model->save($user_data)){
$msg = "save sucesss" ;
}else{
$msg = "not save";
}
$this->session->set_flashdata('msg', $msg);
$this->load->view('partner_profile');
}
model file should be :
public function save($data) {
return $this->db->insert('property', $data);
}

Yii2 Update query in controller not working

I’m trying to update 'page' column but it is not working. I want to update only one column by changing the data from 4 to 5. The data type is an integer.
View
<div class="row">
<div class="col-sm-12 text-center">
<?= Html::a('Add as memoriam', ['update-status', 'id' => $model->ID], [
'class' => 'btn bg-maroon',
'data' => [
'confirm' => 'Are you sure you want to add '.$model->name.' into the dearly departed?',
'method' => 'post',
],
]) ?>
</div>
</div>
Controller
public function actionUpdateStatus($id)
{
$model = $this->findModel($id);
$model->page = 5;
if ($model->save())
$this->redirect(array('view', 'id' => $model->id));
return $this->redirect(['my-obituary']);
}
1. Using save()
This method will call insert() when $isNewRecord is true, or update() when $isNewRecord is false.
public function actionUpdateStatus($id)
{
$model = $this->findModel($id);
$model->page = 5;
if ($model->save(true, ['page'])) {
$this->redirect(array('view', 'id' => $model->id));
}
return $this->redirect(['my-obituary']);
}
2. Using updateAttributes()
This method is a shortcut to update() when data validation is not needed and only a small set attributes need to be updated. You may specify the attributes to be updated as name list or name-value pairs. If the latter, the corresponding attribute values will be modified accordingly. The method will then save the specified attributes into database.
Note that this method will not perform data validation and will not trigger events.
public function actionUpdateStatus($id)
{
$model = $this->findModel($id);
$model->page = 5;
if ($model->updateAttributes(['page' => 5])) {
$this->redirect(array('view', 'id' => $model->id));
}
return $this->redirect(['my-obituary']);
}

Create custom url links in code igniter

I have searched all over the internet for information that would help me achieve this seemingly simple thing.
But I can't get my hands on any that is helpful.
What I want to do is to create a custom url link like http://mywebsite.com/users/username,
where
1) 'users' is a MySQL table name
2) 'username' is a column name.
I did some digging on the internet and found this code on github:
<?php
//check for referal links
function referal()
{
$CI =& get_instance();
$cookie_value_set = $CI->input->cookie('_tm_ref', TRUE) ? $CI->input->cookie('_tm_ref', TRUE) : '';
if ($CI->input->get('ref', TRUE) AND $cookie_value_set == '') {
// referred user so set cookie to ref=username
$cookie = array(
'name' => 'ref',
'value' => $CI->input->get('ref', TRUE),
'expire' => '7776000',
);
$CI->input->set_cookie($cookie);
return TRUE;
}elseif ($cookie_value_set == '') {
$cookie = array(
'name' => 'ref',
'value' => 'sso',
'expire' => '15552000',
);
$CI->input->set_cookie($cookie);
return TRUE;
}elseif ($cookie_value_set != '') {
//already referred so ignore
return TRUE;
}else{
return TRUE;
}
}
//end of hooks file
?>
The owner of the gist only mentioned saving the file as referral.php inside the hook folder. This is not helping me with what I want to achieve, I don't know how to use the code:
1. How do I pass the referrer field to the variable username from the users table?
2. How do I load the hook file to view (register.php)?
3. How and where do I call the hook file?
So can anybody give me an insight?

QueryException - Integrity constraint violation: 1062 Duplicate entry when I hit the route 'logout'

I get the above error when I try and logout by hitting the route /logout. The table that is referenced in the screenshot is mdbids. It stores all of my IDs (strings, 16 characters in length).
When a user is created their MDBID (id) is stored in the mdbids table.
routes.php
<?php
Route::get('login', ['as' => 'login', 'uses' => 'SessionsController#create']);
Route::get('logout', ['as' => 'logout', 'uses' => 'SessionsController#destroy']);
SessionsController.php
<?php
use MDB\Forms\LoginForm;
class SessionsController extends \BaseController {
protected $loginForm;
function __construct(LoginForm $loginForm)
{
$this->loginForm = $loginForm;
}
public function create()
{
if(Auth::check()) return Redirect::to("/users");
return View::make('sessions.create');
}
public function store()
{
$this->loginForm->validate($input = Input::only('email','password'));
if (Auth::attempt($input)) {
Notification::success('You signed in successfully!');
return Redirect::intended('/');
}
Notification::error('The form contains some errors');
return Redirect::to('login')->withInput()->withFlashMessage("The form contains some errors");
}
public function destroy()
{
Auth::logout();
return Redirect::home();
}
}
The following is taken from my User.php (model) file. It isn't the whole file as it is fairly big, but this is the only part where IDs are mentioned.
User.php (model)
<?php
public function save(array $options = array())
{
$this->mdbid = $this->mdbid ?: str_random(16);
$this->key = $this->key ?: str_random(11);
Mdbid::create([
'mdbid' => $this->mdbid,
'table_number' => 7,
'table_name' => 'users',
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
parent::save($options);
}
I don't know where to start to look. Any help is greatly appreciated.
Your issue is that the logout is actually causing save() to run, and therefor you are causing Mdbid::create to run with an already added key (presumably when you logged in, or somewhere else in your User model?).
Solution #1:
You could add a logout() function to the User model that you have. Something similar to
function logout()
{
$this->mdbid = null;
return Auth::logout()
}
This will stop two of the same keys being added to the logout function.
Solution #2
If what you are trying to accomplish is adding a row upon a successful login, then you should not be using the User::save() function, rather, you should be listening for the auth.login event.
Inside app/start/global.php, add the following code:
Event::listen('auth.login', function($user)
{
$user->mdbid = $user->mdbid ?: str_random(16);
$user->key = $user->key ?: str_random(11);
Mdbid::create([
'mdbid' => $user->mdbid,
'table_number' => 7,
'table_name' => 'users',
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
});
This will ensure only one row gets added to Mdbid per successful login, instead of adding a new row (with the same id) each time the User model is updated.
Solution #3 (a.k.a. what was really wanted)
Each table has mdbid as a primary key. Each primary key needs to be added to the Mdbid table each time a new row is inserted.
The way that this should be done is with an Observer. The first part is adding a new Observer class that will be used for all of the models we want to add the mdbid into:
class MdbidObserver
{
/**
* Observe new rows being added into the database
*/
public function creating($model)
{
// note that $model could be any model
$model->mdbid = $model->mdbid ?: str_random(16);
$model->key = $model->key ?: str_random(11);
Mdbid::create([
'mdbid' => $model->mdbid,
'table_number' => 7,
'table_name' => 'users',
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
}
}
The second part is adding the Observer to all the models that we want the mdbid added to (inside app/start/global.php):
User::observe(new MdbidObserver);
Artist::observe(new MdbidObserver);
Album::observe(new MdbidObserver);
To stop any issues with mdbid not actually being random already being used, you might want to add a loop just before $model->mdbid. Something similar to:
$isUnique = false;
while (!$isUnique)
{
$unqiueId = str_random(16);
$row = Mdbid::where('mdbid', $uniqueId);
if (is_object($row))
$isUnique = true;
}
$model->mdbid = $uniqueId;

insert if not exists Codeigniter

my controller:
function getFeed()
{
$feed_url = $this->input->get("url");
$content = file_get_contents($feed_url);
$x = new SimpleXmlElement($content);
foreach($x->channel->item as $entry) {
$feeds[] = array(
'title' => (string)$entry->title,
'url'=> (string)$entry->link,
'username' => $this->session->userdata('username')
);
$this->load->model('membership_model');
$this->membership_model->feeds($feeds);
}
Model:
function feeds($feeds_data)
{
$this->db->insert_batch('feeds', $feeds_data);
}
Is there a function to insert if only the row doesn't exists in the table? I have a table with 4 column : id,title,url,username. I have an anchor when i click him it calls geFeed function and insert the info into table. But i want to insert only if not exists.
I had the same challenge, so i eventually come up with a function which might be helpful to you.
function safe_update_batch($table_name,$records,$filter_field)
{
$filters=array();
foreach($records as $record)$filters[]=$record[$filter_field];
$this->db->query("SET SESSION group_concat_max_len=10000000");
$query=$this->db->select("GROUP_CONCAT($filter_field) AS existing_keys",FALSE)->where_in($filter_field, $filters)->get($table_name);
$row=$query->row();
$found_fields=explode(',',$row->existing_keys);
$insert_batch=array();
$update_batch=array();
foreach($records as $record)
{
if(in_array($record[$filter_field],$found_fields))$update_batch[]=$record;
else $insert_batch[]=$record;
}
if(!empty($insert_batch))$this->db->insert_batch($table_name,$insert_batch);
if(!empty($update_batch))$this->db->update_batch($table_name,$update_batch,$filter_field);
}
//sample usage
$this->safe_update_batch('feeds', $feeds_data,'title');
You can try this in your model!!
function insertClient($array)
{
$this->db->from('MyTable');
$this->db->where('Id', $array['Id']);
$query = $this->db->get();
if($query->num_rows() != 0){
$data = array(
'name'=>$array['name'],
'phone'=>$array['phone'],
'email'=>$array['email']
);
$this->db->where('Id', $array['Id']);
$this->db->update('CLIENTS', $data);
}else{
$data = array(
'name'=>$array['name'],
'phone'=>$array['phone'],
'email'=>$array['email']
);
$this->db->insert('CLIENTS',$data);
}
}
In controller:
$this->site_model->insertClient($_POST);
Sadly if you are using the active record class an INSERT IF NOT EXISTS function doesn't exist. You could try
Extending the active record class (easier said than done)
You could set indexes on certain columns as UNIQUE so that MySQL will check to see if it already exists
You could do some kind of SELECT before your INSERT to determine if the record is already there
For the queries where you need to do INSERT IF NOT EXISTS do $this->db->query('INSERT IF NOT EXISTS...')
function getFeed()
{
// Load the model up here - otherwise you are loading it multiple times
$this->load->model('membership_model');
$feed_url = $this->input->get("url");
$content = file_get_contents($feed_url);
$x = new SimpleXmlElement($content);
foreach($x->channel->item as $entry) {
// check if the feed is unique, if true then add to array
if( $this->membership_model->singleFeedIsUnique($entry) == TRUE ){
$feeds[] = array(
'title' => (string)$entry->title,
'url'=> (string)$entry->link,
'username' => $this->session->userdata('username')); }
} //foreach
// check to make sure we got any feeds with isset()
// if yes, then add them
if (isset($feeds)){ $this->membership_model->feeds($feeds); }
}
You can try this in your model and leave you controller without changes
function feeds($feeds_data)
{
$data = array(
title => $feeds_data[0],
url => $feeds_data[1],
username => $feeds_data[2]
);
$this->db->select('*');
$this->db->from('mytable');
$this->db->where('title',$feeds_data[0]);//you can use another field
if ($this->db->count_all_results() == 0) {
$query = $this->db->insert('mytable', $data);//insert data
} else {
$query = $this->db->update('mytable', $data, array('title'=>$feeds_data[0]));//update with the condition where title exist
}
}
you can check the id if you have it, adding in the data array and use it to check if exist