How I do do get session in model? CakePHP 3.x - session

Cakephp 3.x
I want to do my captcha custom validation. But I can not access a session.
$validator->notEmpty('securityCode', __('not empty message'))
->add('securityCode','custom',
['rule' => function ($value, $context) use ($extra) {
if($this->request->Session()->read('captcha') != $value) {
return false;
}
return true;
}, 'message' => 'error security code']);
return $validator;
or can I my custom validation function give custom parameter?
public function validationLogin(Validator $validator, $customParameter)
{ //bla bla }
I use: http://book.cakephp.org/3.0/en/core-libraries/validation.html#custom-validation-rules

You can pass Session data as parameter of validation function like this
// In Controller
$sessionData = $this->request->Session()->read('captcha');
$validator = $this->{YourModel}->validationLogin(new Validator(), $sessionData);
$errors = $validator->errors($this->request->data());
if (!empty($errors)) {
// Captcha validation failed
}
// In Model
public function validationLogin(Validator $validator, $sessionData)
{
$validator
->notEmpty('securityCode', __('not empty message'))
->add('securityCode', 'custom', [
'rule' => function ($value, $context) use ($sessionData) {
if ($sessionData != $value){
return false;
}
return true;
},
'message' => 'error securty code'
]);
return $validator;
}
Edit: you can access session from model, but it is not a good practise and you better avoid it. Instead rather pass it from controller as in example above
// In model
use Cake\Network\Session;
$session = new Session();
$sessionData = $session->read('captcha');

For CakePHP 3: at the top of your Model class add
use Cake\Network\Session;
and at the point where you want to have to access the session add
$this->session = new Session();
$messages = $this->session->read('captcha'); // Example for the default flash messages
To set a flash message in the model use
$this->session = new Session();
$messages = $this->session->read('Flash.flash');
$messages[] = ['message' => 'YOUR FLASH MESSAGE', 'key' => 'flash', 'element' => 'Flash/default', 'params' => []];
$this->session->write('Flash.flash', $messages);

Related

Return to view from another function in laravel

Hi I'm saving information from blade. The form goes to store function. After saving data I have to send push info using GCM. But this function can not return to view. How can solve this?
public function store(Request $request)
{
$request->validate([
'title_uz' => 'required',
'desc_uz' => 'required',
'url_uz' => 'required',
'company_id' => 'required',
]);
News::create($request->all());
$this->versionUpdate();
$this->sendpush($request);
}
And next function
public function sendpush (Request $request)
{
$fcmUrl = 'https://fcm.googleapis.com/fcm/send';
$notification = [
'title' => $request->title_uz,
'text' => $request->desc_uz,
];
***** here is some functions *******
$result = curl_exec($ch);
curl_close($ch);
$result_to = json_decode($result);
if ($result_to === null) {
return redirect()->route('news.index')
->with('success','DIQQAT!!! Yangilik qo`shildi ammo push-xabar yuborilmadidi.');
}
else {
return redirect()->route('news.index')
->with('success','Yangilik qo`shildi va push-xabar muvoffaqiyatli yuborildi.');
}
}
$result_to returns value but the browser holds at blank screen. It seems the store function holds at the end.
Try this line return $this->sendpush($request);instead of this $this->sendpush($request);
you have redirect from this method so you can try like these
$result_to = $this->sendpush($request);;
if ($result_to === null) {
return redirect()->route('news.index')
->with('success','DIQQAT!!! Yangilik qo`shildi ammo push-xabar yuborilmadidi.');
}
else {
return redirect()->route('news.index')
->with('success','Yangilik qo`shildi va push-xabar muvoffaqiyatli yuborildi.');
}

Cakephp 3 update value in validation provider if returning false

In my model I would like to update a value in my validation provider
For exemple if the $value = '4012*'
It is not alphanumeric so I want $value to empty to save it my database
Model/Table/ProductsTable
public function validationDefault(Validator $validator)
{
$validator
->allowEmpty('code')
->add('code', 'alphaNum', [
'rule' => 'isalphaNum',
'message' => 'Code is wrong',
'provider' => 'table']);
return $validator;
}
public function isalphaNum($value, array $context)
{
if (!ctype_alnum($value)) {
//Update a warning table
$warning = new Warnings;
$warning->insert('Code is wrong',
$context['data']['code'],
$context['field'],
$value
);
//UPDATE THE VALUE TO EMPTY
$value = "";
}
return true;
}
The problem is when I debug my value in my isalphaNum function, it is empty, Good!. But after the validation and when it is saved in the database it is my intial value saved in this exemple '4012*'.
Where should I change my value?

Drupal 8 Form alter the ajax callback is not working

I am getting my ajax callback in normal custom form, but on form alter its not working.
function sample_ajax_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if ($form_id === 'node_sampleajax_form' || $form_id === 'node_sampleajax_edit_form') {
$form['field_nametrain']= array(
'#title' => t('training name'),
'#type' => 'select',
'#options' => _load_training(),
'#required' => FALSE,
'#ajax' => [
'callback' => [$this, 'changeOptionsAjax'],
// 'callback' => '::changeOptionsAjax',
'wrapper' => 'second_field_wrapper',
],
);
$form['field_namedomain'] = [
'#type' => 'select',
'#title' => t('Domain program'),
'#options' => $this->getOptions($form_state),
'#prefix' => '<div id="second_field_wrapper">',
'#suffix' => '</div>',
];
return $form;
}
}
function _load_training() {
$training = array('- Select domain training -');
$query = db_select("node__field_trainingname", "a");
$query->fields("a", array('field_trainingname_value', 'entity_id'));
$query->orderBy("a.field_trainingname_value");
$result = $query->execute();
while($row = $result->fetchObject()){
$training[$row->entity_id] = $row->field_trainingname_value;
}
return $training;
}
function changeOptionsAjax(array &$form, FormStateInterface $form_state) {
return $form['field_namedomain'];
}
function getOptions(array &$form, FormStateInterface $form_state) {
$cvvv = $form_state->getValue('field_nametrain');
<!-- return ["shgsh", $form_state->get(['field_nametrain'])]; -->
$options = array('- Select subdomain category -');
$query = db_select("node__field_trainingname", "a");
$query->fields("a", array('field_trainingname_value', 'entity_id'));
$query = db_select("node__field_cms", "b");
$query->fields("b", array('field_cms_value', 'entity_id'));
$query->join("node__field_trainingname", "b", "b.entity_id=a.entity_id");
$query->condition("a.entity_id", $cvvv);
$result = $query->execute();
while($row = $result->fetchObject()){
$options[$row->entity_id] = $row->field_cms_value;
}
return $options;
}
On using $this->getOptions($form_state) it represent the error log it is not an object and throws website encounter error in front end. But on custom form no error came only in formalter it throws error.
Kindly suggest me ideas to apply in form_alter of Drupal 8
The .module file, where your form alter hook is located, is not a class, therefore there is no $this. Your custom form however is a class (usually in your_module/src/Form/YourForm.php), that's why it works there but not in the .module file.
Further reading: http://www.php.net/manual/en/language.oop5.basic.php
and What does the variable $this mean in PHP?
In your case you should be able to just call
'#options' => getOptions($form, $form_state),
And more on a side note: I would strongly recommend to do some code refactoring.
In your custom submit handler, firt get the form object from the form state.
$formObj = $formState->getFormObject();
then call submitForm() on the form object and pass the form and form state variables.
$formObj->submitForm($form, $formState);
and finally, you just need to simply trigger the save() function on the object.
$formObj->save($form, $formState);
So the whole solution is something like
function YOR_CUSTOM_SUBMIT_HANLDLER(array $form, FormStateInterface $form_state) {
/** #var Drupal\user\RegisterForm $entity */
$formObj = $form_state->getFormObject();
$formObj->submitForm($form, $form_state);
$formObj->save($form, $form_state);
}

