CakePHP - Default labels to placeholders instead - cakephp

So, in CakePHP, there is a way to turn off labels by default by putting 'label'=>false in 'inputDefaults' in the Form->create() statement.
Is there a way to, instead of removing labels altogether, to change labels into element placeholder attributes? This is equivalent to doing the 'inputDefaults'=>array('label'=>false) on the Form->create while adding a 'placeholder'=>'Placeholder' to each element... but is there a way to do it without having to add it to each element and have CakePHP do it for you?

You could run your own copy of FormHelper that contains your modifications. You can copy the version of FormHelper from lib/Cake/View/Helper/FormHelper.php and paste it into your app at app/View/Helper/FormHelper.php and make the required modifications to your copy. The copy in your app folder takes precedence over the one provided in the core. As always, never ever ever make modifications to files in Core.
Alternatively, you could extend FormHelper into your own Helper class:
class MyFormHelper extends FormHelper {
...
}
Don't forget to add 'MyForm' into your $helpers array!
At any rate, what you're asking is not currently possible using Cake 2.x. Without any changes, you'll need to add a 'placeholder' => '...' in the options array of each input() call. If you make this change, please consider contributing it back to the CakePHP community so others can benefit from your work!

Related

Trigger Rule with Filefield 'when field has changed' in Drupal 7

