How to use callback from helper in codeigniter form validation? - codeigniter

My form validation code in controller is,
$this->form_validation->set_rules("name", "Name", "trim|callback_custom_validation");
if ($this->form_validation->run() !== FALSE) {}
My helper code is,
function custom_validation($str) {
// validation logic
}
If i move this custom_validation function to controller then it is working but it is not working as helper.
I need to call this function from controller and model so i am using helper.
So how to call from helper?

There are two ways to do this.
You should create a helper file in the application/helpers folder and place the function in the helper file. Then load the helper file in your controller.
custom_validation.php:
function custom_validation($str) {
// validation logic
}
Inside controller:
$this->load->helper('custom_validation');
You can also extend the Form_validation library.
Create a file: application/libraries/MY_Form_validation.php
<?php
class MY_Form_validation extends CI_Form_validation {
public function custom_validation($str) {
// validation logic
}
}
And then just load it as normal validation:
$this->form_validation->set_rules('name', 'Name', 'required|custom_validation');

Add your custom validation method to any model and use it in controllers and models like this example:
$this->form_validation->set_rules(
'name', 'Name',
array(
'trim',
'required',
array($this->Mymodel_m, 'custom_validation')
)
);
if ($this->form_validation->run() !== FALSE) {...}
More info
Callable: Use anything as a rule

Related

Transform piece of laravel livewire code into Facade or trait

I'm trying to transform the following piece of code into a Facade.
But I don't know how to call $this in the facade. I want to do this without using $this or passing it as a parameter. Can I somehow dependency inject it?
The following piece of code is inside a livewire component which will dispatch event to show a toast by a JS listener.
//turn this
$this->dispatchBrowserEvent('showToast', ['name'=>'success','title' => 'Updated','message'=>'Your data is saved']);
//into this
$toast::success('Updated','Your data is saved');
How can I simplify this code?
I usually create a trait Toast.
trait Toast
{
public function successAlert(string $title, string $message)
{
$this->dispatchBrowserEvent('showToast', [
'name' => 'success',
'title' => $title,
'message' => $message,
])
}
}
Then on my livewire component I use:
class MyComponent extends Component
{
use Toast;
public function save()
{
// save
$this->successAlert('Updated','Your data is saved');
}
}
I couldn't think in an easy way to implement the facade, since you need to access internal features of the livewire component to dispatch the browser event.

Yii2: Standalone validation not triggering client validation

Validation functions don't work.
Validation customs rules are not applied to the usernmane field
module dektrium/user
PHP 7.1
Yii 2.0.16
Already try all from here: https://www.yiiframework.com/doc/guide/2.0/en/input-validation (Inline Validators and Standalone Validators)
Model Agent :
class Agent extends Profile
{
public $username;
public $password;
public $password2;
public function rules()
{
$rules = [
['username', AgentValidator::className()],// it's not work
[['email'], 'email'], // it's work
['password2', 'compare', 'compareAttribute' => 'password', 'message' => 'Пароли должны совпадать'],//// it's work
];
return array_merge(parent::rules(), $rules);
}
}
AgentValidator.php
<?php
namespace app\components;
use yii\validators\Validator;
class AgentValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
if (User::findOne(['username' => $this->$attribute]]) {
$this->addError($attribute, 'Такой логин уже занят');
}
}
}
You are using standalone validator and you want the frontend validation to be working along with the backend so you need to override the yii\validators\Validator::clientValidateAttribute() in your Standalone validator AgentValidator, which returns a piece of JavaScript code that performs the validation on the client-side.
Within the JavaScript code, you may use the following predefined variables:
attribute: the name of the attribute being validated.
value: the value being validated.
messages: an array used to hold the validation error messages for the attribute.
deferred: an array which deferred objects can be pushed into.
You can go through the section Implementing Client Validation to read in detail.
Apart from everything listed above you have a mistake in your validator code User::findOne(['username' => $this->$attribute]], you need to use $model->$attribute rather than $this->$attribute which will never get the exact value entered in the form. You might have mistakenly added it from the model.
Your current validator should be like below
<?php
namespace app\components;
use yii\validators\Validator;
class AgentValidator extends Validator
{
public $message='Такой логин уже занят';
public function validateAttribute($model, $attribute)
{
if (User::findOne(['username' => $model->$attribute])!==null)
{
$model->addError($attribute, $this->message);
}
}
public function clientValidateAttribute($model, $attribute, $view) {
//check if user exists
$userExists = User::findOne(['username' => $model->$attribute])!==null;
$message = json_encode($this->message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return <<<JS
if($userExists){
messages.push($message);
return;
}
JS;
}
}
So, Thank Muhammad Omer Aslam for right answer.
Yii2 does't generate any js code for validation by custom rules. Therefore it is necessary to add a check to the controller and the form
For me it:
Controller
if (\Yii::$app->request->isAjax) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model->load(\Yii::$app->request->post());
return \yii\widgets\ActiveForm::validate($model);
}
Form
$form = ActiveForm::begin([ 'enableAjaxValidation' => true]);

Trying to hook into Model 'updating' event with a trait