laravel on saving model return json from validation

Hi I'm having a problem outputting my json information on saving method in the model. I get the following error -
UnexpectedValueException in Response.php line 397:
The Response content must be a string or object implementing __toString(), "boolean" given.
I do validation on the model while saving and in the validate method of the model I need to out put the json but I'm getting boolean instead of json object
Javascript:
submit: function(e) {
e.preventDefault();
var contact = this.model.save({
firstname: this.firstname.val(),
lastname: this.lastname.val(),
company: this.company.val(),
email_address: this.email_address.val(),
description: this.description.val(),
}, {success:function(response){ console.log(response)}, wait: true});
Contact Model:
class Contact extends Model
{
protected $table = "contacts";
protected $fillable = ['firstname', 'lastname', 'company', 'email_address', 'description'];
public static function boot() {
parent::boot();
static::creating(function($model) {
return $model->validate('POST');
});
static::updating(function($model) {
return $model->validate('PUT');
});
static::saving(function($model) {
return $model->validate('PUT');
});
}
public function rules($method)
{
switch($method)
{
case 'GET':
case 'DELETE':
{
return [];
}
case 'POST':
{
return [
'firstname' => 'required',
'lastname' => 'required',
'email_address' => 'required|email|unique:contacts,email_address',
'description' => 'requried'
];
}
case 'PUT':
case 'PATCH':
{
return [
'firstname' => 'required',
'lastname' => 'required',
'email_address' => 'required|email|unique:contacts,email_address,'.$this->id,
'description' => 'required',
];
}
default: break;
}
return [];
}
public function messages() {
return [
'firstname.required' => 'Please enter your first name.',
'lastname.required' => 'Please enter your first name.',
'email_address.required' => 'Please enter a email address.',
'email_address.email' => 'Please enter a valid email address',
'email_address.unique' => 'The email is not unique.',
'description' => 'Please enter a description.'
];
}
public function validate($method)
{
$data = $this->attributes;
// if( $data['slug'] === '') {
// // if the slug is blank, create one from title data
// $data['slug'] = str_slug( $data['title'], '-' );
// }
// make a new validator object
$v = Validator::make($data, $this->rules($method), $this->messages());
// check for failure
if ($v->fails())
{
// set errors and return false
// json here not return response it's always boolean true or false
return new JsonResponse(array('error' => true, 'errors' => $v->messages()));
}
// validation pass
return true; //new JsonResponse(array('errors'=>false));
}
public function errors() {
return $this->errors;
}
public function user() {
return $this->hasOne('App\User', 'email', 'email_address');
}
}
Saving the model:
public function update(Request $request, $id) {
$contact = Contact::find($id)->with('user')->first();
$contact->firstname = $request->get('firstname');
$contact->lastname = $request->get('lastname');
$contact->email_address = $request->get('email_address');
$contact->company = $request->get('company');
$contact->description = $request->get('description');
return $contact->save(); //return formatted json
}
According to your implementation of validation, you should change the following part (in Contact):
// check for failure
if ($v->fails())
{
// set errors and return false
// json here not return response it's always boolean true or false
return new JsonResponse(array('error' => true, 'errors' => $v->messages()));
}
To something like this:
if ($v->fails()) {
$this->errors = $v->errors();
return false;
}
Then, from the Controller, try something like this:
// If validation failed
if(!$contact->save()) {
return response()->json([
'error' => true,
'errors' => $contact->errors()
]);
}
// Contact created if reached here...
return response()->json(['error' => false, 'contact' => $contact]);
Also, check the Ajax-Request-Validation and Form-Request-Validation (Easier and Managable).
Note: Don't try to return any kind of HTTP Response from model. Returning the HTTP response is part of your application logic and model should not care about these.
As save() does return boolean so You've to check if it's ok.
1) Change Your Contact model to put errors to model's errors param:
/* if($v->fails()) remove/comment this line
...
} */
$this->errors = $v->errors();
return !$v->fails();
2) In Your controller put this code:
public function update(Request $request, $id) {
$contact = Contact::find($id)->with('user')->first();
if(!$contact) {
return response('Contact not found', 404);
}
$contact->firstname = $request->get('firstname');
$contact->lastname = $request->get('lastname');
$contact->email_address = $request->get('email_address');
$contact->company = $request->get('company');
$contact->description = $request->get('description');
return $contact->save()?
$contact->toJson() : // returns 200 OK status with contact (json)
response($contact->errors, 400); // returns proper 400 Bad Request header with errors (json) in it
}
p.s. it's nice to answer to requester with http status, industry has made all to make life of developer easy, so if it's not 2xx, 3xx status so => response for Your request from client-side app will be treated as error (handler success: function(response) will not catch error here)

