What does isDirty() mean in Laravel? - php

First of all, I am not familiar with Laravel so much (or with the term "dirty" for that matter).
I stumbled upon this line of code -
if ($this->isDirty('status')) {
if (Notification::has('website-status-' . strtolower($this->status))) {
Notification::set($this->account, 'website-status-' . strtolower($this->status), $this->emailAttributes())
->email();
}
}
And I couldn't understand what that means exactly. I tried to find out on the internet but the Laravel site only says this
"Determine if a given attribute is dirty"
which doesn't really help...

When you want to know if the model has been edited since it was queried from the database, or isn't saved at all, then you use the ->isDirty() function.

The isDirty method determines if any attributes have been changed since the model was loaded. You may pass a specific attribute name to determine if a particular attribute is dirty.
$user = User::create([
'first_name' => 'Amir',
'last_name' => 'Kaftari',
'title' => 'Developer',
]);
$user->title = 'Jafar';
$user->isDirty(); // true
$user->isDirty('title'); // true
$user->isDirty('first_name'); // false

Eloquent provides the isDirty, isClean, and wasChanged methods to examine the internal state of your model and determine how its attributes have changed from when they were originally loaded.
You can find complete description and examples of these three methods here in the official document:
https://laravel.com/docs/9.x/eloquent#examining-attribute-changes

As support for the accepted answer:
$model = Model::find(1);
$model->first_column = $request->first_value;
$model->second_column = $request->second_value;
$model->third_column = $request->third_value;
if($model->isDirty()){
// the model has been edited, else codes here will not be executed
}
$model->save();

Related

Update two models using yii x-editable

So, I'm using this extension: x-editable for yii.
And I'm currently trying to update two models in update() function.
I have two models:
Realisasi.php
RealisasiDeadline.php.
So when a cell is updated on table Realisasi.php (one value in column t1701 in this case), I want the function to update the corresponding value in column t1701 of table RealisasiDeadline, using column no as the foreign key.
Since I haven't found any example on Google, I made it up myself:
public function actionSimpanEdit($kode) {
Yii::import('editable.EditableSaver');
$es = new EditableSaver($_GET['model']); // 'modelName' is classname of model to be updated
$es->update();
$es2 = RealisasiDeadline::model()->findByPk($kode);//this is where I'm stuck
$es2['t1701'] = '1991-11-19';//this too
$es->update();//and this
}
This is the view.php:
array(
'name' => 't1701',
'value' => 'CHtml::value($data,"hubtarget.t1701")=== "0"?"Target Nol":$data->t1701',
'header' => 'Bkl Selatan',
'class' => 'editable.EditableColumn',
'editable' => array(
'url' => $this->createUrl('simpanEdit', array('model' => 'Realisasi', 'kode'=>'$data->no')),
)
),
What have I missed? Is it possible at all to do? If not, is there another solution?
UPDATE
It's not showing any error. But the value in table RealisasiDeadline doesn't change, only the one in Realisasi does.
Added some comments to original function so you can improve upon it. Biggest issue with this code is that looking at it I have no idea what it does.
public function actionSimpanEdit($kode) {
Yii::import('editable.EditableSaver'); // Should be at the top of the file
// For the love of god use descriptive variable names
$es = new EditableSaver($_GET['model']); // Would prefer to have model as actions argument
$es->update();
$es2 = RealisasiDeadline::model()->findByPk($kode); // no idea what this model is responsible for
$es2['t1701'] = '1991-11-19'; // no idea what attribute t1701 is, use descriptive names
$es->update();
}
I have refactored it a bit. Still have no idea what it does ;/
public function actionSimpanEdit($id, $model) {
$editableSaver = new EditableSaver($model);
$editableSaver->update();
$deadline = RealisasiDeadline::model()->findByPk($id);
if($deadline instanceof RealisasiDeadline) {
$deadline->t1701 = '1991-11-19';
if(!$deadline->update()) {
// something went wrong
}
} else {
// not found
}
}
Going back to your problem. It is probably caused by RealisasiDeadline model being not found or some behavior or event preventing it from update.

Laravel - both input values can't be no how to validate?

I'm using Laravel for a project and want to know how to validate a particular scenario I'm facing. I would like to do this with the native features of Laravel if this is possible?
I have a form which has two questions (as dropdowns), for which both the answer can either be yes or no, however it should throw a validation error if both of the dropdowns equal to no, but they can both be yes.
I've check the laravel documentation, but was unsure what rule to apply here, if there is one at all that can be used? Would I need to write my own rule in this case?
very simple:
let's say both the fields names are foo and bar respectively.
then:
// Validate for those fields like $rules = ['foo'=>'required', 'bar'=>'required'] etc
// if validation passes, add this (i.e. inside if($validator->passes()))
if($_POST['foo'] == 'no' && $_POST['bar'] == 'no')
{
$messages = new Illuminate\Support\MessageBag;
$messages->add('customError', 'both fields can not be no');
return Redirect::route('route.name')->withErrors($validator);
}
the error messge will appear while retrieving.
if you get confuse, just dump the $error var and check how to retrieve it. even if validation passes but it gets failed in the above code, it won't be any difference than what would have happened if indeed validation failed.
Obviously don't know what your form fields are called, but this should work.
This is using the sometimes() method to add a conditional query, where the field value should not be no if the corresponding field equals no.
$data = array(
'field1' => 'no',
'field2' => 'no'
);
$validator = Validator::make($data, array());
$validator->sometimes('field1', 'not_in:no', function($input) {
return $input->field2 == 'no';
});
$validator->sometimes('field2', 'not_in:no', function($input) {
return $input->field1 == 'no';
});
if ($validator->fails()) {
// will fail in this instance
// changing one of the values in the $data array to yes (or anything else, obvs) will result in a pass
}
Just to note, this will only work in Laravel 4.2+

