Laravel 5: Update record without changing current date/time value of updated_at field - laravel-5

In my Laravel 5 project, I would like to increase the number of views when a visitor come/refresh on the product page like:
$rds = Product::whereId($id)->first();
$rds->hits++;
$rds->save();
The problem is that the field: updated_at automatically update, which is not what I want at all because I would like to change only field: hits, not update_at field.
If I set $rds->updated_at = false; the field is updated to be '0000-00-00 00:00:0'.
Could you advise how to prevent updated_at field from automatically changing for only certain function?
Best Regards,
Naren

Set the timestamps to false to disable updating created_at and updated_at.
$rds = Product::whereId($id)->first();
$rds->hits++;
$rds->timestamps = false;
$rds->save();
You can have a look at the code by Laravel here in performUpdate method:
\Illuminate\Database\Eloquent\Model.php
// First we need to create a fresh query instance and touch the creation and
// update timestamp on the model which are maintained by us for developer
// convenience. Then we will just continue saving the model instances.
if ($this->timestamps && Arr::get($options, 'timestamps', true)) {
$this->updateTimestamps();
}

it's not $rds->updated_at = false, should be $rds->timestamps = false

Simply put the below in your model it would disable timestamp
public $timestamps = false;
or append to the body of the method, below
$rds->timestamps = false;
NB: The first would disable timestamps permanently, while the other would not allow update of timestamp on your edit.

Related

How store null in database using vue and laravel?

I have Vue project with Laravel API, and also I have a column named expired_date: date it is nullable
this is the response after I dd the data from the network console:
The problem is when I store the data I just found the expired_date store value 0000-00-00
My code of store:
$data = $request->except('image');
if (!$request->expired_date) {
$data['expired_date'] = null;
}
Post::create($data);
The issue is that an empty string '' is being saved instead of null, resulting in 0000-00-00 values saved to the field. In this case it's because the ConvertEmptyStringsToNull middleware included with the framework was mistakenly commented out and disabled, so the solution is to re-enable that middleware.
Other common causes are forgetting to make the field nullable in the database, or having an incorrect default value.
To explicitly set a field to null without using the ConvertEmptyStringsToNull middleware, it is possible to use a mutator similar to this inside of the model:
public function setExpiredDateAttribute($date) {
$this->attributes['expired_date'] = empty($date) ? null : Carbon::parse($date);
}

laravel scout temporary disable toSearchableArray when doing updates

is it possible to disable toSearchableArray when doing updates to a record or is there any way to only update specific fields in a record in my search index?
Eg:
public function toSearchableArray()
{
$item = $this->toArray();
$item['title'] = $this->title;
...
...
...
$item['category'] = $this->category->category_name;
$item['uploaded_at'] = Carbon::now('America/Montreal')->timestamp;
}
The only problem now is each time I update a record it also resets its uploaded_at timestamp and re-loads the relationship which is one more query I dont need since it already has it set when I created the item.
So is there any way I can temporary disable toSearchableArray ? I only need to update a few fields in in the row in my index so there is no need to rerun everything in toSearchableArray
Like bellow only update the title and then update the title in my algolia index without reseting uploaded_at or loading the category relation again
$order = App\Order::find(1);
$order->title = 'a new title'
$order->save();
You can use, unsearchable function available in laravel scout.
$modal->unsearchable();
//etc.....
//Finally save the modal
$modal->save()
This way when you save or update it's won't sync to algolia.
If You again want to sync the model to algolia you may call searchable method as shown below.
$modal->searchable();

Laravel 4: Unique Validation with Extra Condition While Updating Record

I am soft deleting events in the database and while updating any event i need to check if user replace the value of "sysname" field with some existing (non deleted and active) event's sysname then i need to prevent it. Therefore, i just want to know that while applying unique validation for the relevant field, how would i assign a condition to check for is_deleted = 0 and status=1
Here is my code of Event model:
public static function editrules($id=0, $merge=[]) {
return array_merge(
[
'sysname' => 'required|unique:tblEvent,sysname,'.$id.',event_id',
],
$merge);
}
The above code simply prevent to update existing event "sysname" for the current event. But
i need to know that what code i need to add in above sample code to check existing non deleted (is_deleted = 0) and active event (status=1)
"unique:tblEvent,sysname,{$id},event_id,deleted_at,NULL,status,1"