Adding custom message to Zend Framework 2 Callback Validator

I would like to add a custom error message to my Callback Validator below ("Zip Code is required" for example), how would I go about doing this?
$zip = new \Zend\InputFilter\Input('zip');
$zip->setRequired(false);
$zip->getValidatorChain()
->attach(new \Zend\Validator\Callback(function ($value, $context) {
if($context['location_type_id'] == \Application\Model\ProjectModel::$LOCATION_TYPE_ID_AT_AN_ADDRESS)
{
return (isset($value)&&($value!= NULL))? $value: false;
}
return true;
}));
If you need more information, let me know and I will update.
Thanks for your help!
Abor
Just to throw in my two cents, a custom message can also be set via configuration. I often use this when using a factory type approach like so:
'name' => array(
...
'validators' => array(
new \Zend\Validator\Callback(
array(
'messages' => array(\Zend\Validator\Callback::INVALID_VALUE => '%value% can only be Foo'),
'callback' => function($value){
return $value == 'Foo';
}))
)
),
This produces a message like "Bar can only be Foo".
Look closely at the \Zend\Validator\Callback::INVALID_VALUE key, this is a constant defined in \Zend\Validator\Callback:
const INVALID_VALUE = 'callbackValue';
Which is used in that class to set the messages used by the validator:
protected $messageTemplates = array(
self::INVALID_VALUE => "The input is not valid",
self::INVALID_CALLBACK => "An exception has been raised within the callback",
);
Which means you can safely use \Zend\Validator\Callback::INVALID_VALUE => 'Custom message'
I'm not sure whether this breaks a coding principle, somebody please correct me if it does.
You can do it that way :
$callback = new \Zend\Validator\Callback(function ($value) {
// Your validation logic
}
);
$callback->setMessage('Zip Code is required');
$zip = new \Zend\InputFilter\Input('zip');
$zip->setRequired(false);
$zip->getValidatorChain()->attach($callback);
Thanks to jchampion for his help.
$zip = new \Zend\InputFilter\Input('zip');
$zip->setRequired(false);
$callback = new \Zend\Validator\Callback(function ($value, $context) {
if($context['location_type_id'] == \Application\Model\ProjectModel::$LOCATION_TYPE_ID_AT_AN_ADDRESS)
{
return (isset($value)&&($value!= NULL))? true: false;
}
return true;
});
$callback->setMessage('Zip Code is required');
$zip->getValidatorChain()->attach(new \Zend\Validator\NotEmpty(\Zend\Validator\NotEmpty::NULL));
$zip->getValidatorChain()->attach($callback);

Resources