Can I use AUTO_INCREMENT in my laravel project? - mysql

I have an Eloquent model that has a column that is a number composed of various codes and at the end a number that should increment automatically. This last number is the same number I use to define the primary key of my model, so my question is:
Is there a way to use the AUTO_INCREMENT variable from my MySQL database?
If not, what is the best way to create a variable in Laravel that automatically increments?
example:
$code1 = $this->getCode1();
$code2 = $this->getCode2();
$autoIncr = ...;
$final_code = $code1 . $code2 . $autoIncr;

you can create a function that returns the next id (autoincrement) of your table and the insert the entry in your table;
$code1 = $this->getCode1();
$code2 = $this->getCode2();
$autoIncr = $this->getNextAutoincrement();
$final_code = $code1 . $code2 . $autoIncr;
//Insert in your table
$row = YourModel::create([
'finalCode' => $final_code
]);
private function getNextAutoincrement() {
//don't forget import DB facade at the beginning of your class
$id = DB::select("SHOW TABLE STATUS LIKE 'YOUR_TABLE_NAME'");
$next_id=$id[0]->Auto_increment;
return $next_id;
}
Hope I've helped you

Related

how to get model primary key value after save

i have a problem when i try to get the primary key (auto increment) from the db after i save the model.
In the database the tabel doesn't have a primary key so i set it using this:
public static function primaryKey(){
return ['id_cod'];
}
And i removed it from the models rules.
When i save the model, all the data is saved on the db included id_cod, but if i try to access to this property it gives me null.
$evento = new Evento();
//populate the model with some data
//..... eg: $evento->name = 'name';
//save model
$evento->save();
$evento->refresh();
echo Yii::$app->db->getLastInsertID(); // gives me the correct id_cod but i think it's not the correct way
echo $evento->id_cod;//gives me null
echo $evento->name;//gives me name
How can i get the id_cod just after save the model?

How to delete specific column value from db in yii2

I want to delete updated value from db. Like if the notice is inserted of notice column in class table and I want to delete it. So what will be the query in yii2? Please help -
$model = Class::find()->where('id', $id)->one;
$model->delete();
Above query is for -
DELETE FROM class WHERE id = $id;
I want to write query like that in yii2 -
DELETE notice FROM class WHERE id = $id;
If you are searching using the primary key, you can use
$model = Class::findOne($id);
Then, for deleting (setting to null) the notice field, you just need to use
$model->notice = NULL;
$model->save();
Note that if the notice attribute is required, or not null, the save will fail.
Yii allows you to execute SQL command direct
https://www.yiiframework.com/doc/api/2.0/yii-db-command
$query = "DELETE notice FROM class WHERE id = {$id}";
Yii::$app->db->createCommand($query)->execute();

How to update a pivot table using Eloquent in laravel 5

