CakePHP check if there is a booked date - date

I'm struggling with this since a week ago and it's driving me crazy.
I'm doing a website for doing surveys in a forest using CakePHP 2.x.
There is many places, and each place has different points. An user can choose one of those points and book a day for a survey, but there can be only one survey in a point each day.
The models are: Place, Point, User, BookedSurvey
The controllers are: PlacesController, PointsController, UsersController, BookedSurveysControllers
The tables (omitting some that are not necessaries for this question) are places, points, users, booked_surveys; and inside of booked_surveys you can find the fields id (INT AUTO INCREMENT), survey_date (datetime), point_id (int) and user_id (int).
The views are: add, edit, remove, index for each one
When viewing a point, an user can select a date and press "Book survey". This is part of the view:
<h2>Book a date:</h2>
<?php
echo $this->Form->create('BoostCake', array(
'inputDefaults' => array(
'div' => 'form-group',
'label' => array(
'class' => 'col col-md-1 control-label'
),
'wrapInput' => 'col col-md-9',
'class' => 'form-control'
),
'class' => 'form-horizontal'
));
?>
<?php
echo $this->Form->create('Point');
echo $this->Form->input('BookedSurvey.survey_date', array(
'type'=>'date',
'label' => '',
'dateFormat' => 'YMD',
'minYear' => date('Y'),
'minMonth' => date('M'),
'minDay' => date('D'),
'div' => 'col col-md-9',
'style' => 'margin: 15px 5px 5px 0px'
));
echo $this->Form->hidden('User.id', array(
'value' => $user_id)
);
?>
<div class="form-group">
<?php
echo $this->Form->submit('Book survey', array(
'div' => 'col col-md-9',
'class' => 'btn btn-success btn-lg',
'style' => 'margin: 10px 5px 5px 10px'
));
?>
</div>
Then, the controler must search in booked_survey if the point has any survey for the same date. As each field should have only one survey per day, an error will be shown if there is any other survey in the same point for the same day.
And this is the problem: it never finds any coincidence. I Googled, tried all the different options, and still is not working. This is my seach in the PointsController (it's simplified, at the moment I'm trying to search any survey on the same date):
// Begin of comprobation
$booked_condition = $this->Point->BookedSurvey->find('first', array(
'conditions' => array(
'DATE(BookedSurvey.survey_date)' => 'date()'
)
)
);
if ($booked_condition) {
echo "Already booked";
}
// End of comprobation
To be honest, I don't know what is failing, but please, if somebody can help...
OK, solved:
if ($this->request->is('post')) {
$date = $this->request->data['BookedSurvey']['survey_date'];
$formattedDate = CakeTime::format(
"{$date['year']}-{$date['month']}-{$date['day']}",
"%B %e, %Y"
);
print_r($formattedDate); //'Jul 23, 2014'
$isBooked = $this->Point->BookedSurvey->find('count', array(
// replace the date as you see fit, using Jul 23, 2014 as an example
'conditions' => CakeTime::dayAsSql($formattedDate, 'survey_date')
));
echo "status";
print_r($isBooked);
print_r(date('m'));
print_r($this->request->data['BookedSurvey']['survey_date']);
if($isBooked > 0) {
echo "Already booked";
}
}

As suggested, this is the solution to the problem:
if ($this->request->is('post')) {
$date = $this->request->data['BookedSurvey']['survey_date'];
$formattedDate = CakeTime::format(
"{$date['year']}-{$date['month']}-{$date['day']}",
"%B %e, %Y"
);
print_r($formattedDate); //'Jul 23, 2014'
$isBooked = $this->Point->BookedSurvey->find('count', array(
// replace the date as you see fit, using Jul 23, 2014 as an example
'conditions' => CakeTime::dayAsSql($formattedDate, 'survey_date')
));
echo "status";
print_r($isBooked);
print_r(date('m'));
print_r($this->request->data['BookedSurvey']['survey_date']);
if($isBooked > 0) {
echo "Already booked";
}
}

Related

Create a SelectBox using Form Helper in CakePHP3

I am trying to make a combo box for an edit page.
echo $this->Form->select('status',
['empty' => 'Select Status'],
['class' => 'form-control', 'required']
);
Here I want to add 2 things :
$options = array('0' => 'Inactive',
'1' => 'Active',
);
and selected value. suppose that is $status;
I tried with different options but sometime it do not add classes and sometime it shows options in tag
It will be great if somebody give clue.
Thanks
<?= $this->Form->input('status', [
'type' => 'select',
'options' => ['0' => __('Inactive') , '1' => __('Active')],
'empty' => __('Select Status'),
'class' => 'form-control',
'required' => true, 'label' => __('Type')
])
?>

Can't save retrieved from database drop down values in zend framework 2

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?

CakePHP 2.1 Contact Form in Element Won't Send

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

CodeIgniter: Controller structure for forms with many inputs

