Hey guys trying to declare a variable in CakePHP in the Fields Controller. This variable will display the template id from the template table, but the view is saying the variable is undefined even though we delared it in the controller. Temaplates has many fields and fields belongs to templates.
Here is the Fields Controller:
<?php
class FieldsController extends AppController{
public $uses = array('Template');
function add(){
$this->set('title_for_layout', 'Please Enter Your Invoice Headings');
$this->set('stylesheet_used', 'style');
$this->set('image_used', 'eBOXLogo.jpg');
$this->Session->setFlash("Please create your required fields.");
$templates = $this->Template->find('list');
//$current_template = $this->request->data['Field']['template_id'];
// right way to do it, but Template is undefined, and says undefined var
//$template = $this->request->data['Field']['template_id'];
// makes sense with the find, no errors, but still doesnt print in form, says undefined var
//$current_template = $this->request->data($template['Field']['template_id']);
if($this->request->is('post'))
{
$this->Field->create();
if ($this->Field->save($this->request->data))
{
if($this->request->data['submit'] == "type_1")
{
$this->Session->setFlash('The field has been saved');
$this->redirect( array('controller' => 'fields','action' => 'add'));
}
if($this->request->data['submit'] == "type_2")
{
$this->Session->setFlash('The template has been saved');
$this->redirect( array('controller' => 'templates','action' => 'index'));
}
}
else
{
$this->Session->setFlash('The field could not be saved. Please, try again.');
}
}
}
}
And here is our add view which adds fields:
<?php
echo $this->Form->create('Field', array('action'=>'add'));
echo $this->Form->create('Field', array('action'=>'add'));
echo $this->Form->input('name', array('label'=>'Name: '));
echo $this->Form->input('description', array('label'=>'Description: '));
//echo $this->Form->input('template_id',array('label'=>'Template ID: ', 'type' => 'select', 'options' => $templates));
echo $this->Form->input('template_id',array('label'=>'Template ID: ', 'type' => 'text', 'default'=> $templates));
//echo $this->Form->input('templates_id', array('label'=>'Template ID: ', 'type' => 'text', 'default' => $current_template['templates_id']));//this would be the conventional fk fieldname
echo $this->Form->button('Continue adding fields', array('name' => 'submit', 'value' => 'type_1'));
echo $this->Form->button('Finish adding fields', array('name' => 'submit', 'value' => 'type_2'));
echo $this->Form->end();
?>
You should try the following code:
<?php
class FieldsController extends AppController{
public $uses = array('Template', 'Field');
function add(){
$this->set('title_for_layout', 'Please Enter Your Invoice Headings');
$this->set('stylesheet_used', 'style');
$this->set('image_used', 'eBOXLogo.jpg');
$this->Session->setFlash("Please create your required fields.");
$templates = $this->Template->find('list', array('fields' => array('Template.id, Template.template_name' );
$this->set('templates', $templates);
//$current_template = $this->request->data['Field']['template_id'];
// right way to do it, but Template is undefined, and says undefined var
//comment: You should check the request data with in if condition
//$template = $this->request->data['Field']['template_id'];
// makes sense with the find, no errors, but still doesnt print in form, says undefined var
//$current_template = $this->request->data($template['Field']['template_id']);
if($this->request->is('post'))
{
$this->Field->create();
if ($this->Field->save($this->request->data))
{
if($this->request->data['submit'] == "type_1")
{
$this->Session->setFlash('The field has been saved');
$this->redirect( array('controller' => 'fields','action' => 'add'));
}
if($this->request->data['submit'] == "type_2")
{
$this->Session->setFlash('The template has been saved');
$this->redirect( array('controller' => 'templates','action' => 'index'));
}
}
else
{
$this->Session->setFlash('The field could not be saved. Please, try again.');
}
}
}
}
You view should looks like:
<?php
echo $this->Form->create('Field', array('action'=>'add'));
echo $this->Form->input('name', array('label'=>'Name: '));
echo $this->Form->input('description', array('label'=>'Description: '));
echo $this->Form->input('template_id',array('label'=>'Template ID: ', 'options' => $templates));
//echo $this->Form->input('template_id',array('label'=>'Template ID: ', 'type' => 'text', 'default'=> $templates));
//echo $this->Form->input('templates_id', array('label'=>'Template ID: ', 'type' => 'text', 'default' => $current_template['templates_id']));//this would be the conventional fk fieldname
echo $this->Form->button('Continue adding fields', array('name' => 'submit', 'value' => 'type_1'));
echo $this->Form->button('Finish adding fields', array('name' => 'submit', 'value' => 'type_2'));
echo $this->Form->end();
?>
Kindly check and verify if it is working for you or not.
You are missing $this->set('templates', $templates); after doing the find() for templates in your controller.
Related
First issue is I have the following validators and public function in my table
UsersTable.php
$validator
->scalar('name')
->maxLength('name', 45)
->requirePresence('name', 'create')
->notEmptyString('name', 'You must enter a name for the user.');
$validator
->add('name', 'custom', array('rule' => 'checkExistingUser', 'message' => 'This user already appears to be in the system.', 'on' => 'create'));
public function checkExistingUser($value,$context)
{
return $this->find('all', ['conditions' => ['Users.name' => $context['data']['name'], 'Users.user_type_id' => $context['data']['user_type_id']]])->count() < 1 ;
}
When I save the form below I receive the message "Method checkExistingUser does not exist". Why doesn't it recognize the method when it's clearly defined in the table model? Am I missing something?
add.ctp
<?php echo $this->Form->create($user);?>
<fieldset>
<legend><?php echo __('Add User'); ?></legend>
<?php
echo $this->Form->control('name', ['type' => 'text']);
echo $this->Form->control('user_type_id');
echo $this->Form->control('owner', array('type' => 'text', 'label' => "Owner Name"));
echo $this->Form->control('owner_contact', array('type' => 'text', 'label' => "Owner Contact (phone, email etc)"));
echo $this->Form->control('description', ['type' => 'textarea']);
echo $this->Form->control('ia_exception', array('type' => 'text', 'label' => "IA Exception Number"));
echo $this->Form->control('is_manual', array('type' => 'checkbox', 'label' => "Password Updated Manually"));
echo $this->Form->control('Environment', ['type' => 'select', 'multiple' => 'true', 'label' => 'Environment(s)']);
?>
</fieldset>
<div class="buttons">
<?php
echo $this->Form->button('Save', ['type'=> 'submit', 'name' => 'submit']);
echo $this->Form->button('Cancel', ['type' => 'button', 'name'=>'cancel', 'onClick' => 'history.go(-1);return true;']);
echo $this->Form->end();
?>
</div>
UsersController.php
function add() {
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->set('The user has been saved');
return $this->redirect(array('action' => 'index'));
} else {
$this->Flash->set('The user could not be saved. Please, try again.');
}
}
$userTypes = $this->Users->UserTypes->find('list');
$changeSteps = $this->Users->ChangeSteps->find('list');
$environments = $this->Users->Environments->find('list');
$this->set(compact('user','userTypes', 'changeSteps', 'environments'));
}
Second issue is when I try to submit my form to check that the validator is working correctly for an empty name field I don't receive the message 'You must enter a name for the user'. Instead I receive a message stating 'This field is required'. Why is it not showing my message from notEmptyString? And where is 'This field is required' coming from?
For the first issue, I had to add a provider in my validator.
I changed
$validator
->add('name', 'custom', array('rule' => 'checkExistingUser', 'message' => 'This user already appears to be in the system.', 'on' => 'create'));
To this
$validator
->add('name', 'custom', ['rule' => 'checkExistingUser', 'provider' => 'table', 'message' => 'This user already appears to be in the system.', 'on' => 'create']);
Be careful with custom methods for validation during patching, because Cake expects string to be returned, otherwise it will rendere default meassage.
So for example, if we use a custom validation function during patching
// in a Controller
$this->Users->patchEntity($user, $data, ['validate' => 'custom');
Same applies for closures.
// in UserTable.php
public function validationCustom(Validator $validator) {
$validator = $this->validationDefault($validator);
$validator
->minLength('password',8,'At least 8 digits');
$validator->add('password',
'strength_light',[
'rule' => 'passwordCheck',
'provider' => 'table',
'message' => 'At least a number and a capital letter'
]
);
return $validator;
}
public function passwordCheck ($value = "") {
return preg_match("/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{8,}/",$value);
}
This will return default message and not the custom one ("At least..") because we set a callable not-cakephp function as rule for custom validation, so the message should be returned by the called function:
public function passwordCheck ($value = "") {
if (!preg_match("/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{8,}/",$value))
return "At least a number and a capital letter";
}
I am creating a magento custom admin module and a form. I want update this form but not updating. In Controller, under SaveAction() I print $this->getRequest()->getPost() and get empty array. please help me. Below code for form declination..
protected function _prepareForm() {
$form = new Varien_Data_Form(array(
'id' => 'edit_form1',
'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),
'method' => 'post',
'enctype' => 'multipart/form-data'
)
);
$form->setUseContainer(true);
$this->setForm($form);
return parent::_prepareForm();
}
And Create a from filed set like
protected function _prepareForm() {
$form = new Varien_Data_Form();
$this->setForm($form);
$fieldset = $form->addFieldset('qbanner_form', array('legend' => Mage::helper('qbanner')->__('Art information')));
$fieldset->addField('name', 'text', array(
'label' => Mage::helper('catalog')->__('Product'),
'required' => false,
'name' => 'name',
));
$fieldset->addField('artist_name', 'text', array(
'label' => Mage::helper('catalog')->__('Artist Name'),
// 'name' => 'artist_name',
'value' => Mage::helper('catalog')->__('Art Name value'),
));
$fieldset->addField('bca_status', 'select', array(
'label' => Mage::helper('catalog')->__('Art status'),
'name' => 'bca_status',
'values' =>$this->_getAttributeOptions('bca_status'),
));
$fieldset->addField('reason', 'editor', array(
'name' => 'reason',
'label' => Mage::helper('catalog')->__('Reason'),
'title' => Mage::helper('catalog')->__('Reason'),
'style' => 'width:440px; height:300px;',
'wysiwyg' => true,
'required' => false,
));
$fieldset->addField('thumbnail', 'text', array(
'label' => Mage::helper('catalog')->__('Art status'),
'name' => 'thumbnail',
//'values' =>$this->_getAttributeOptions('thumbnail'),
//'renderer' => 'Qaz_Qbanner_Block_Adminhtml_Qbanner_Grid_Renderer_Image'
));
if (Mage::getSingleton('adminhtml/session')->getQbannerData()) {
$form->setValues(Mage::getSingleton('adminhtml/session')->getQbannerData());
Mage::getSingleton('adminhtml/session')->setQbannerData(null);
} elseif (Mage::registry('qbanner_data')) {
$form->setValues(Mage::registry('qbanner_data')->getData());
}
return parent::_prepareForm();
}
protected function _getAttributeOptions($attribute_code)
{
$attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', $attribute_code);
$options = array();
foreach( $attribute->getSource()->getAllOptions(true, true) as $option ) {
$options[$option['value']] = $option['label'];
}
return $options;
}
Here my
SaveAction()
public function saveAction() {
echo print_r( $this->getRequest()->getPost());
}
I have tied verious post. Any ideas?
Common error for all. You just need to add form key to your form.
Just add this line below your form declaration.
<input type="hidden" name="form_key" value="<?php echo Mage::getSingleton('core/session')->getFormKey(); ?>" />
Like this
<form action="<?php echo Mage::helper("adminhtml")->getUrl("demo/adminhtml_demo/demo");?>" method="post" id="custom-payment-form" enctype="multipart/form-data">
<input type="hidden" name="form_key" value="<?php echo Mage::getSingleton('core/session')->getFormKey(); ?>" />
Add this. Now you can get parameters by $this->getRequest()->getPost().
you can get variable of post and get method in magento with $this->getRequest()->getParams(); getParams() method But if you want to get exactly some variable data then use getParam('id');
/magento/catalog/product/view/id/406/category/14
$this->getRequest()->getParam('id') // 406
$this->getRequest()->getParams(); //get all get and post variables
First of all, excuse me for my poor english.
I have read a lot about populating a drop down with values from a database in zend framework 2, the 2 links that help me a lot are these:
http://framework.zend.com/manual/2.2/en/modules/zend.form.collections.html
http://zf2.readthedocs.org/en/release-2.1.4/modules/zend.form.advanced-use-of-forms.html
This is what i did
I create a form, and add a field of type "categoryFieldset"
class ProductForm extends Form
{
public function init()
{
// we want to ignore the name passed
parent::__construct('product');
$this->setName('product');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'id',
'type' => 'Hidden',
));
$this->add(array(
'name' => 'name',
'type' => 'Text',
'options' => array(
'label' => 'Name',
),
));
$this->add(array(
'name' => 'category',
'type' => 'CategoryFieldSet',
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Add',
'id' => 'submitbutton',
),
));
}
}
i create a class named categoryFieldset that extends from fieldset where I added a select field:
class CategoryFieldset extends Fieldset
{
function _construct(CategoryTable $categoryTable)
{
parent::_construct('category_fieldset');
$this->setHydrator(new ClassMethodsHydrator(false))->setObject(new Category());
$categorySelectOptionsArray = $categoryTable->populateSelectCategory();
$this->add(array(
'name' => 'categoryField',
'type' => 'Select',
'options' => array(
'label' => 'Category',
'value_options' => $categorySelectOptionsArray,
),
));
}
}
Add code to my module file:
public function getFormElementConfig()
{
return array(
'factories' => array(
'CategoryFieldSet' => function($sm) {
$serviceLocator = $sm->getServiceLocator();
$categoryTable = $serviceLocator->get('Administrador\Model\CategoryTable');
$fieldset = new CategoryFieldset($categoryTable);
return $fieldset;
},
)
);
}
My view has this:
$form = $this->form;
$form->setAttribute('action', $this->url('product', array('action' => 'add')));
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formHidden($form->get('id'));
echo $this->formRow($form->get('name'));
echo "";
$category_fieldset = $form->get('category');
echo $this->formRow($category_fieldset->get('categoryField'));
echo "";
echo $this->formSubmit($form->get('submit'));
echo "";
echo $this->form()->closeTag();
Right now everything is fine, the select elements are showing the values from database, but my problem is when i try to add the data to the database, the field where is the dropdown of categories is saved with the value "0" instead of the id value of the category. I think the problem is the way the view is rendering the select field, when i checked the HTML code i notice that the name of the select field is "category[categoryField]" and it should be "category".
This is the HTML code:
<span>Category</span>
<select name="category[categoryField]">
<option value="1">Category 1</option>
<option value="2">Category 2</option>
<option value="3">Category 3</option>
<option value="4">Category 4</option>
<option value="5">Category 5</option>
</select>
I printed the $request->getPost() array in the viw and this is what it shows:
Zend\Stdlib\Parameters Object ( [storage:ArrayObject:private] => Array ( [id] => [name] => Product1 [category] => Array ( [categoryField] => 2 ) [submit] => Add ) )
What do i need to do to make the field name shows like "category" or to be able to save that record to the database?
I have two contact forms in my CakePHP application -- one with its own Controller, Model, and View, and another one in an element that can be accessed as a "quick" contact form from the footer of every page on the site.
The code for both forms is the same. The element is intended to access the Controller and Model that the other form uses. However, the element is not submitting the data or sending the email, while the regular page works just fine.
Here is the MVC Code for the regular form that IS working:
<!-- Model: Model/Contact.php -->
<?php
class Contact extends AppModel {
var $name = 'Contacts';
public $useTable = false; // Not using the database, of course.
var $validate = array(
'name' => array(
'rule' => '/.+/',
'allowEmpty' => false,
'required' => true,
),
'email' => array(
'allowEmpty' => false,
'required' => true,
)
);
function schema() {
return array (
'name' => array('type' => 'string', 'length' => 60, 'class' => 'contact input'),
'email' => array('type' => 'string', 'length' => 60, 'class' => 'contact input'),
'message' => array('type' => 'text', 'length' => 2000, 'class' => 'contact input'),
);
}
}
?>
<!-- Controller: Controller/ContactsController.php -->
class ContactsController extends AppController
{
var $name = 'Contacts';
/* var $uses = 'Contact'; */
var $helpers = array('Html', 'Form', 'Js');
var $components = array('Email', 'Session');
public function index() {
if(isset($this->data['Contact'])) {
$userEmail = $this->data['Contact']['email'];
$userMessage = $this->data['Contact']['message'];
$email = new CakeEmail();
$email->from(array($userEmail));
$email->to('email#example.com');
$email->subject('Website Contact Form Submission');
$email->send($userMessage);
if ($email->send($userMessage)) {
$this->Session->setFlash('Thank you for contacting us');
}
else {
$this->Session->setFlash('Mail Not Sent');
}
}
}
public function contact() {
if(isset($this->data['Contact'])) {
$userEmail = $this->data['Contact']['email'];
$userMessage = $this->data['Contact']['message'];
$email = new CakeEmail();
$email->from(array($userEmail));
$email->to('email#example.com');
$email->subject('Website Contact Form Submission');
$email->send($userMessage);
if ($email->send($userMessage)) {
$this->Session->setFlash('Thank you for contacting us');
// $this->redirect(array('controller' => 'pages', 'action' => 'index'));
}
else {
$this->Session->setFlash('Mail Not Sent');
}
}
}
}
?>
<!-- View: Views/Contacts/index.ctp -->
<?
$main = 'contact';
$title = 'quick contact';
?>
<div style="border-bottom: solid 1px #ccc;">
<h1 style="position:relative; float:left;"><?php echo $main; ?></h1>
<h2 style="position:relative;float:left;margin-top:15px; color: #869c38"> • <?php echo $title;?></h2>
<br><br>
</div>
<div class="clear"><br></div>
<div id="interior-page">
<?php
echo $this->Form->create('Contact');
echo $this->Form->input('name', array('default' => 'name (required)', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->input('email', array('default' => 'email (required)', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->input('message', array('default' => 'message', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->submit();
echo $this->Form->end();
?>
</div>
And here is the view for the quick contact form that is NOT working, located in an element displayed in the footer of the default layout:
<?php
echo $this->Form->create('Contact');
echo $this->Form->input('name', array('default' => 'name (required)', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->input('email', array('default' => 'email (required)', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->input('message', array('default' => 'message', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->submit();
echo $this->Form->end();
?>
I tried different ways of changing the form action, but I couldn't figure that out.
Usually, cake "automagically" creates the action of the form based on where you call it from E.g. if called from the view Views/Contacts/index.ctp, it will set the action to /contacts/index. In case of an element, Cake can't really guess what you're trying to do, so you need to set the action manually:
$this->Form->create('Contact', array('action' => 'index'));
Or set the full URL alternatively:
$this->Form->create('Contact', array('url' => '/contacts/index'));
Make sure you're including the Contact model for use on every page you need to create that form. In your case, since it's in your layout, that likely means you should put it in your AppController, so every page has access to it.
You also need to specify where the form should submit to:
echo $this->Form->create('Contact', array(
'url' => array('controller'=>'contacts', 'action'=>'contact')
)
);
Off-note - You can combine the last 2 lines:
echo $this->Form->end('Submit');
This creates the submit button with text "Submit" and also closes the form.
Thanks for this! It helped me a lot.
Just a quick thing, you're sending the email twice.
Once here:
$email->send($userMessage);
And again here:
if ($email->send($userMessage))
The first instance ($email->send($userMessage)) isn't necessary.
Cheers
I have some trouble making a customized breadcrumb:
I my layout.phtml I have:
$container = new Zend_Navigation();
$this->navigation($container);
$container->addPage(
array(
'label' => 'Dashboard',
'module' => 'default',
'controller' => 'dashboard',
'action' => 'index',
'pages' =>
array(
array(
'label' => 'Create Order',
'module' => 'default',
'controller' => 'createorder',
'action' => 'index'
),
array(
'label' => 'Query',
'module' => 'default',
'controller' => 'query',
'action' => 'index',
'pages' => array(
array(
'label' => 'View Order',
'module' => 'default',
'controller' => 'order',
'action' => 'vieworder'
)
)
),
array(
'label' => 'Administration',
'module' => 'default',
'controller' => 'admin',
'action' => 'index',
'pages' =>
array(
array(
'label' => 'News and Announcements',
'module' => 'default',
'controller' => 'admin',
'action' => 'addnews',
'pages' => array(
array(
'label' => 'Edit News and Announcements',
'module' => 'default',
'controller' => 'admin',
'action' => 'editnews'
)
)
)
)
)
)
)
);
The next line is:
echo $this->navigation()->breadcrumbs()->setPartial(array('BreadCrumb.phtml','default'));
The BreadCrumb.phtml is called well, but I don't know how to make an ul-li menu in my BreadCrumb.phtml. How do I get the navigation I'm actually in?
Thanks in advance for any help. Andrea
To do so, your BreadCrumb.phtml should look like this:
<?php
if (null === $this->container) {
$this->container = $this->breadcrumbs()->getContainer();
}
// find deepest active
if (!$active = $this->breadcrumbs()->findActive($this->container)) {
return '';
}
$active = $active['page'];
// put the deepest active page last in breadcrumbs
if ($this->breadcrumbs()->getLinkLast()) {
$html = ' <li>' . $this->breadcrumbs()->htmlify($active) . '</li>' . PHP_EOL;
} else {
$html = $active->getLabel();
if ($this->breadcrumbs()->getUseTranslator() && $t = $this->breadcrumbs()->getTranslator()) {
$html = $t->translate($html);
}
$html = ' <li>' . $this->escape($html) . '</li>' . PHP_EOL;
}
// walk back to root
while (($parent = $active->getParent()) != null) {
if ($parent instanceof Zend_Navigation_Page) {
// prepend crumb to html
$html = ' <li>' . $this->breadcrumbs()->htmlify($parent) . '</li>' . PHP_EOL . $html;
}
if ($parent === $this->container) {
// at the root of the given container
break;
}
$active = $parent;
}
echo strlen($html) ? $this->breadcrumbs()->getIndent() . '<ul id="breadcrumbs">' . PHP_EOL
. $html . '</ul>' . PHP_EOL : '';
?>
Then you will get something like this:
<ul id="breadcrumbs">
<li>Home</li>
<li>Articles</li>
<li>Shop</li>
<li>Last link</li>
</ul>
Inside the view script, the zend navigation container is retrievable via $this->container. The container is iterable, so you can walk through it with a simple foreach loop (e.g. foreach($this->container as $page)
I've found simple solution for render breadcrumbs wrapped in ul-li menu.
You can place this code in your breadcrumbs.phtml:
<?php $breadcrumbs = $this->navigation()->breadcrumbs()->setMinDepth(0); ?>
<?php $items = array_filter(explode($breadcrumbs->getSeparator(), $breadcrumbs->render())); ?>
<?php if ($items) : ?>
<ul class="breadcrumbs">
<?php foreach ($items as $item) : ?>
<li><?= $item ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>