updated_at timestamp not being updated when using sync in Laravel 4

I use the following code to update tags and other information about an organization:
Route::put('org/{org}', function(Org $org){
$org->description = Input::get('description');
$org->website = Input::get('website');
$org->save();
$org->tags()->sync(Input::get('tags'));
return Redirect::to('org/'.$org->id)
->with('message', 'Seccessfully updated page!');
});
However, if I only change the tags associated with this org, the updated_at field is not updated. I added protected $touches = array('org'); to my Tag model, but this only seems to work for belongsTo relations, while the relation between orgs and tags is a many-to-many polymorphic relation.
Is there a way to allow the sync function to automatically update the default updated_at timestamp?
Doing it manually, like below, will update the timestamp even if my edit doesn't actually change anything:
$org->updated_at = \Carbon\Carbon::now()->toDateTimeString();
$org->save();
You have to setup touches array on Tag model, BUT it has limitation:
Eloquent guesses the relation name, so will work only if the name complies with the convention.
Organization model -> organizations relation.
And if you want to manually update the timestamp you can use this instead:
$model->touch();

Adding a custom field to Magento's subscription module

The newsletter subscription module in Magento has only one field (email) by default. After I add an extra field to the form (say country), how can I get the form data to show up in the Magento back-end and be sent as an email to a preset recipient? Thanks.
If you want to add some custom fields for Magento newsletter subscriber (for example subscriber_name), you should do the following:
Add new column for newsletter_subscriber table
Add text input to newsletter template
Create observer for newsletter_subscriber_save_before event
In the observer you can get your custom field's value from request and assign it to subscriber's object:
public function newsletterSubscriberSave(Varien_Event_Observer $observer)
{
$subscriber = $observer->getEvent()->getSubscriber();
$name = Mage::app()->getRequest()->getParam('subscriber_name');
$subscriber->setSubscriberName($name);
return $this;
}
UPDATE:
Here is the detailed article explaining how to add Country field
Also, I have created a free module, it is available on the GitHub
There are a few things that you need to take care of to make this work:
Add a new column for your data to the appropriate database table
Make sure that Magento saves your new field to the database
Present the data in the admin backend
Record the data when you get a new newsletter subscription
Here's how you can do all those things:
Ad. 1)
Using phpMyAdmin, MySQL command line, or whatever is your preferred DB manipulation method, add a new column "country" as, say, varchar(100) to the newsletter_subscriber table.
Ad. 2)
Magento will automatically give you access to the new field through the getCountry() and setCountry() methods on the Mage_Newsletter_Model_Subscriber object. The only thing it won't do is save your field back to the DB after it has been changed with code somewhere in the system. To get it saved you need to modify _prepareSave(Mage_Newsletter_Model_Subscriber $subscriber) function found in Mage_Newsletter_Model_Mysql4_Subscriber (app/code/core/Mage/Newsletter/Model/Mysql4/Subscriber.php). Be sure to make a local copy of the file first and not modify the core file. Here's what you need to add:
protected function _prepareSave(Mage_Newsletter_Model_Subscriber $subscriber)
{
$data = array();
$data['customer_id'] = $subscriber->getCustomerId();
$data['store_id'] = $subscriber->getStoreId()?$subscriber->getStoreId():0;
$data['subscriber_status'] = $subscriber->getStatus();
$data['subscriber_email'] = $subscriber->getEmail();
$data['subscriber_confirm_code'] = $subscriber->getCode();
//ADD A NEW FIELD START
//note that the string index for the $data array
//must match the name of the column created in step 1
$data['country'] = $subscriber->getCountry();
//ADD A NEW FIELD END
(...)
}
Ad. 3)
You will need to modify (a local copy of) the file app/code/core/Mage/Adminhtml/Block/Newsletter/Subscriber/Grid.php. The method you are looking for is called _prepareColumns(). In there you will see a series of calls to $this->addColumn(). You need to add a corresponding call for your "Country" field with the following code:
$this->addColumn('country', array(
'header' => Mage::helper('newsletter')->__('Country'),
//the index must match the name of the column created in step 1
'index' => 'country',
'default' => '----'
));
If you want the field to appear at the end of the grid (as the last column) add it as the last call, otherwise, squeeze it between the existing calls exactly where you want it to end up in the admin.
Ad. 4)
This is a part I did not have to do in my customization of the Magento newsletter, so it will be mostly theoretical. The subscription occurs in the controller located at app/code/core/Mage/Newsletter/controllers/SubscriberController.php. Here's the code of the newAction method with my proposed changes:
public function newAction()
{
if ($this->getRequest()->isPost() && $this->getRequest()->getPost('email')) {
$session = Mage::getSingleton('core/session');
$email = (string) $this->getRequest()->getPost('email');
try {
if (!Zend_Validate::is($email, 'EmailAddress')) {
Mage::throwException($this->__('Please enter a valid email address'));
}
$status = Mage::getModel('newsletter/subscriber')->subscribe($email);
if ($status == Mage_Newsletter_Model_Subscriber::STATUS_NOT_ACTIVE) {
$session->addSuccess($this->__('Confirmation request has been sent'));
}
else {
$session->addSuccess($this->__('Thank you for your subscription'));
}
//ADD COUNTRY INFO START
//at this point we may safly assume that subscription record was created
//let's retrieve this record and add the additional data to it
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
//assuming that the input's id is "country"
$subscriber->setCountry((string) $this->getRequest()->getPost('country'));
//don't forget to save the subscriber!
$subscriber->save();
//ADD COUNTRY INFO END
}
catch (Mage_Core_Exception $e) {
$session->addException($e, $this->__('There was a problem with the subscription: %s', $e->getMessage()));
}
catch (Exception $e) {
$session->addException($e, $this->__('There was a problem with the subscription'));
}
}
$this->_redirectReferer();
}
Going through the above steps should take care of the most part of your problem. Let me know how that last part worked out, as I did not have a chance to test it.
Once you have your additional field in the Subscriber object you can do whatever you want with it. I did not really get what you mean by
be sent as an email to a preset recipient
If you can explain that I will try to help you out with this part too.
Edit - how to send a mail when someone subscribes
Just add the following code to the controller after the part which adds country to a subscriber object.
$mail = new Zend_Mail();
$mail->setBodyHtml("New subscriber: $email <br /><br />Country: ".$this->getRequest()->getPost('country'));
$mail->setFrom("youremail#email.com")
->addTo("admin#mysite.com")
->setSubject("Your Subject here");
$mail->send();
Adding to the accepted answer, you can also get away with this a little easier if you're adding a date, datetime, or timestamp-type column.
In my case, I wanted to add a "Subscribed at Date" to my grid. To do this, I wrote my upgrade script, column type being TIMESTAMP and the default value being CURRENT_TIMESTAMP. This way, when the row is added, the current date/time is recorded.
Then, all you have to do is add your block customizations. I'd suggest doing it by extending Magento's grid block rather than doing the local codepool override though. This way, you only need to override _prepareColumns();
Old thread but if someone has the same question, there is a free extension, that adds fields for gender, firstname and lastname and makes it available in the backend grid for export via xml/csv: http://www.magentocommerce.com/magento-connect/extended-newsletter-subscription-for-guests.html
Perhaps you can extend the code to fit your needs.
This is a warning for anyone who's installed the Ebizmarts_MailChimp extension.
It's a great extension. But it adds subscriber_firstname and subscriber_lastname to the newsletter_subscriber table.
If you intend to create these fields, you should either "require" the Ebizmarts_MailChimp extension or check the fields don't exist before your extension creates them.
In the opposite, where you've created them and want to install the the Ebizmarts_MailChimp extension after you've created these fields, you will have to comment out the addColumn code for these two fields during installation.

Resources