I've got a set of different rules that check if various field types have been updated 'after updating existing content'. The problem is that each one works fine, except for the only filefield type which will not work. The condition used is a 'NOT Data comparison' on the field checking the 'node-unchanged' version against the new 'node' version. This works with every other type of field and actions appropriately (that I have used at least), just not the filefield type; the rule just fires regardless of changes or not on the filefield.
I also found this post about a very similar problem: https://www.drupal.org/node/1011014#comment-10040082
I think I have the makings of a workaround, but I just wanted to check this with some fellow developers first as my PHP isn't the best.
If I were to enable the PHP module then add a condition in rules that checks the 'source' attribute to see if a new file has been added... would this work? The code I have is:
if (isset($object->field_FILEFIELD_NAME[0]['source'])) { //Check for new files }
I believe that $object is the node passed on by rule function as argument.
Is this a good idea/best approach? Any ideas or workarounds would be great.
Yes, you can use PHP for filefield checks as it is more clear (but always less secure). Here are my suggestions:
Create a Rule component (of type "Condition set (AND)") instead of a rule to do this check.
Use a parameter with your rule component (of type Node) so you have the $node available.
Use php to do the checks. Get the file data from the filefield using $node.
Create a normal rule (eg with event Before Saving Content) where you will use this component as a condition among others.
As you said you need to check for differences not for empty values, right? So instead of using isset you need to see if there is a different fid (which normally changes when there is a different file). Other methods are available and if you want to see which data can change do a dpm() to the filefield using devel module.
In order to get the unchanged value of the filefield use the same component on you main Rule but with the $unchanged node as parameter.

Replacement for AppModel in Cakephp3

I would like to implement an autoslug-function for two models in CakePHP3 and use the beforeSave-callback for that which works fine. However the slug structure is a bit different than in Inflector::slug, so I wrote a small function for the different structure which finally leads to my question
In Cake2 I would have placed this helper function in AppModel which is not existing anymore. What's the best way to do that now? A behaviour (which seems a bit biggish for 2 lines of code) or class AppTable extends Table or ..?
Make it a behavior and use it where needed instead of putting it in a super model class. If you put that into a plugin and repository you can simply add your plugin as package via composer for every app that needs this plugin.

Best configuration and parameters for ctags in a CakePHP project

What is the best configuration and parameters for ctags in a CakePHP project?
I want to be able to auto-complete ctp files, Components, Behaviours, Models and Helpers?
Check these github repositories, I have found then and they are so good for work with php and cakephp
https://github.com/amix/vimrc
https://github.com/ndreynolds/vim-cakephp
This solution requires 1 line in your .ctags file and two lines in your .vimrc file, so it's fairly minimal.
tl;dr
.ctags:
--langmap=php:+.ctp
.vimrc:
# Controller -> Component
map <leader>t yiw<cr>:tag /^<C-R>"<CR>
# View -> Helper
map <leader>h yiw<cr>:tag /^<C-R>"Helper<CR>
Add Views to your tags
This solution is mostly for jumping between files. I'll try and add auto-completion at a later date.
Add this to your ~/.ctags options file to include CakePHP views as PHP files:
--langmap=php:+.ctp
Then I'm assuming you've done ctags -R . at the root of your project (that's what I've done at least). This out of the box should pick up PHP syntax and class definitions.
Auto-completion (general)
I found the auto-completion (omni-completion from Ctrl+XCtrl+O) doesn't work very nicely with PHP, e.g. if I type $this-> and then try to auto-complete it doesn't find any tags.
The fix for this was to use install phpcomplete.vim. This will find methods within your class.
However that won't auto-complete connected models.
Models
By default ctags should work for all Controller -> Model jumping as the Model name is the same as the class name.
Behaviors
These again should be fine as you don't specify the name of the behavior you just have the method name which depending on how independent the name is it should get found - or at least it will be in the list of tags.
Components
There's no direct way of mapping these, I couldn't see a way of mapping them through the ctags --regex options. ctags recognises that they are classes but doesn't know the xxx -> xxxComponent mapping.
However there is one slight trick. You can do a tag search on the beginning of the class name (source)
:tag /^Email
will find
class EmailComponent
You can then map this in your .vimrc
map <leader>t yiw<cr>:tag /^<C-R>"<CR>
This copies the word that you've got the cursor over and then pastes it into the tag command and executes it. My leader is set to ,, so I can type ,t and it takes me to the corresponding component under the cursor.
Helpers
Ok, another slight hack in the .vimrc file:
map <leader>h yiw<cr>:tag /^<C-R>"Helper<CR>
Using ,h, this will jump you from $html->... to
class HtmlHelper extends AppHelper {
But it doesn't work for functions inside e.g. if your cursor is over script in $html->script, it will not take you to the HtmlHelper script method. So it's a work in progress.

Drupal: D7 rewriting values returned by views

I have a requirement to perform an indexed search across content which must include a couple of tags in the result. The tags must be a random selection. The platform is Drupal 7.12
I have created a view that manages the results of a SOLR search through the search_api. The view returns the required content and seems to work as intended. I have included a couple of Global: custom text fields as placeholders for the tag entries.
I am now looking for a solution to manage the requirement to randomise the tag values. The randomisation is not the issue, the issue is how to include the random values into the view result.
My current approach is to write a views_pre_render hook to intercept the placeholders which appear as fields ([nothing] and [nothing_1]). The test code looks like the following
function MODULE_views_pre_render( &$view )
{
$view_display = $view->display['default'];
$display_option = $view_display->display_options;
$fields = $display_option['fields'];
foreach( $view->result as $result )
{
$fields['nothing']['alter']['text'] = sprintf("test %d", rand(1,9));
}
}
I am currently not seeing any change in the placeholder when the view is rendered.
Any pointers to approach, alternate solutions etc would be gratefully received as this is consuming a lot of scarce time at the moment. Calling print_r( $view ) from within the hook dumps over 46M into a log file for a result set of 2 items.
There are two possible solutions for your task.
First approach is do everything on the template level. Define a template for the view field you want to randomize. In advanced settings of your display go to Theme: Information. Make sure that the proper theme is selected and find the template suggestions for your field. They are listed starting from most general to the most specific and you can choose whatever suits you better.
I guess the most specific template suggestion for your field would be something like this: views-view-field--[YOR VIEW NAME]--[YOUR DISPLAY NAME]--nothing.tpl.php. Create the file with that name in the theme templates directory and in this template you can render what ever you want.
By default this template has only one line:
print $output;
you can change this to:
print sprintf("test %d", rand(1,9));
or to anything else, whatsoever :)
Second approach is to go with Views PHP module. WIth this module you can add a custom PHP field in which you can do whatever you want. Even though the module hasn't been released it seems to work quite well for the most of the tasks and most certainly for such a simple task as randomizing numbers it will work out for sure.
I stumbled upon this while searching for another issue and thought I would contribute.
Instead of adding another module or modifying a template, just add a views "sort criteria" of "Global: Random".

CakePHP $this->element correct usage?

I'm trying to make a reusable component (a weekday dropdown box, simple as pie) and am following the advice in http://book.cakephp.org/view/1081/Elements.
According to that page, I should make a blah.ctp file in app/views/elements, and it will be magically accessible in my view code as $this->element('blah').
So I did it. I'm passing the form and field name to my element in the view code:
$this->element(
'weekday_input',
array('form'=>$this->Form, 'fieldname'=>'weekday')
);
Earlier I created a form using $this->Form->create, so I figured I need to pass it to the element explicitly.
And my element code, in weekday_input.ctp:
echo $form->input(
$fieldname,
array(
'options',
array('Sunday'=>'Sunday',...,'Saturday'=>'Saturday')
)
);
(Weekdays in between omitted for brevity.)
Am I using $this->element properly? Is there something more clean available?
You don't have to pass the Form object. Form, Html and other helpers are available in elements (just as in view). Whether or not you want to pass fieldname depends: Do you need to change it?
An element is a bit too simple I expect. Also it is not very testable. Would focus on Helpers, which is a more advanced way of developing this. But there is another solution I would prefer even more:
For this kind of issues it might be more appropriate to extend the formhelper itself. You can see a simple example here:
http://blog.nlware.com/2012/02/07/cakephp-2-0-how-to-extend-the-formhelper/
A full example can be found for example here:
https://github.com/slywalker/cakephp-plugin-boost_cake/blob/master/View/Helper/BoostCakeFormHelper.php
As you asked for a clean solution think about creating a plugin (or check out existing plugins). That will separate the code out of your project more clean. And it will be available for re-use without much issues.
you can find all files needed for a plugin in the same project:
https://github.com/slywalker/cakephp-plugin-boost_cake
And the documentation here:
http://book.cakephp.org/2.0/en/plugins.html

Resources