Yii2 How to update cell with a db migrate file - yii2

I need to update a row, but I cant find any example of this on the web on how to do this with a yii migrate file.
Table = pages
Column = name
Value = newsletter-index
Slug = this value we need to update

If I undestand correctly this should be it. It updates slug column with new value for the rows where column name is newsletter-index.
public function up()
{
$this->update('pages', ['slug' => 'new value here'], ['name' => 'newsletter-index']);
}

Related

how to name database column appropriately

In excel file, I have columns like this; 11.01-12.00, 12.01-13.00, ..., 29.01-30.00. And the content of the column is the price. I want to store a price in many ranges in MySQL like excel column.
Do I have to create a table like this or Do your guys have any better way please guide me?
An option may be to define a column price_range or prices as json column and store the data as key=>value pairs for eg: '11.01-12:00'=> 11.50
In your migration file for the table, add a column
$table->json('prices');
And in your model class, specify to cast prices column as array.
class MyModel extends Model
{
protected $casts = ['prices' => 'array'];
//... rest of the class code
}
By specifying the cast, you can now use associative array to store data on the column, you can work in php arrays to store and update data.
$myModel = new MyModel;
$myModel->prices = [
'11.01-12.00' => 11.50,
'12.01-13.00' => 12.35,
//...
'29.01-30.00' => 29.82,
];
$myModel->save();
To update data
$myModel = MyModel::find(5);
$newPrices = [
'11.01-12.00' => 11.20,
'12.01-13.00' => 12.63,
//...
'29.01-30.00' => 29.05,
]
$myModel->update(['prices' => $newPrices]);
/OR to update price for a specific price range
$myModel->update(['prices->11.01-12.00' => 11.25]);
Laravel docs:
https://laravel.com/docs/8.x/eloquent-mutators#array-and-json-casting
https://laravel.com/docs/8.x/eloquent#mass-assignment-json-columns
https://laravel.com/docs/8.x/queries#updating-json-columns
In your database table migration file, define a column called price to hold your value.
$table->integer('price');
Store your price as the lowest denominator for your currency performing whatever arithmetic is required to perform the conversions in/out of the database.
There is no need for you to create individual columns for different prices.
Edit 1
Based on your question update that the information is in an excel file, you'll want to make use of a package such as Laravel Excel (no point reinventing the wheel) to perform your import.
Nice tutorial for importing an excel file here

Laravel update json column in postgresql

In postgresql db I have a column type json call it "activities". I would like to add there new (key -> value) pair. Without delete existing data.
At this moment my code look like this:
$user = User::with('userLife')->where(['id' =>$id])->first();
$user->userLife->confirmation_token = null;
$user->userLife->activities = ['emailConfirmed' => Carbon::now()->timestamp];
$user->email_confirmed = true;
$user->push();
In my Model I added:
protected $casts = [
'activities' => 'array',
];
But when I use this code all other data in column is removed and only 'emailConfirmed' appeared there.
So how to do it properly to just add new value in column without removing previous?
Thank you.
You should add it as new element through another variable:
$activities = $user->userLife->activities;
$activities['emailConfirmed'] = Carbon::now()->timestamp;
$user->userLife->activities = $activities;

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.

Magento add a column to sales_flat_quote table and add data