I am new to laravel. I am working on a laravel 5 app and I am stuck here. I have 2 models as such:
class Message extends Eloquent{
public function user()
{
return $this->belongsTo('App\User', 'from');
}
public function users()
{
return $this->belongsToMany('App\User')->withPivot('status');
}
}
class User extends Eloquent {
public function messages()
{
return $this->hasMany('App\Message', 'from');
}
public function receive_messages() {
return $this->belongsToMany('App\Message')->withPivot('status');
}
}
There exist a many-to-many relationship between Message and User giving me a pivot table as such:
Table Name: message_user
Colums:
message_id
user_id
status
I have an SQL query as such:
update message_user
set status = 1
where user_id = 4 and message_id in (select id from messages where message_id = 123)
How can I translate this query to the laravel equivalent?
The code below solved my problem:
$messages = Message::where('message_id', $id)->get();
foreach($messages as $message)
$message->users()->updateExistingPivot($user, array('status' => 1), false);
You may use one of these two functions, sync() attach() and the difference in a nutshell is that Sync will get array as its first argument and sync it with pivot table (remove and add the passed keys in your array) which means if you got 3,2,1 as valued within your junction table, and passed sync with values of, 3,4,2, sync automatically will remove value 1 and add the value 4 for you. where Attach will take single ID value
The GIST: if you want to add extra values to your junction table, pass it as the second argument to sync() like so:
$message = Messages::find(123);
$user = User::find(4);
// using attach() for single message
$user->message()->attach($message->id, [
'status' => 1
]);
$message2 = Messages::find(456); // for testing
// using sync() for multiple messages
$user->message()->sync([
$message->id => [
'status' => 1
],
$message2->id => [
'status' => 1
],
]);
Here is a small example of how to update the pivot table column
$query = Classes::query();
$query = $query->with('trainees')
->where('user_id', Auth::id())
->find($input['classId']);
foreach ($query->trainees as $trainee) {
$trainee->pivot->status = 1 //your column;
$trainee->pivot->save();
}
Note: make sure your relation data must in an array
Hope its help you :)
happy coding
Laravel 5.8
First, allow your pivot columns to be searchable by chaining the withPivot method to your belongsToMany
Copied from my own code to save time
// I have 3 columns in my Pivot table which I use in a many-to-many and one-to-many-through scenarios
$task = $user->goalobjectives()->where(['goal_objective_id'=>$goal_objective_id,'goal_obj_add_id'=>$goal_obj_add_id])->first(); //get the first record
$task->pivot->goal_objective_id = $new; //change your col to a new value
$task->pivot->save(); //save
The caveat is that your pivot table needs to have a primary 'id' key.
If you don't want that then you can try the following:
$tasks=$user->posts()->where(['posts_id'=>$posts_id,'expires'=>true])->get()->pluck('id'); // get a collection of your pivot table data tied to this user
$key=join(",",array_keys($tasks->toArray(),$valueYouWantToRemove));
$tasks->splice($key,1,$newValueYouWantToInsert);
$c = array_fill(0,$tasks->count(),['expires'=>true]); //make an array containing your pivot data
$newArray=$tasks->combine($c) //combine the 2 arrays as keys and values
$user->posts()->sync($newArray); //your pivot table now contains only the values you want
4th July Update Update to above snippet.
//Ideally, you should do a check see if this user is new
//and if he already has data saved in the junction table
//or are we working with a brand new user
$count = $user->goalobjectives->where('pivot.goal_obj_add_id',$request->record)->count();
//if true, we retrieve all the ids in the junction table
//where the additional pivot column matches that which we want to update
if($count) {
$ids = $user->goalobjectives->where('pivot.goal_obj_add_id',$request->record)->pluck('id');
//convert to array
$exists = $ids->toArray();
//if user exists and both saved and input data are exactly the same
//there is no need
//to update and we redirect user back
if(array_sum($inputArray) == array_sum($exists)) {
//redirect user back
}
//else we update junction table with a private function
//called 'attachToUser'
$res = $this->attachToUser($user, $inputArray, $ids, $request->record);
}//end if
elseif(!$count) {
//we are working with a new user
//we build an array. The third pivot column must have equal rows as
//user input array
$fill = array_fill(0,count($inputArray),['goal_obj_add_id'=>$request->record]);
//combine third pivot column with user input
$new = array_combine($inputArray,$fill);
//junction table updated with 'user_id','goal_objective_id','goal_obj_add_id'
$res = $user->goalobjectives()->attach($new);
//redirect user if success
}
//our private function which takes care of updating the pivot table
private function attachToUser(User $user, $userData, $storedData, $record) {
//find the saved data which must not be deleted using intersect method
$intersect = $storedData->intersect($userData);
if($intersect->count()) {
//we reject any data from the user input that already exists in the database
$extra = collect($userData)->reject(function($value,$key)use($intersect){
return in_array($value,$intersect->toArray());
});
//merge the old and new data
$merge = $intersect->merge($extra);
//same as above we build a new input array
$recArray = array_fill(0,$merge->count(),['goal_obj_add_id'=>$record]);
//same as above, combine them and form a new array
$new = $merge->combine($recArray);
//our new array now contains old data that was originally saved
//so we must remove old data linked to this user
// and the pivot record to prevent duplicates
$storedArray = $storedData->toArray();
$user->goalobjectives()->wherePivot('goal_obj_add_id',$record)->detach($storedArray);
//this will save the new array without detaching
//other data previously saved by this user
$res = $user->goalobjectives()->wherePivot('goal_obj_add_id',$record)->syncWithoutDetaching($new);
}//end if
//we are not working with a new user
//but input array is totally different from saved data
//meaning its new data
elseif(!$intersect->count()) {
$recArray = array_fill(0,count($userData),['goal_obj_add_id'=>$record]);
$new = $storedData->combine($recArray);
$res = $user->goalobjectives()->wherePivot('goal_obj_add_id',$record)->syncWithoutDetaching($new);
}
//none of the above we return false
return !!$res;
}//end attachToUser function
This will work for pivot table which doesn't have a primary auto increment id. without a auto increment id, user cannot update,insert,delete any row in the pivot table by accessing it directly.
For Updating your pivot table you can use updateExistingPivot method.