I'm trying to provide a way to track when a user makes a change to a model for a notes section in my application. E.g. John goes and modifies 2 fields, a note would be created saying John has changed title from 'My title 1' to 'My title 2' and content from 'Lipsum' to 'Lipsum2'.
Here is a trait I created:
<?php
namespace App\Traits;
use Illuminate\Database\Eloquent\Model;
trait TrackChanges
{
public $changes;
public static function bootChangesTrait()
{
static::updating(function($model)
{
$this->changes = [];
foreach($model->getDirty() as $key => $value)
{
$original = $model->getOriginal($key);
$this->changes[$key] = [
'old' => $original,
'new' => $value,
];
}
});
}
}
And I am using that trait successfully on my model. However, I'm not sure how to capture the contents of the changes, or if they are even working correctly.
In my controller I have:
$site = Site::findOrFail($id);
// Catch and cast the is_active checkbox if it's been unselected
if ( ! $request->exists('is_active') )
{
$request->request->add([ 'is_active' => 0 ]);
}
// // Get rid of the CSRF field & method
$data = $request->except([ '_token', '_method' ]);
$site->update($data);
I tried dd($site->changes) before and after $site->update($data); but it just returns null.
What am I doing wrong?
You need to change your boot method in your trait to bootTrackChanges(). To boot traits you need to follow the naming pattern of boot{TraitName} for your boot method. Then you need to change your $this calls in your trait to $model so the change get saved to the model so your trait should look like this:
<?php
namespace App\Traits;
use Illuminate\Database\Eloquent\Model;
trait TrackChanges
{
public $changes;
public static function bootTrackChanges()
{
static::updating(function($model)
{
$changes = [];
foreach($model->getDirty() as $key => $value)
{
$original = $model->getOriginal($key);
$changes[$key] = [
'old' => $original,
'new' => $value,
];
}
$model->changes = $changes;
});
}
}
Another thing to note is if you have defined a boot method in your model make sure you call the parent boot method as well or else your trait's boot methods will not be called and your listener will not be registered.. I have spent hours and hours on this one before due to forgetting to call the parent method. In your model defining a boot method is not required but if you did call the parent like:
class MyModel extends Model
{
use TrackChanges;
protected static function boot()
{
// Your boot logic here
parent::boot();
}
}

Laravel 5 Form request validation with parameters

I am using form request validation and there are some rules that needs external values as a parameters.
Here are my validation rules for editing a business profile inside a form request class,
public function rules()
{
return [
'name' => 'required|unique:businesses,name,'.$business->id,
'url' => 'required|url|unique:businesses'
];
}
I can use this on the controller by type hinting it.
public function postBusinessEdit(BusinessEditRequest $request, Business $business)
{
//
}
But how to pass the $business object as a parameter to the rules method?
Lets say this is your model binding:
$router->model('business', 'App\Business');
Then you can reference the Business class from within the FormRequest object like this:
public function rules()
{
$business = $this->route()->getParameter('business');
// rest of the code
}
Note that if you use your form request both for create and update validation, while creating the record, the business variable will be null because your object does not exists yet. So take care to make the needed checks before referencing the object properties or methods.
There can be many ways to achieve this. I do it as below.
You can have a hidden field 'id' in your business form like bellow,
{!! Form::hidden('id', $business->id) !!}
and you can retrieve this id in FormRequest as below,
public function rules()
{
$businessId = $this->input('id');
return [
'name' => 'required|unique:businesses,name,'.$businessId,
'url' => 'required|url|unique:businesses'
];
}
For those who switched to laravel 5 :
public function rules()
{
$business = $this->route('business');
// rest of the code
}
Let say if we have a scenario like we want to change our validation rules depends on the type that we pass in with the route. For example:
app.dev/business/{type}
For different type of business, we have different validation rules. All we need to do is type-hint the request on your controller method.
public function store(StoreBusiness $request)
{
// The incoming request is valid...
}
For the custom form request
class StoreBussiness extends FormRequest
{
public function rules()
{
$type = $this->route()->parameter('type');
$rules = [];
if ($type === 'a') {
}
return rules;
}
}
In Laravel 5.5 at least (haven't checked older versions), once you did your explicit binding (https://laravel.com/docs/5.5/routing#route-model-binding), you can get your model directly through $this:
class StoreBussiness extends FormRequest
{
public function rules()
{
$rules = [];
if ($this->type === 'a') {
}
return rules;
}
}
Since Laravel 5.6 you may type hint it in the rules method:
public function rules(Business $business)
{
return [
'name' => 'required|unique:businesses,name,'.$business->id,
'url' => 'required|url|unique:businesses'
];
}
See the docs for more:
You may type-hint any dependencies you need within the rules method's signature. They will automatically be resolved via the Laravel service container.

Calling a method in model from layout in Zendframework 2

I try in Zendframework 2 to call a method in model form layout to show some user specific things. I have tried to do it in Module.php in init and onBootstrap and tried to declare some variables that will be available in layout.phtml, but I failed and have not found anything usefull.
You'd typically use a view helper as a proxy to your model for this
Create a view helper in your application, eg.,
<?php
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
class MyModelHelper extends AbstractHelper
{
protected $model;
public function __construct($model)
{
$this->model = $model;
}
public function myCoolModelMethod()
{
return $this->model->method();
}
}
You then make it available by registering it with the framework in your Module.php file using the getViewHelperConfig() method and an anomyous function as a factory to compose your helper, and inject the model it's expecting
<?php
namespace Application;
class Module
{
public function getViewHelperConfig()
{
return array(
'factories' => array(
'myModelHelper' => function($sm) {
// either create a new instance of your model
$model = new \FQCN\To\Model();
// or, if your model is in the servicemanager, fetch it from there
//$model = $sm->getServiceLocator()->get('ModelService')
// create a new instance of your helper, injecting the model it uses
$helper = new \Application\View\Helper\MyModelHelper($model);
return $helper;
},
),
);
}
}
Finally, in your view (any view), you can call your helper, which in turn calls your models methods
// view.phtml
<?php echo $this->myModelHelper()->myCoolModelMethod(); ?>

Resources