I am coming from a previous enviornment where doing things like modifying queries and adding columns was just a matter of writing the sql and executing it. However, now that I'm working in Magento I want to do things "the Magento way".
Scenario: we use paypal express, and before the controller redirects to paypal, I would really like to add a field (if not there already) in sales_flat_quote, called paypal_status - and set the value = 1 (we'll call it, sent to paypal).
On return I want to update that to either 2 or 3 (returned and pending transaction, or returned and captured transaction).
So there are two things I need to know how to do:
have something like $db->addColumn('paypal_status') where it will only add if not exists, and
write UPDATE sales_flat_quote SET paypal_status = 1 WHERE entity_id =
{whatever}
This will be inside the ...Paypal_Express class.
Open database and fire this SQL: Alter table sales_flat_quote Add paypal_status tinyint(1) NOT NULL DEFAULT 1;
Alternatively, you can write following in your SQL file (located at CompanyName\MyModuleName\sql\companyname_modulename_setup) of your custom module. This file will get executed only one time , that is the first time when the module is installed. At that time your custom column will not be there in database so it will create one.
$installer = $this;
$installer->startSetup();
$installer->run("ALTER TABLE `{$installer->getTable('sales/quote')}` ADD `paypal_status` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'My Custom Paypal Status';");
$installer->endSetup();
Clear all cahces.
To save data :
$myValue = 2;
Mage::getSingleton("checkout/cart")->getQuote()->setPaypalStatus($myValue)->save();
Mage::getSingleton("checkout/cart")->getQuote() will give you current quote.
In your sql file at CompanyName\MyModuleName\sql\companyname_modulename_setup copy the following code in order to create the column.
$installer = $this;
$installer->startSetup();
$installer->getConnection()
->addColumn($installer->getTable('sales/quote'),
'paypal_status',
array(
'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
'nullable' => true,
'comment' => 'Paypal Status',
)
);
$installer->endSetup();
Logout and login, and flush magento cache in order to add the column to the table.
The Express Checkout controller is in app/code/core/Mage/Paypal/Controller/Express/Abstract.php. If you want to add a field before the controller redirects to paypal you can modify the _initCheckout() method like this:
protected function _initCheckout()
$quote = $this->_getQuote();
if (!$quote->hasItems() || $quote->getHasError()) {
$this->getResponse()->setHeader('HTTP/1.1','403 Forbidden');
Mage::throwException(Mage::helper('paypal')->__('Unable to initialize Express Checkout.'));
}
$quote->setPaymentStatus(1); // Here is your change
$this->_checkout = Mage::getSingleton($this->_checkoutType, array(
'config' => $this->_config,
'quote' => $quote,
));
return $this->_checkout;
}

How to add combined unique fields validator rule in Laravel 4

I am using Laravel 4.2 and mysql db . I have an exam table in which i am taking Exams entry and the fields are --> id | examdate | batch | chapter | totalmarks
I have made a combined unique key using $table->unique( array('examdate','batch','chapter') ); in schema builder.Now I want to add a validation rule to it. I know i can add unique validation by laravel unique validator rule but the problem is ,it checks only for one field . I want it to add uniqueness to the 3 fields combined(user must not be able to add second row with same value combination of examdate,batch and chapter fields).
Is it even possible to do it in laravel 4 .Is there any workaround if its not possible?
You could write a custom validator rule. The rule could look something like this:
'unique_multiple:table,field1,field2,field3,...,fieldN'
The code for that would look something like this:
Validator::extend('unique_multiple', function ($attribute, $value, $parameters)
{
// Get table name from first parameter
$table = array_shift($parameters);
// Build the query
$query = DB::table($table);
// Add the field conditions
foreach ($parameters as $i => $field)
$query->where($field, $value[$i]);
// Validation result will be false if any rows match the combination
return ($query->count() == 0);
});
You can use as many fields as you like for the condition, just make sure the value passed is an array containing the values of the fields in the same order as declared in the validation rule. So your validator code would look something like this:
$validator = Validator::make(
// Validator data goes here
array(
'unique_fields' => array('examdate_value', 'batch_value', 'chapter_value')
),
// Validator rules go here
array(
'unique_fields' => 'unique_multiple:exams,examdate,batch,chapter'
)
);
It didn't work for me so I adjusted the code a tiny bit.
Validator::extend('unique_multiple', function ($attribute, $value, $parameters, $validator)
{
// Get the other fields
$fields = $validator->getData();
// Get table name from first parameter
$table = array_shift($parameters);
// Build the query
$query = DB::table($table);
// Add the field conditions
foreach ($parameters as $i => $field) {
$query->where($field, $fields[$field]);
}
// Validation result will be false if any rows match the combination
return ($query->count() == 0);
});
The validator looks like this. You don't need a particular order of DB table column names as stated in the other answer.
$validator = Validator::make($request->all(), [
'attributeName' => 'unique_multiple:tableName,field[1],field[2],....,field[n]'
],[
'unique_multiple' => 'This combination already exists.'
]);