I have to modify the PHPTAL template below by adding another field, "location"
<tal:block tal:repeat="contact Model/contactList">
<div class="contactCell">
Name: <span content="contact/name">contact name</span><br/>
Number: <span content="contacy/number">2374687234</span><br/>
<-- THIS NEEDS ADDING-->
Location: <span content="contact/location">contact's location</span>
</div>
</tal:block>
My problem is that I don't know what methods and properties are available in the model and I don't want to read the PHP code to trace this either. I would like to be able to dump out all the properties of the model from within the template so it's easy to see if the property I need is already available or whether I have to ask the backend dev to make it available. Something like this would be good.
<div class="debug panel">
<tal:dumpObject Model/contactList>
</div>
which would then produce something like this in my HTML output:
<div class="debug panel">
contact Array
[
{
[name] => John Smith
[number] => 374862378
[address] => 22 Acacia Avenue
[location] => London
},{
[name] => Billy Bragg
[number] => 384567365
[address] => 10 Downing Street
[location] => London
},
...
]
</div>
This way I would be able to immediately see what I can use and what I need to request from other devs.
You can get pretty far with:
<pre tal:content="php:print_r(object, true)"/>
if the object is a plain array or a stdClass object.
However, PHPTAL can also read object's methods and invokes magic __get() methods, so if the object is from some fancy ORM it may not be possible to list all properties that would work.
You can use var_dump inside PHPTAL as well:
<pre tal:content="php:var_dump(object)"/>
Related
Is it possible to add a class to the hidden form created by CakePHP's postLink form helper?
Here's my code
Form->postLink(
' ' . __('Delete'),
['action' => 'delete', $this->fetch('item')],
['confirm' => __('Are you sure you want to delete # {0}?', $this->fetch('item'))
,'escape' => false
,'title' => __('Delete')
,'class' => 'btn btn-danger btn-xs isAction'
]) ?>
Note that I'm not looking to add a class to the link that gets created.
Any ideas are welcome!
There's pretty much only one way currently, and that would be to change the formStart template temporarily, something along the lines of this:
// read current template and set the new one
$formStart = $this->Form->getTemplates('formStart');
$this->Form->setTemplates([
'formStart' => '<form class="hiddenFormClass"{{attrs}}>'
]);
echo $this->Form->postLink(/* ... */);
// set the template back to its previous state
$this->Form->setTemplates([
'formStart' => $formStart
]);
It's also possible to reset the templates to their default state using the resetTemplates() method, however this would reset all possible changes made to any of the templates, so it's probably better to play it safe as shown above.
See also
Cookbook > Controllers > Views > Helpers > Form > Customizing the Templates FormHelper Uses
API \Cake\View\Helper\FormHelper::setTemplates()
API \Cake\View\Helper\FormHelper::getTemplates()
API \Cake\View\Helper\FormHelper::resetTemplates()
I am trying to shift a website from using a MS-SQL database to SQLite. I have therefore exported the MS-SQL database to SQLite and connected it successfully with Dancer, the lightweight Perl web framework which uses Template Toolkit.
I now have an issue with the FOREACH loops. Data is being passed as usual - as tested with the debug to_dumper($test) statement - but TT does not show it. Are you aware of any differences between MS-SSQL and SQLite? Other FOREACH loops also appear to have the same non display of data issue.
Any ideas are much appreciated!
a tail on the data passed is:
{
'OneLiner' => 'Cruise on the Kerala backwaters',
'Meta_Descr' => 'Get inspired by the trip ideas on our Traveller\'s Palm website. We are passionate about India and will be delighted to help you in designing your own tailor-made tour.',
'PageName' => 'Popular Tours',
'Introduction' => 'Tried and tested by thousands of clients over thirty years, these tours are the classics that always deliver. Tweaked and perfected based on our clients\' feedback these tours give you that perfect introduction to India or are the quickest way to travel between your old favourites. Rajasthan, Kerala, Goa and North India all feature on these tours and with good reason.
We\'d also be happy to make any personalized changes or additions to these itineraries if you so choose and add your personal twist to these well-loved highlights.',
'Meta_Title' => 'Popular Tours - Experience India | Traveller\'s Palm',
'url' => 'popular-tours',
'Themes_id' => 7,
'Meta_Keywords' => 'popular holidays india, tailor-made popular india tours, popular india custom tour'
},
{
'Meta_Title' => 'Romance - Experience India | Traveller\'s Palm',
'Introduction' => 'Muslin draped four poster bed or a gently moving boat in the tropical backwaters? Tracking a tiger or exploring a working farm? Your romantic getaway can be what you want it to be; a sybaritic time with your beloved or an active and adventurous time shared with your spouse.',
'Meta_Descr' => 'Get inspired by the trip ideas on our Traveller\'s Palm website. We are passionate about India and will be delighted to help you experience the romance of travel in India.',
'PageName' => 'Romance',
'OneLiner' => 'Looking for a romantic getaway',
'Meta_Keywords' => 'romantic holidays india, tailor-made india romantic holidays, india honeymoon tour',
'Themes_id' => 12,
'url' => 'romance'
}
]; in /home/user/webapps/travelo/lib/xxx/MemcacheDB.pm l. 1483
the memcached query is identical as used with the MS-SQL based site:
sub themes {
return memcached_get_or_set('themes',sub {
my $qry = "SELECT pagename,introduction,url, oneliner,
meta_title,meta_descr,meta_keywords,themes_id
FROM themes";
my $test = database('sqlserver')
->selectall_arrayref( $qry, { Slice => {} } );
debug to_dumper($test);
return $test;
});
}
The relevant html section in TT is:
<ul class="slides image-box style1">
[% FOREACH theme in themes %]
<li>
<article class="box">
<figure>
<a class="hover-effect" title="[% theme.title %]" href="[% request.uri_base %]/destinations/[% country %]/[% THEMES %]/[% theme.url %]">
<img width="270" height="160" alt="" src="[% IMAGE %]/themes/themes_[% theme.themes_id %].jpg" />
</a>
</figure>
<div class="details">
<h4 class="box-title">[% theme.pagename %]</h4>
</div>
</article>
</li>
[% END %]
</ul>
First off I'm new to cakephp.... I'm pulling survey questions from a database and building a form of type=file.
echo $this->Form->create('PersonalDetail', array('type' => 'file', 'id' => 'editProfileForm', 'class' => 'form-horizontal'));
echo $this->Form->hidden('id');
echo $this->Form->hidden('PersonalDetail.id');
echo $this->Form->input('PersonalDetail.field_name', array('label' => false, 'div' => false, 'readonly' => false));
echo $this->Form->submit('Update Profile', array('class' => 'btn btn-primary', 'id' => 'editProfileSubmitBtn'));
echo $this->Form->end();
According to cakephp docs "Since this is an edit form, a hidden input field is generated to override the default HTTP method." But I can't seem to figure out how to tell cake this is an edit form. It always inserts a hidden POST not PUT method:
<form action="/editForm" id="editProfileForm" class="form-horizontal" enctype="multipart/form-data" method="post" accept-charset="utf-8">
<div style="display:none;">
<input type="hidden" name="_method" value="POST"/>
<input type="hidden" name="data[_Token][key]" value="ff8b198e82d800a35581" id="Token836"/></div>
<input type="hidden" name="data[id]" id="id"/>
<input type="hidden" name="data[PersonalDetail][id]" id="PersonalDetailsId"/>
<label class="control-label required">Username</label>
<input name="data[PersonalDetail][field_name]" maxlength="255" type="text" id="PersonalDetailsFieldName"/>
<input class="btn btn-primary" id="editProfileSubmitBtn" type="submit" value="Update Profile"/>
<div style="display:none;">
<input type="hidden" name="data[_Token][fields]" value="a2f722badf82c0d8991ab8%3APersonalDetail.id%7Cid" id="TokenField020"/> <input type="hidden" name="data[_Token][unlocked]" value="" id="TokenUnlocked1562820470"/> </div></form>
The problem is when I submit the form and watch with Firefox's Tamper Data the form posts the data fine, but then it posts again immediately again with all the data missing.
On a working form example, I see the same behaviour, except the hidden input field is "PUT" and when the form submits, it is first a PUT with data, then the immediate second submission is with the POST with data instead of begin blank.
I assume I'm missing something basic here, but I'm really confused.
Here's the controller where PersonalForm is a database of questions passed to an element that builds the forms. PersonalDetail is supposed contain the answers but for this first time this is run the user won't have any answers.
public function editForm() {
$userId = $this->UserAuth->getUserId();
if (!empty($userId)) {
$user_account_type = $this->UserDetail->read('account_type', $userId);
$user_account_type = $user_account_type['UserDetail']['account_type'];
$this->set('user_acct_type', $user_account_type);
$this->loadModel('Usermgmt.PersonalForm');
$forms = $this->PersonalForm->find('all');
$this->set('forms', $forms);
if ($this->request->isPut() || $this->request->isPost()) {
//put in ajax verification
//$this->PersonalDetail->saveAssociated($this->request->data);
$this->Session->setFlash(__('Your answers have been successfully updated'));
$this->redirect('/dashboard');
} else {
// read user's original responses and populate form
$this->loadModel('Usermgmt.PersonalDetail');
$answers = $this->PersonalDetail->read(null, $userId);
$this->request->data = null;
if (!empty($answers)) {
$this->request->data = $answers;
}
}
} else {
$this->redirect('/dashboard');
}
}
I'm using cakephp 2.3.7 and I'm running the debugKit plugin (maybe causing more than one submission? I don't know.) Edit: Also I'm using UserAuth and Security modules.
EDIT: I oversimplified the example when I removed the hidden id fields. Now I included the two hidden input elements. However the first time this form is loaded there is no edit data so it is a create instead of add case. So I don't understand why it is posting twice and losing the data on the second post. Perhaps that is the real problem and not that it should be PUT vs POST? I'm obviously missing something fundamental in how cake is processing the post data.
Perhaps I should mention this is form is part of a plugin. Could the routing have something to do with the loss of data and the second post?
You are missing the vital part of an edit form, the id:
echo $this->Form->input('id');
Without its presence cake assumes that this is not an update (edit), but a create (add).
Also mind your casing, its not $this->Form->Submit() but $this->Form->submit().
EDIT:
At second look: I also guess that you violated more than 5 other conventions, including the most important one: Models are singular, Controllers plural. Meaning:
$this->Form->create('PersonalDetail');
If your model is PersonalDetail (which from your controller code it looks like).
This would explain why the data doesnt end up where it is supposed to.
Again my recommendation: Bake your code to see how its done.
It appears this is related to a security module problem.
I was able to prevent the double empty data posts by adding the following to the beforeFilter:
if (isset($this->Security) && ($this->RequestHandler->isAjax() || $this->action == 'editForm')) {
$this->Security->csrfCheck = false;
$this->Security->validatePost = false;
}
Now I need to research the reasons for this security problem with my form to fix it.
I'm using cakephp 2.3.0. I searched in the manual for quite awhile, but I haven't found the answer. Also, I've searched the Internet, but still haven't found what I'm looking for. SO, I'm posting my question here. Note, I'm fairly new to cakephp.
Scenario:
I have a simple form with two fields: activity and zip code.
I'm using POST on the form.
When I type in some value in those fields and submit, I echo those 'post' values/parameters and display in the browser screen. What I typed in, I can see on the screen, but the number '1' is added to the end of what I typed in the form.
Here is an example. I type in these values in the form, 'walk' and '44555'. Then I click 'Submit'. The post goes to my controller's action, which then calls my view. My view is displayed on the browser screen and I echo out those 'post' values. The results on screen are 'walk1' and '445551'.
Example #2: If I follow the steps above and don't enter any values in my form (I'll add error checking later), what I see on the browser screen is '1' and '1'.
I am unable to figure out why I am getting the value of '1' added to my form's POST values?
I'll be glad to include any other additional php code to this posting, if requested by someone trying to help.
Here is my FORM code (from my view)...I know there are DIV helpers, but I'll get to that later:
echo $this->Form->create(null, array('url' => array('controller'=>'activities', 'action'=>'results'))); ?>
<div class="box1" style="position:relative; top:10px; left:10px; float: left;">
Search here.... <br>
<hr>
<?php echo $this->Form->input('activityName', array('size'=>'30',
'label'=>'Activity Name:', 'value'=>'i.e. walking, etc.'));?>
<br>
<?php echo $this->Form->input('zip', array('size'=>'7', 'label'=>'Postal Code:')); ?>
<br>
</div>
<div class="box1" align="right">
<?php echo $this->Form->end('Go Search');?>
</div>
Here is my controller code:
<?php
class ActivitiesController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
//other code....
}
public function results() {
$this->layout = 'second';
$name = $this->request->data['Activity']['activityName'];
$pCode = $this->request->data['Activity']['zip'];
$this->set('theName', $name);
$this->set('theZip', $pCode);
$this->set('results', $this->Activity->
find('all', array('conditions' => array('name' => $name, 'postal_code' => $pCode))));
$this->set('title_for_layout', 'Results');
$this->render();
}
}
?>
My final view code. I left off some of the code...just showing the part that matters:
<div style="position:relative; top:10px; left:5px; ">
<?php echo print_r($theName); ?>
<br>
<?php echo print_r($theZip); ?>
Thanks
The 1 comes from printing the return value of print_r() which is true (i.e. 1).
In other words: you shouldn't do echo print_r(), just do print_r(). The function handles the printing by itself, you don't have to print the results manually.
(Also, print_r() is almost never the best choice to print out values except when debugging and even then CakePHP's debug() is much more suitable.)
I have a product search page with the form below. The search result is displayed on the same page with search bar at the top.
echo $this->Form->create('Searches', array('action'=>'products', 'type' => 'get', 'name' => 'textbox1'));
echo $form->input($varName1, array('label' => false));
echo $form->end('Locate');
I also have a little box next to the search result that allows (it doesn't work yet) the user to flag using checkboxes a product and accordingly update its database (table products and using model Product) with a button click. Note that I have a Searches controller for this search page.
<form method="link" action="/myapp/product/test_update_db>
<label><input type="checkbox" name="flag1" <?php echo $preCheckBox1; ?>>Flag 1</input></label>
<label><input type="checkbox" name="flag2" <?php echo $preCheckBox2; ?>>Flag 2</input></label>
<input type="submit" value="Update">
</form>
I'm having difficulty with this approach figuring out how to perform this check-box-and-DB-update routine. I'm getting to the link I'd like to go (/myapp/product/test_update_db), but I don't know how to take variables flag1 and flag2, along with row ID of this result ($results['Product']['id'])) to the new page.
Could someone guide me on how to perform this neatly? Is this general approach correct? If not, what route should I be taking? I'd prefer not to use javascript at this time, if possible.
EDIT: I think I can make this work if I use the URL for passing data.. but I'd still like to know how this could be done "under the hood" or in MVC. I feel like I'm hacking at the CakePHP platform.
UPDATE: So, I ended up using the URL parameters for retrieving information pieces like flag1 and flag2. I'm still looking for an alternative method.
To see where your is-checkbox-checked data is located, do the following in your controller:
// Cake 2.0+
debug($this->request->data);
// previous versions
debug($this->data);
If you want to pass data to your search controller from the current page, you can always add the data to your form:
$this->input
(
'Product.id',
array
(
'type' => 'hidden',
'value' => $yourProductId
)
);
I ended up using information embedded in the URL for getting submission data. Something like below..
In Products controller, when the form with flag1 and flag2 are submitted:
public function test_update_db() {
// Get variables from URL, if any, and save accordingly
$result = $this->Product->updateProduct($this->params['url'], 'url');
if ($result) {
$this->Session->setFlash('Successfully updated!', 'default', array('class' => 'success'));
$this->redirect($this->referer());
}
else {
$this->Session->setFlash('Update was unsuccessful!', 'default', array('class' => 'error'));
$this->redirect($this->referer());
}
}
This works for doing what I needed to do. I feel like there's a more proper way to do this though.
if ($result) {
$this->Session->setFlash('Successfully updated!', 'default', array('class' => 'success'));
$this->redirect($this->referer());
}