Regarding Yii CMarkdown Class

I want to display some text in a CDetailView which was previously encoded in MarkDown format.
this is my view code:
<?php
$this->widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
'title',
array(
'name'=>'text',
'type'=>'raw',
'value'=>$this->markdown->transform($model->text)
),
'author_id',
'date_added',
),
));
?>
and in my controller, I instantiate a CMarkDown filter like this:
private $_markdown = null;
public function getMarkdown()
{
if ( $this->_markdown === null)
{
$this->_markdown = new CMarkdown();
$this->_markdown->purifyOutput = true;
}
return $this->_markdown;
}
notice how I explicitly set purifyOutput to true.
So I created a mock post full of things like marquee and injected javascript to see how it would behave and it didn't filter anything at all!! I got an alert on my face and the marquee was all happy moving around on the page....
I found a workaround which was to set 'type'=>'html' in the CDetailView but I shouldn't need to do that, should I??
Isn't that purifyOutput option supposed to filter unwanted stuff out for me when I call the ->transform() method??
Some help, please.
To purify the output you need to use CMarkdown::processOutput, not the transform method (that one is more low-level and does not honor purifyOutput).
If you look at the documentation carefully, you will notice that processOutput mentions the purifyOutput setting while transform does not. Viewing the source confirms this.

How to make this Filter run after this Validator

I have an element. I want to add a custom validator and custom filter to it. The validator makes sure the input is one of several permitted values, then the filter adds some custom values to the input. This means I have to validate the original input first before running the filter. I do it in this order
$element = new Zend_Form_Element_Text('element');
$element->addValidator('PermittedValue', false);
$element->addFilter('TotalHyphen', false);
$this->addElement($element);
but this order isn't being respected. The filter runs first and changes the data, then the validator runs on the filtered data which means it always fails even for valid input. It seems from documentation that this is intentional
Note: Validation Operates On Filtered
Values Zend_Form_Element::isValid()
filters values through the provided
filter chain prior to validation. See
the Filters section for more
information.
How can I specify the order in which validators and filters run?
Sure seems like creating a custom element that supports post-validation filtering would be the way to go. How about this:
/**
* An element that supports post-validation filtering
*/
class My_Form_Element_PostValidateFilterable extends Zend_Form_Element_Text
{
protected $_postValidateFilters = array();
public function setPostValidateFilters(array $filters)
{
$this->_postValidateFilters = $filters;
return $this;
}
public function getPostValidateFilters()
{
return $this->_postValidateFilters;
}
public function isValid($value, $context = null)
{
$isValid = parent::isValid($value, $context);
if ($isValid){
foreach ($this->getPostValidateFilters() as $filter){
$value = $filter->filter($value);
}
$this->setValue($value);
}
return $isValid;
}
}
Usage would be something like this:
$elt = $form->addElement('PostValidateFilterable', 'myElement', array(
'label' => 'MyLabel',
'filters' => array(
'StringTrim',
// etc
),
'validators' => array(
'NotEmpty',
// etc
),
// here comes the good stuff
'postValidateFilters' => array(
new My_Filter_RunAfterValidateOne(),
new My_Filter_RunAfterValidateTwo(),
),
));
This keeps the validation and filtering in the form - keeping the controller thin.
Not tested, just a stab in the dark. And surely you could fatten/modify the API to add/remove filters by key, etc.
Whaddya think?
Maybe don't add the filter at all. Validate the content first in the controller, and then use the filter separately:
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getParams())) {
$filter = new Filter_Whatever();
$val = $filter->filter($request->getParam('element'));
... //call your model or whatever
}
I've never done this, but I suppose this (or something similar) might work.
Good point ! ,
AFAIK filters should or must run before validating the input :
from ZF docs
It's often useful and/or necessary to
perform some normalization on input
prior to validation. For example, you
may want to strip out all HTML, but
run your validations on what remains
to ensure the submission is valid. Or
you may want to trim empty space
surrounding input so that a
StringLength validator will use the
correct length of the input without
counting leading or trailing
whitespace characters.
but if and only if you are in case which can't solve mingos's answer must be the help
What you want to achieve is to change default behavior of how text element is being processed. Thus, I think you could create your own element (e.g. My_Form_Element_Text) that extends Zend_Form_Element_Text and overload its isValid() method.
Specifically you could just change second line in the orginal isValid() method, from $value = $this->getValue(); into $value = $this->getUnfilteredValue();. This way your validation will be performed using unfiltered values.

Zend Framework: Can I use an add view script for editing too?

I have a simple Zend Framework that has a view script to add records to the database. This is a silly question IMHO, but how can I use the add view script to edit the record as well??
I have played around with a few scenarios to no avail.
Thanks,
Steve
Per Matt S' comment, the method you're looking for is Zend_Form::populate(). There are some notes about it in the documentation: Populating and Retrieving Values.
Basically, you use it like this in the controller:
$form = new Form_Person();
// get the data from somewhere
if($id = $this->getRequest()->getParam('id') && $model->find($id)) {
// really, use data from the model here
// but the populate() -method can take any array as an argument
$form->populate(array(
'name' => 'Dolph',
'age' => '52'
));
}
$this->view->form = $form;
and in your view, as usual:
<?= $this->form ?>
So the array could be for example the result of Zend_Db_Table_Row_Abstract::toArray() with column names matching to the names you gave the form elements.

Categories