I already passed the ajax value to the front controller from js in prestashop 1.7.6.
So I first set the link in hookFooter function of module class file with
// Create a link with the path
$link = new Link;
$parameters = array("action" => "send_changed_price");
$ajax_link = $link->getModuleLink('mymodule','ajax', $parameters);
Second, used this url in custom.js file and made a Ajax call with
$.getJSON(
ajax_link,
{parameter1 : 1100},
function(data) {
if(typeof data.status !== "undefined") {
// Use your new datas here
console.log(data);
}
}
);
And get the Ajax value in init_content function of front controller mymoduele/controllers/front/ajax.php with
switch (Tools::getValue('action')) {
case 'send_changed_price':
$var1 = Tools::getValue('parameter1');
// $var1.=$var;//(float)$var1;
// Edit default response and do some work here
$response = array('status' => true, "message" => $var1);
break;
default:
break;
}
The problem is I want to use this ajax value in my module class, but not in front controller class. Because I have to use this value in hookActionCartSave(one of hook) function of my module class.
How can I pass this value to the module main class?
Or is there any other way to pass Ajax value to main module class directly?
From your FrontController you can call any module function you need by using $this->module->HERE_IS_NAME_OF_YOUR_MODULE_FUNCTION()
First, I added these data to datable with one front controller which adapt with database:
<?php
class DbAdapter extends ObjectModel {
public static $definition_array = array(
'table' => 'tablename',
'primary' => 'id',
'fields' => array(
'value1' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
'value2' => array('type' => self::TYPE_FLOAT, 'validate' => 'isNegativePrice', 'required' => true)
)
);
public static function insertData($value1, $value2, ...) {
$result=Db::getInstance()->insert('tablename', array(
'value1' => $value1,
'value2' => $value2,
...........
));
}
public static function getData($value1) {
$query = "SELECT * FROM `"._DB_PREFIX_."tablename` WHERE `value1` = $value1 ORDER BY id DESC";
return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query);
}
}
In front controller, after get the Ajax value, save them with that datatable adapter function.
switch (Tools::getValue('action')) {
case 'send_changed_price':
$var1 = Tools::getValue('parameter1');
$var2 = "additional_value";
DbAdapter::insertData($var1, $var2);
break;
default:
break;
}
And in the module main class just used getData() function
$stitch_data_row= DbAdapter::getStitch($specific_price->id_cart);
Of course, you have to include this Db adapter class php file at the top in module main class and Ajax class file.
include_once(_PS_MODULE_DIR_ . 'modulename/classes/DbAdapter.php');
Related
Example for send and received data between ajax function and action of controller in Zend framework 3
Here is a simple example of an ajax request using ZF3. You may give a try with this one. In this example we would use ZF3's default Application module.
Lets assume we would retrieve data via a ajax call from the following url.
http://yoursite.com/title
Lets create an action method for the title route in the IndexController.
public function titleAction()
{
// Initialize view
$view = new ViewModel();
// Checks if this is a Javascript request
$xmlHttpRequst = $this->getRequest()->isXmlHttpRequest();
if (! $xmlHttpRequst) {
die('Bad request');
}
/**
* Here we may pull data from database but for tests
* here we make an array of titles for the view
*/
$titles = [];
for ($i = 0; $i < 10; $i++) {
$titles[] = "Lorem ipsum dolor {$i}";
}
// Set data to be used in the view
$view->setVariable('titles', $titles);
/**
* Tell the renderer not to show the layout
* by setting setTerminal to true
*/
$view->setTerminal(true);
return $view;
}
We created a method, we need creating a view template for it.
view/application/index/title.phtml
<?php
foreach ($titles as $title) {
echo '<h2>' . $title . '</h2>';
}
Now we would create another action method in the IndexController from where we would make the ajax call.
http://yoursite.com/text
So lets make that action method too...
public function textAction()
{
return new ViewModel();
}
and view template would be like so
view/application/index/text.phtml
<h1>Handling ajax request</h1>
<button onclick="showTitle()">Show Title</button>
<div id="box"></div>
<?php
// Set url
$url = $this->serverUrl('/title'); // http://yoursite.com/title
// This is for the "url" catch
echo "<script>" . PHP_EOL;
echo "\tvar url = '{$url}';" . PHP_EOL;
echo "</script>" . PHP_EOL;
?>
<script>
function showTitle() {
$.get(url, function(data){
$('#box').html(data);
})
.done(function(){
console.log('Done!');
})
.fail(function(){
console.log('Failed!');
});
}
</script>
This script needs jQuery Javascript library to make the ajax call. So make sure that script is added in your view/layout/layout.phtml.
The last thing we need is to set up routes for the /title and /text. Lets add those two routes to the route section of module/Application/config/module.config.php
'title' => [
'type' => Literal::class,
'options' => [
'route' => '/title',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'title',
],
],
],
'text' => [
'type' => Literal::class,
'options' => [
'route' => '/text',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'text',
],
],
],
Let us know if it makes you happy!
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);
}
controller:
public function searchAction()
{
$form = new Application_Form_Search;
$k = $form->getValue('keyword');
$car = new Application_Model_Car();
$mapper = new Application_Model_CarMapper();
$this->view->cars = $mapper->search($keyword);
}
form
<?php
class Application_Form_Search extends Zend_Form {
public function init(){
$this->setMethod('post');
$this->addElement('text', 'keyword', array(
'required' => true,
'label' => 'Keyword:'
));
$this->addElement('button', 'submit', array(
'required' => false,
'ignore' => true,
'label' => 'Search'
));
}
}
?>
original view page
$(document).ready(function(){
$("#submit").click(function(){
$("#main").load('/cars/search');
});
});
Here I am trying to return the search view at the "id=main" section in the original view page by using .load()
In the search view, <?=$this->keyword?> is showing null
it seems like there's problem fetching the keyword field from the form
Ok, you need to set the second variable of .load to send the data. At present you aren't sending the data to the .load function
so it would be more like this. This is assuming that you have id of keyword
$("#main").load('/cars/search', {'keyword':$('input#keyword').val()});
or you could use
$("#main").load('/cars/search', {'keyword':$('[name="keyword"]').val()});
Please see
http://api.jquery.com/load/
Also remember to escape the value so people can't send malicious code through your form.
Hope that helps
I am having some issues with a form's CSRF validation and the use of sessions which are stored in the database using ZF2.
Here is the code I have added to Module.php onBootstrap() method:
// create session which is persisted in the database
$dbAdapter = $serviceManager->get('Zend\Db\Adapter\Adapter');
$sessionTableGateway = new TableGateway\TableGateway('XXX.XXX', $dbAdapter);
$sessionOptions = new DbTableGatewayOptions();
$sessionOptions->setDataColumn('SESSION_DATA')
->setIdColumn('SESSION_ID')
->setModifiedColumn('SESSION_MODIFIED')
->setLifetimeColumn('SESSION_LIFETIME')
->setNameColumn('SESSION_NAME');
$sessionGateway = new DbTableGateway($sessionTableGateway, $sessionOptions);
$sessionConfig = new SessionConfig();
$sessionConfig->setOptions(array(
'gc_probability' => 1,
'gc_divisor' => 1,
'use_cookies' => true
));
$storage = new SessionStorage();
$sessionManager = new SessionManager($sessionConfig, $storage);
$sessionManager->setSaveHandler($sessionGateway);
$sessionManager->start(true);
Container::setDefaultManager($sessionManager);
In the form, I am creating a standard CSRF element like this:
$this->add(array(
'name' => 'csrf',
'type' => 'Zend\Form\Element\Csrf'
));
When the form is loaded, I can see the CSRF hash in the session which is stored in the database:
__ZF|a:2:{s:20:"_REQUEST_ACCESS_TIME";d:1383673583.296492099761962890625;s:29:"Zend_Validator_Csrf_salt_csrf";a:1:{s:6:"EXPIRE";i:1383673883;}}FlashMessenger|C:23:"Zend\Stdlib\ArrayObject":21:{x:i:2;a:0:{};m:a:0:{}}Zend_Validator_Csrf_salt_csrf|C:23:"Zend\Stdlib\ArrayObject":72:{x:i:2;a:1:{s:4:"hash";s:32:"1ba5170385f4c2e2839766f19c3c2dbd";};m:a:0:{}
When I submit the form, I do not get any errors, however, it seems that the form's isValid() method is failing, and it looks like the CSRF Validation routine always gets a null value for the CSRF token from my session stored in the database.
Any ideas on what is going on here?
Thanks
If you're not having problems with sessions elsewhere in your code then this may be a form issue and not a database session issue. Make sure that the CSRF input element in your form...:
SomeForm.php
use Zend\Form\Element;
use Zend\Form\Fieldset;
use Zend\Form\Form;
use Zend\InputFilter\Input;
use Zend\InputFilter\InputFilter;
use Zend\Validator;
class SomeForm extends Form
{
public function __construct($name = null)
{
parent::__construct('csrf-eg');
$this->setAttribute('method', 'post');
// CSRF field
$this->add
(
array
(
'type' => 'Zend\Form\Element\Csrf',
'name' => 'your_csrf',
'attributes' => array
(
'type' => 'text',
'id' => 'divIDforCsrfField',
),
'options' => array
(
'csrf_options' => array
(
'timeout' => 600
)
),
)
);
}
}
actually has a filter attached and validation for the CSRF field:
SomeFormFilter.php
namespace Some\Form;
use Zend\Form\Element;
use Zend\Form\Fieldset;
use Zend\InputFilter\Input;
use Zend\InputFilter\InputFilter;
use Zend\Validator;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
class SomeFormFilter implements InputFilterAwareInterface
{
public $your_csrf;
protected $inputFilter;
public function exchangeArray($data){...}
public function setInputFilter(InputFilterInterface $inputFilter){...}
public function getInputFilter()
{
if (!$this->inputFilter){
$inputFilter = new InputFilter();
$factory = new InputFactory();
// CSRF field
$inputFilter->add
(
$factory->createInput
(
array
(
'name' => 'your_csrf',
'required' => true,
'validators' => array
(
array
(
'name' => 'Csrf',
'options' => array
(
'messages' => array
(
Validator\Csrf::NOT_SAME => 'Your CSRF validation msg',
),
),
),
)
)
);
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
To get your csrf validation messages into your Action:
$SomeForm = new SomeForm();
$SomeFormValues = $this->getRequest()->getPost();
$SomeForm->setData($SomeFormValues);
$SomeFormFilter = new SomeFormFilter();
$SomeForm->setInputFilter($SomeFormFilter->getInputFilter());
if ($SomeForm->isValid($SomeFormValues))
{
$validatedData = $SomeForm->getData();
}
else
{
$SomeFormMessages = $SomeForm->getMessages();
}
$viewModel = new ViewModel
(
array
(
'SomeFormMessages' => $SomeFormMessages,
)
);
return $viewModel;
I want to use CakePHP's core validation for lists in my model:
var $validate = array(
'selectBox' => array(
'allowedChoice' => array(
'rule' => array('inList', $listToCheck),
'message' => 'Enter something in listToCheck.'
)
)
);
However, the $listToCheck array is the same array that's used in the view, to populate a selectbox. Where do I put this function?
public function getList() {
return array('hi'=>'Hello','bi'=>'Goodbye','si'=>'Salutations');
}
Already in my controller, in one of the actions I'm setting it for the view, like:
public function actionForForm() {
$options = $this->getList();
$this->set('options', $options);
}
So, I don't want to have to copy the getList() function...where can I put it so the Model can call it to populate its $listToCheck array?
Thanks for your help.
Considering that it's data, you should store the list of valid choices in the model.
class MyModel extends AppModel {
var $fieldAbcChoices = array('a' => 'The A', 'b' => 'The B', 'c' => 'The C');
}
You can get that variable in the Controller simply like this:
$this->set('fieldAbcs', $this->MyModel->fieldAbcChoices);
Unfortunately you can't simply use that variable in the rule declaration for the inList rule, since rules are declared as instance variables and those can only be initialized statically (no variables allowed). The best way around that is to set the variable in the Constructor:
var $validate = array(
'fieldAbc' => array(
'allowedChoice' => array(
'rule' => array('inList', array()),
'message' => 'Enter something in listToCheck.'
)
)
);
function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->validate['fieldAbc']['allowedChoice']['rule'][1] = array_keys($this->fieldAbcChoices);
}
If you're not comfortable overriding the Constructor, you could also do this in a beforeValidate() callback.
Also note that you shouldn't name your field 'selectBox'. :)