Implementing a Laravel 4 Pivot Table using Eloquent

I've got the following structure in my database:
-shared_resources table
-tags table
-shared_resource_tag table
There is a many to many relationship between shared_resources and tags. When I am creating a shared_resource I do the following:
Add the shared_resource to the shared_resources table
Add the tags to the tags table
Add the shared_resource_id and the tag_id to the shared_resource_tag table
I can manage to get through steps 1 and 2 but for some reason I am unable to make any entries to the pivot table. I don't know why. I set up the relationships in my models accordingly:
SharedResource:
class SharedResource extends Eloquent{
public function tags(){
return $this->belongsToMany('Tag');
}
}
Tag:
class Tag extends Eloquent{
public function sharedResources(){
return $this->belongsToMany('SharedResource');
}
}
Then when I am creating the entries I do this:
$tags = Array();
$tags = explode(',', Input::get('tags'));
foreach($tags as $tag){
$newTag = new Tag;
$newTag->name = $tag;
$newTag->save();
}
//Pivot table entry
$resource->tags()->sync($tags);
$resource->save();
The code above runs into an error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'shared_resource_id' in 'where clause' (SQL: select `tag_id` from `shared_resource_tag` where `shared_resource_id` is null)
I'm very confused as to whats going on, I understood that Eloquent made implementing these n:n relationships easy.
The sync() method will need the id's of the tags, and not the string names which you are giving it. You can try something like:
$tags = Array();
$tagIds = Array();
$tags = explode(',', Input::get('tags'));
foreach($tags as $tag){
$newTag = new Tag;
$newTag->name = $tag;
$newTag->save();
$tagIds[] = $newTag->id;
}
//Pivot table entry
$resource->tags()->sync($tagIds);
$resource->save();
You can find more info here under Using Sync To Attach Many To Many Models
$tags = explode(',', Input::get('tags'));
// Create or add tags
$tagIds = array();
if ( $tags )
{
$found = $this->tag->findOrCreate( $tags );
foreach ( $found as $tag )
{
$tagIds[ ] = $tag->id;
}
}
// Assign set tags to model
$model->tags()->sync( $tagIds );

Cakephp save array data in MySql Database using loop with create

I am facing strange problem first time. I am trying to insert simple records in database with Custom Auto Increment Values e.g 00001, 00002, 00003. but unable to get Incremented value. Each record get updated with same max number.
Controller Code
public function dobulk() {
for($i=0;$i<5;$i++) {
$data = array();
$this->Tmp->create();
$data['Tmp']['invoice_no'] = $this->Tmp->get_no();
$data['Tmp']['invoice_date'] = '2013-12-11';
$this->Tmp->save($data);
}
}
Model Code
public function get_no() {
$strSql = "SELECT
LPAD(IFNULL(RIGHT(MAX(invoice_no),5),0) + 1,5,'0') AS max_id
FROM tmps
;";
$result = $this->query($strSql);
$invoice_no = $result[0][0]['max_id'];
return $invoice_no;
}
Database Table
CREATE TABLE `tmps` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`invoice_no` varchar(20) DEFAULT NULL,
`invoice_date` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
Thanks in advance.
You're probably running into the model cache.
From here: Bakery article on caching
If Model->cacheQueries == true, Cake will store the result of queries in memory. If it later sees an identical query, the result will be pulled from memory instead of hitting the database. This is only cached for the duration of a single page request. However, if a record is updated, the cache is not cleared. This is what gets most people unfamiliar with the cache.
So to make your code work, add this line to the top of the dobulk() function:
$this->Tmp->cacheQueries = false;
As you're running raw SQL inside your model, you might also have to change the query request inside get_no() to:
$result = $this->query($strSql, false);
Hope below solution will help you!
public function get_no() {
$strSql = "SELECT MAX(invoice_no) AS max_id FROM tmps;";
$result = $this->query($strSql);
$invoice_no = $result['Tmp']['max_id'];
return $invoice_no;
}
public function dobulk(){
$data = array();
$tempInvoiceNumber = $this->Tmp->get_no();
for($i=1;$i<=5;$i++) {
$data[$i]['Tmp']['invoice_no'] = tempInvoiceNumber+$i;
$data[$i]['Tmp']['invoice_date'] = '2013-12-11';
}
$this->Tmp->saveAll($data);
}