I'm developing a site using CodeIgniter and am trying to adhere to the "Fat Model / Skinny Controller" paradigm, but am running into some problems when it comes to pages containing forms with a number of inputs. The code below is what I'm using to define the inputs for the address fields
Part of my Controller (where I'm defining the form inputs and their attributes):
$this->data['address1'] = array(
'name' => 'address1',
'id' => 'address1',
'type' => 'text',
'class' => 'field text addr',
'tabindex' => '10',
'value' => $this->form_validation->set_value('address1'),
'placeholder' => 'Street Address'
);
$this->data['address2'] = array(
'name' => 'address2',
'id' => 'address2',
'type' => 'text',
'class' => 'field text addr',
'tabindex' => '11',
'value' => $this->form_validation->set_value('address2'),
'placeholder' => 'Address Line 2',
);
$this->data['city'] = array(
'name' => 'city',
'id' => 'city',
'type' => 'text',
'class' => 'field text addr',
'tabindex' => '12',
'value' => $this->form_validation->set_value('city'),
'placeholder' => 'City'
);
$this->data['state'] = array(
'name' => 'state',
'id' => 'state',
'class' => 'field addr',
'tabindex' => '13',
'value' => $this->form_validation->set_value('state'),
'label' => array('class' => 'desc')
);
$this->data['zip'] = array(
'name' => 'zip',
'id' => 'zip',
'type' => 'text',
'class' => 'field text addr',
'tabindex' => '14',
'maxlength' => '20',
'value' => $this->form_validation->set_value('zip'),
'placeholder' => 'Zip / Postal Code'
);
$this->data['country'] = array(
'name' => 'country',
'id' => 'country',
'class' => 'field addr',
'tabindex' => '15',
'value' => $this->form_validation->set_value('country')
);
Part of my View (minus all the HTML to position the form inputs):
<?php
echo form_open("address/add");
echo form_input($address1);
echo form_input($address2);
echo form_input($city);
$options = array();
$options[''] = 'State / Province / Region';
foreach($province_options AS $prov)
{
$options[$prov->id] = $prov->province;
}
echo form_dropdown('state',$options,'',$state);
echo form_input($zip);
$options = array();
$options[''] = 'Country';
foreach($country_options AS $cnt)
{
$options[$cnt->id] = $cnt->country;
}
echo form_dropdown('country',$options,'',$country);
echo form_submit('submit', 'Submit & Continue');
echo form_close();
?>
I feel like my Controller is overly verbose, but I can't think of what the alternative would be for how to organize the information necessary to represent my form if I'm planning on using the Form Helper to generate the form inputs in my view. Is this the right way to be doing things, or is there a better approach?
Just because Codeigniter provides all of these helpers does not mean you have to use them!
All you need is form_open() because this adds the CRSF token (if used).
Raw HTML is much cleaner and I suspect much faster than waiting for PHP to render markup.
Edit: I would like to add, the reason its cleaner is because you have control over the output, where as CI might adere to certain specifications.
I don't see a problem in your question.
This is just silly
$options = array();
$options[''] = 'State / Province / Region';
There is a little bit of logic that can be moved to the controller or even model layer:
$options = array();
$options[''] = 'Country';
foreach($country_options AS $cnt)
{
$options[$cnt->id] = $cnt->country;
}
echo form_dropdown('country',$options,'',$country);
Could probably look like:
echo form_dropdown('country', $countries, '', $country);
...if you move the options to the controller or view.
This is a problem I run into all the time trying to keep things DRY as possible, where to define the form data? I think sometimes we forget the power of the "V" in "MVC". You could define all the view logic in the view instead.
Things like id, tabindex and placeholder are only necessary and useful in the view. Things like form validation rules and data checking/prepping belong in the Controller/Model layer.
The form helper functions are useful, but sometimes raw HTML is better. For example:
// Controller
$this->data['address1'] = array(
'name' => 'address1',
'id' => 'address1',
'type' => 'text',
'class' => 'field text addr',
'tabindex' => '10',
'value' => $this->form_validation->set_value('address1'),
'placeholder' => 'Street Address'
);
// View
echo form_input($address1);
Or simply:
<input name="address1" id="address1" tabindex="10" type="text" placeholder="Street Address" value="<?php echo set_value('address1'); ?>" class="field text addr">
I wrote a bunch of applications last year where I defined all this stuff in the Model, and now I'm regretting it as I've been going back to do maintenance on them and all the view logic is obscured away in the Model or Controller. Editing a Controller or Model to change a class attribute is just silly.

Zend Form decorators trouble

How do I achieve the following with form decorators for form elements:
<dt>
<ul>
<li>The errors</li>
<li>The errors</li>
</ul>
<label>The label</label>
</dt>
<dd>
<input type="text" value="The input field">
</dd>
In other words, in stead of Errors appended after the input field, I want them prepended before the Label. I do however want to keep the <dt> and <dd> tags as illustrated above.
Alright, I found out how to do it. Gradually the decorators are starting to make sense to me:
$decorators = array(
'Label',
array( 'Errors', array( 'placement' => 'prepend' ) ),
array( array( 'dt' => 'HtmlTag' ), array( 'tag' => 'dt' ) ),
array( array( 'ddOpen' => 'HtmlTag' ), array( 'tag' => 'dd', 'openOnly' => true, 'placement' => 'append' ) ),
array( 'ViewHelper' ),
array( array( 'ddClose' => 'HtmlTag' ), array( 'tag' => 'dd', 'closeOnly' => true, 'placement' => 'append' ) )
);
What this does is the following:
First render the Label
Then prepend (default = append) the Errors
Wrap (default) all previous content in a HtmlTag (dt)
Next, append (default = wrap) a opening HtmlTag (dd)
Then append (default) the ViewHelper
Next, append (default = wrap) a closing HtmlTag (dd)
Then set the decorators:
// be sure to only set them, after you have added the relevant elements to the form
$this->setElementDecorators( $decorators );
PS:
Be aware though that my particular example produces invaliid html. ;-) I only found out later that <ul> elements are not allowed in <dt> elements with DOCTYPE HTML 4.01 strict
In your form class, try this:
$this->setElementDecorators(array(
'Errors',
'ViewHelper',
'Label',
));