Can someone explain why this is useful if you can never use the HtmlHelper to close a tag?
// No text specified.
<?php
echo $this->Html->tag('span', null, array('class' => 'welcome'));
?>
// Output
<span class="welcome">
In an ideal world there would be some way to create a closing tag, such as </span>
Well, the "usefulness" depends on how it's been used.
First, there's no HtmlHelper->closeTag function, because the tag function surrounds the string (or element) that's inside. Example
echo $this->Html->tag('span', "i'm a span", array('class' => 'welcome'));
// Output
<span class="welcome">i'm a span</span>
There's really no point on having a closeTag function if the HtmlHelper opens and closes tags inside the function.
Clearly an unclosed <span> tag isn't that useful either, and that example isn't the best one to show some use (I know it's in the cake docs, not blaming you).
Since HTML isn't XML, then there are cases where unclosed tags may appear (check the HTML specs). In that link is a list of what is defined as void elements, which are:
area, base, br, col, command, embed, hr, img, input, keygen, link, meta, param, source, track, wbr
Little ways down that link reference, it is written
Void elements only have a start tag; end tags must not be specified for void elements.
Soooo.... you may want to do that. You can write <br> with a complicated and more character-count expensive command. Maybe you want to write the whole .cpt view in php and no echos of normal strings, just pure php with the advantages of HtmlHelper (like escaping html characters).
So, in theory, you can do
echo $this->Html->tag('br', null, array());
echo $this->Html->tag('link', null, array());
and that would be valid tags. Why would you do that? * shrug * Who knows. But isn't it nice you have the option?
Also, HtmlHelper probably uses that function internaly to write other tags. I mean, maybe HtmlHelper->img() uses HtmlHelper->tag('img', null), and since the tag function is public, well, you get that seemingly useless option as well.
I know it doesn't sound as much "usefulness" still, but it's the little things that count...
Related
Example:
.. member:: CK_UTF8CHAR model[16]
Gives me both the type and the name bolded and hyperlink not working.
Practically we are forced to use this cases like that:
.. member:: model
Because otherwise it would be incorrect (use it without array and with the same type).
Well, this seems to be a real bug in Sphinx. I reported that and it was confirmed. I've come up with a little workaround for now, but it's more of a crutch. Just put the following to the layout.html file of your Sphinx theme:
<script>
$('dl.member dt').each(function() {
$(this).find('big:first').text('[')
$(this).find('big:last').text(']')
});
</script>
Now you may use parenthesis instead of brackets in broken structures: model(16) becomes model[16] (and label(\ ) becomes label[], but only within the .. member:: directive.
I know it is not a very elegant solution, but it is OK as a temporary fix, until the bug gets resolved.
Finally, a simple, straight-answer question :D
Background: My company has changed the way that that they handle when certain sites are used. Previously, certain sites were only delivered to on certain weeks; now, every site delivers every week. They have asked me to get rid of the weeks field on their "add new site" form. The link between week and site is still necessary for the code to work, however, so I am trying to hide the field and populate it with every single week.
Auto-populating it is simple. I just do this:
echo $this->Form->input('Week', array('value'=>array('1','2','3','4','5')));
And when I debug the data getting sent from the form, I get the following, which is exactly the way I want it to work.
'Week' => array(
'Week' => array(
(int) 0 => '1',
(int) 1 => '2',
(int) 2 => '3',
(int) 3 => '4',
(int) 4 => '5'
)
So the next step is simply hide that input. Easy, right? I just do one of the following two things to the form:
echo $this->Form->hidden('Week', array('value'=>array('1','2','3','4','5')));
or
echo $this->Form->input('Week', array('value'=>array('1','2','3','4','5'), 'type'=>'hidden'));
All I have done is change the type to hidden. But now, the data returned from debugging the data from the form looks like this:
'Week' => array(
'Week' => '1 2 3 4 5'
So my question is, what is the difference in the way data is handled between a normal "input" field and a "hidden" field. Why does that difference occur, and why is it important? And for this particular issue, how do I get hidden data to behave in the same way as normal input data?
As you said in the comments, Week is a multiple choice input, so that's why the difference in value handling. If the input is something that allows multiple choice (like multiple select or checkboxes), then it's logical all values comes as an array. But the hidden type is basically a hidden text input (ok, maybe not, but I'm simplifying). Look, if you put
echo $this->Form->input('Week', array('type'=>'text', 'value'=>array('1','2','3','4','5')));
you'll get the same string as you have with the input field, so it isn't a matter of if it's hidden or not.
Now, for your case, you can add the week values as an string and change the way you handle the value on post, as a string instead of an array.
But, if by some reason that's not a possibility (too much code to change, etc), then keep the same code you have now, and hide it with css. Something like
echo $this->Form->input('Week', array('value'=>array('1','2','3','4','5'),
'div'=>array('style'=>'display:none')));
should do the trick (maybe a few more styles needs to be added, try with just that first).
I don't like the css solution that much, browsers can interpret css different ways and etc etc... But it fits your needs and you don't have to change anything else.
EDIT
On second though, it is possible to achieve the same array output with just hidden fields. It isn't pretty though. You have to change the name of every input to tell php it's an array, like this
echo $this->Form->input('Week1', array('type'=>'hidden', 'value'=>1, 'name'=>'data[Week][Week][]'));
echo $this->Form->input('Week2', array('type'=>'hidden', 'value'=>3, 'name'=>'data[Week][Week][]'));
echo $this->Form->input('Week3', array('type'=>'hidden', 'value'=>4, 'name'=>'data[Week][Week][]'));
The important part is the name option for every input, see the array reference? Specially the last empty []. This is actually how cakephp sends all data as an array. Have you tried to create a form without the FormHelper in cake? You wouldn't get the post data in $this->request->data['form_name'] unless you set the input names for all your form fields.
Cake sends all post data inside the $data array by naming all the inputs with <input name="data[ModelName][field_name]" and for multiple inputs is <input name="data[ModelName][field_name][]" (with the empty array at the end, so it gets numerically indexed). You can see that using any html inspector on any other form created with the formhelper in cake.
I hope it's clear... I'll stick with the css solution here. The multiple hidden inputs seems messier.
I noticed there is a bug in Croogo's NodesController::search() when searching for words with some non-ascii chars on them e.g. 'üäö'. If I search for example for 'Steuergeräte' (german) I get no results, even though I should. If I search for 'Steuergerate' (which would be misspelled in german) I get the desired results. Which is totally weird.
A direct query on the db I works fine:
"SELECT * FROM i18n WHERE content LIKE '%Steuergeräte%';"
Which returns the expected records.
But it's not a general problem with unicode-chars, as for example, searching for a japanese word worked as expected. So this only affect some chars.
Cakephp: 2.4.0, Croogo: 1.4.5
Ok, I found the cause of the problem.
On the search-view, the string to be searched for is cleaned with:
$q = Sanitize::clean($this->request->params['named']['q']);
Which among other things runs html_entities on the string as default, when 'encode' => true is set (default). This would turn e.g. ö into ö and then search for words with html-entities on them.
I got a workaround by doing:
$q = $this->request->params['named']['q'];
// Use encode=false on Sanitize::clean to prevent äüöß etc. getting
// replaced by html entities. And strip tags manually first to prevent
// html injected strings.
$q = strip_tags($q);
$q = Sanitize::clean($q, array('encode' => false));
Note: If like in my case, TinyMCE is set with 'entity_encoding' => 'raw' then the body field in the nodes table would contain äöü instead of htmlentities as well, which IMO is a far better practice as replacing them with htmlentities. Per default though, tinymce replaces chars with htmlentities, so the body field would work with the default search behaviour of Croogo/Cakephp. But searching, for example, in the title-field wouldn't.
Update
Ok, as mark comments suggested, sanitizing and using cake's paginate method, is not necessary, so the Sanitize part can be skipped. I also found using htmlspecialchars even better as strip_tags, as strip_tags wouldn't take care of e.g. '&', and on the body, tinyMCE saves those as html_entities. So the updated code would look like this:
$q = htmlspecialchars($this->request->params['named']['q']);
// go on with searching for nodes on paginate-method
Best solution for timing the page load from as early as possible in the app process, and displaying in the layout footer, without modifying Cake source?
Edited solution. Credit to Everton Yoshitani.
// app/Layouts/default.ctp
echo round(microtime(true) - TIME_START, 3);
Nothing wrong with your code, but if you wanted even more accurate, use a constant inAPP/webroot/index.php right at the top:
<?php
// set a constant for use in app/view/layout/default.ctp
define('MTIME', microtime(true));
/**
* PHP 5
*
and layout:
// see app/webroot/index.php for constant declaration
echo round(microtime(true) - MTIME, 3);
as this file is the very first one accessed (assuming using .htaccess). This relies on you using a constant in an unexpected place.
bootstrap.php is generally the place to put code like this, but a simple comment in your webroot/index.php explaining why the constant is there would clarify any confusion for anyone reading your code.
In these days I thought on how to work better with AppHelpers in CakePHP. I thought to use the AppHelper to make links and other html elements consistent depending by the context i need, for example, for users I have the method
$this->AppUser->profile($data, $options, $attributes);
this method returns a link styled for the users, with a specific css classes, maybe something line this:
<a class="user female" href="http://url/profiles/username">Username</a>
My problem is the data is structured differently by the situation, in some case I have an array like this:
$data['User']['id']
$data['User']['username']
$data['Profile']['user_id']
$data['Profile']['sex']
$data['Profile']['other']
And in some other cases, with different queries and different entities I have this:
$data['User']['id']
$data['User']['username']
$data['User']['Profile']['user_id']
$data['User']['Profile']['sex']
$data['User']['Profile']['other']
So I would like to understand if I missing something in the data hierarchy because it should be always structured in the same way?
And so should I to send data to the Helper always structured in the same way?
Should I let the helper parse the data depending by the situation, so with conditions to find where the data is?
That's pretty common, and is a result of finding related items multiple levels deep. I usually have a helper method on the Helper that normalizes the data.
I would always send the data to the helper as-is, and then restructure it as needed within the helper. It would look something like this:
function normalizeUserData($data) {
foreach ($data['User'] as $field => $value) {
if (is_array($value)) {
// move it to the same level as User
$data[$field] = $value;
unset($data['User'][$field]);
}
}
}
Now your functions can always expect the Profile data on the same level as the User key. This function isn't perfect and isn't recursive, but should give you a good start.