I wish to add a version number to my css file but I don't see a way to do it with the html helper.
I see one example of adding a timestamp through the bootstrap.php but I want to be able to control the version number myself.
I am using cakephp 2.3
style.min.css?v=1
<?php
echo $this->Html->css('style.min', array('v'=>'1'));
echo $this->fetch('css');
?>
or
<?php
echo $this->Html->css('style.min?v=1');
echo $this->fetch('css');
?>
Just add the .css
echo $this->Html->css('style.min.css?v=1');
Although it's standard practice to omit the .css, it's acceptable to include it, and will allow you to add additional parameters to the end of the URL.
In CakePHP 3x you can do this in config/app.php.
/**
* Apply timestamps with the last modified time to static assets (js, css, images).
* Will append a querystring parameter containing the time the file was modified.
* This is useful for busting browser caches.
*
* Set to true to apply timestamps when debug is true. Set to 'force' to always
* enable timestamping regardless of debug value.
*/
'Asset' => [
// 'timestamp' => true,
],
Related
At first - I'm new to the Yii Framework. I did some research on my own but I couldn't find a precise solution to my issue.
Assume there are two related models - Product and Image. A single Product may have multiple Images assigned. What is the best approach at creating the create / update forms that would be able to manage this kind of scheme?
The Image model consists of various fields, along with a path to the image file, so it's not just a "container" for the path itself. What's more - I need to have a thumbnail generated for every uploaded image and its path stored within the same model.
What I need to achieve is pretty much similar to the admin inline functionality known from Django - there should be a section in the Product create / update form which would allow users to add / modify / delete Images.
I tried the multimodelform extension but I couldn't get file uploading to work. What's the best way of getting it done and not having to build the whole file-upload-enabled-multiple-model-form structure manually?
The detailed solution depends on if you are using CActiveForm or CHtml form. Since you have 2 related models I assume you are using CActiveForm and will point out some thing you need to keep in mind.
For this example i am gonna assume some definitions
Product with fields id, name
Product with ONE to MANY relation to 'images' on ProductImage
ProductImage with fields id, productId, path
I also assume there gonna be 1 upload / edit, but multi delete
Here's the view:
$form = $this->beginWidget(
'CActiveForm',
array(
'id' => 'upload-form',
'enableAjaxValidation' => false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)
);
echo $form->labelEx($product, 'name');
echo $form->fileField($product, 'name');
echo $form->error($product, 'name');
echo $form->checkBoxList($product, 'path', $product->images);
echo $form->labelEx($productImage, 'path');
echo $form->fileField($productImage, 'path');
echo $form->error($productImage, 'path');
$this->endWidget();
And your action
public function actionUpdate($productId) {
$product = Product::model()->findByPk($productId)->with('images');
$productImage = new ProductImage();
if(isset($_POST['Item']))
{
$product->attributes=$_POST['Product'];
foreach($product->images as $im) {
if(in_array($im->path, $_POST['Item']['Image']))
$im->delete();
}
$productImage->image=CUploadedFile::getInstance($productImage,'path');
if($productImage->save())
{
$productImage->image->saveAs('some/new/path');
// redirect to success page
}
}
$this->render('update', array(
'product'=>$product,
'productImage'=>$productImage,
));
}
Now note that this solution is not tested so there will be bugs, but it should give you an idea on how to write your own form.
Resources:
http://www.yiiframework.com/wiki/2/how-to-upload-a-file-using-a-model/
http://www.yiiframework.com/wiki/384/creating-and-updating-model-and-its-related-models-in-one-form-inc-image
I seem to be beaten at the very first hurdle on this one, I can't seem to get a basic "Hello world" going on in cake PHP.
in /app/Controller/MyController.php I have:
public $helpers = array('Js' => array('Jquery'), 'Html', 'Form');
public $components = array('RequestHandler');
in /app/View/Layouts/default.ctp I have:
echo $this->Html->script('//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js');
echo $this->fetch('script');
echo $this->Js->writeBuffer();
?></head>
in /app/View/My/index.ctp I have:
$this->Js->alert('HelloWorld');
but I get no alerts! If I try:
echo $this->Js->alert('HelloWorld');
it prints out to the browser: (double quotes instead of the typed single quotes!?)
alert("HelloWorld");
but not wrapped in < script > tags or even a $(document).ready(function(){});
Have I missed something out?
JsHelper is pretty useless to be honest. I don't even bother with it properly, I just include JavaScript in my site as I would normally, but using Cake's methods to keep it within the framework.
Example layout would have jQuery included in the <head> like this:
app/View/Layouts/default.ctp
<head>
<?php
// Include jQuery
echo $this->Html->script('jquery-1.8.2.min');
// Want to send some glabal values to your scripts?
$this->Js->set(array(
'TEST' => 'Hello World',
'ROOT' => $this->Html->url( '/', true)
));
echo $this->Js->writeBuffer(array('onDomReady' => false));
// Include any other scripts you've set
echo $this->fetch('script');
?>
</head>
Then in your view, you might want to include a specific script for that page:
app/View/Pages/test.ctp
<?php echo $this->Html->script('test.js'); ?>
And you just keep all your JavaScript as usual in an external script:
app/webroot/js/test.js
$(document).ready(function() {
/**
* Alert the value we set in our layout. All JS vars that have been
* set are available in your JavaScript via the window.app object.
*/
alert(window.app.TEST + ' sent from ' + window.app.ROOT);
});
The general consensus is don't bother using the JsHelper, and is likely being removed in Cake 3 in any case.
I would put echo $this->Js->writeBuffer(); before </body>
I am not sure on the exact workings but I think your JS is working with echo because it is being output in the middle of your view, so when the page loads, it alerts. (The JS will be in the middle of your HTML output) rather than in the <head> or before </body>
The writeBuffer is being called before the view file is processed; so your view js does not get added to the buffer. I could be incorrect however.
Set the write buffer at the end of each ctp file and it should work
My Goal:
Reuse of a contact form to be related to several different entities I call "Parents" ie Group has contact information, Member has contact info etc....
The way I tried doing it was:
1. Creating a view file for contact, named "form.ctp" which doesn`t create a new form, nor submits, just echo's the contact's fields.
2. Calling this file using requestAction
My Problem:
The form's _Token get crumbled.
Parent add.ctp example
<?php echo $this->Form->create('Group');?>
<fieldset>
echo $this->Form->input($field_prefix.'contact_id',array('type'=>'hidden'));
<?php echo $this->requestAction(array('controller' => 'contacts', 'action' => 'form'), array('named' => array('index'=>'0','parent'=>'Group',
'fields'=>array(
'email'=>array('value'=>'xx#yy.com','hidden'=>1)
))));
inside the form.ctp I have:
//Associated Model
echo $this->Form->input('Contact.0.city',array('type'=>'hidden'));
echo $this->Form->input('Contact.0.postcode');
echo $this->Form->input('Contact.0.phone');
echo $this->Form->input('Contact.0.cellphone');
echo $this->Form->input('Contact.0.email',array('value'=>""));
echo $this->Form->input('Contact.0.id',array('type'=>'hidden'));
?>
Looking at the HTML source code that is generated, I see that whether I use the request action or just copy the contect of the form.ctp into the "Parent's" add file, I get the same HTML result.
HOWEVER!!! when I use the form.ctp Action Request, I get the blackhole, the tokens are being messed up!!!
Any Ideas?
Thanks in advance
Orly
If your problem is solely reusing a form, you can use the form as a Element, and then you could call it multiple times, substituting in the exact values you need.
As for SecurityComponent, I would recommend (at least as a temporary fix) disabling SecurityComponent for that specific action by using $this->Security->unlockedActions(); in your controller's beforeFilter()
I can do this in any of my View file in Cake PHP:
<?php echo $this->Html->script('myjs.js', false); ?>
but if I do the same thing in my default view (default.ctp) then the JS files don't load i.e. they don't get echoed. I have tried moving includes above and below <?php echo $scripts_for_layout ?> in the default view but they still don't get printed:
<?php echo $scripts_for_layout ?>
<?php echo $this->Html->script('myjs.js'); ?>
<?php echo $this->Html->script('myjs.js'); ?>
<?php echo $scripts_for_layout ?>
Any ideas?
Thank you :).
with or without an extension - this is not the reason why the script do not get echoed,
as mensch mentioned before it makes no difference because of:
source of html helper cakephp 2
if (strpos($url, '?') === false && substr($url, -3) !== '.js') {
$url .= '.js';
}
the reason is:
you have already inserted this script inside your view,
cake checks if the script is already inserted on the page
options - 'once' - Whether or not the script should be checked for uniqueness. If true scripts will only be included once, use false to allow
the same script to be included more than once per request.
by default the value of once is set to TRUE
remove the script from your view first and then try it with or without '.js'
P.S.: why the petervaz answer has worked for you:
because this check:
if ($options['once'] && isset($this->__includedScripts[$url])) {
return null;
}
made before check for file extension
so isset(__includedScripts['myjs']) == false // because first key was __includedScripts['myjs.js']
and you've got your script included
I have a project with scripts added just before $scripts_for_layout and they are displayed fine. The only difference is that I'm not adding the extension .js to the call, like this:
default.ctp:
<head>
<?php echo $this->Html->charset(); ?>
<title>
<?php echo "Site > $title_for_layout"; ?>
</title>
<?php
echo $this->Html->script('jquery-1.6.4');
echo $this->Html->script('jquery-ui-1.8.16.custom.min');
echo $this->Html->script('mercado');
echo $scripts_for_layout;
?>
</head>
Another thing I'd DEFINITELY recommend is to check that loading your JS in a view is 100% OK with everything.
Do NOT use $this->Html->script if you are unsure about:
--- the dependency of scripts on each other
--- the dependency of some plugins on other scripts
--- how many different layouts and/or views you want to use in the future.
For example, some plugins use jQuery but they require jQuery to be loaded BEFORE the plugin itself.
So if you put jQuery in a view or layout, the plugin's JS loads before jQuery and plugin may not work. If you want to make sure some script loads first, you can try this:
in your app/View/Helper/AppHelper.php:
class AppHelper extends Helper {
public $helpers = array('Html', 'Session');
public function beforeRender($viewFile){
echo $this->Html->script('jquery', array('inline'=>false));
}
}
Therefore you don't have to include jQuery in multiple views and it loads first.
$scripts_for_layout in a layout is a placeholder for all the scripts included in views, so if you include it or don't won't have any effect if you load scripts directly in the default.ctp.
That being said, adding the extension or leaving it out of the $this->Html->script() call shouldn't make a difference. What could be the case is that the HtmlHelper isn't called correctly (it's called by default in Cake 2.0), but you should be receiving error messages. Is debug set to 2 in /app/Config/core.php?
How can I change the extension for CakePHP Views from .ctp to .php
I have seen there is this line in /cake/libs/view.php var $ext = '.ctp'; that sets the extension but how can I do it from my /app/ folder so it doesn't effect Cake core files.
Thanks
You can set the extension in your AppController with
public $ext = '.yourext';
This is is reply to Cameron's comment regarding the issue of using multiple extensions in light of the fact cakephp does not allow you to specify multiple extensions.
I am using Mustache for a single site that uses merb, rails2, rails3 and cakephp for different sections of the site. The cake site "receives" mustache files for common layout elements but these templates have a '.mustache' file extension which my cake site will not recognize. My workaround is basically what dhofstet suggests just framed in the context of your specific usecase. In short, create a wrapper that might look something like this:
<?
$tmp = $this->ext;
$this->ext = '.mustache';
?>
<?= $m->render($this->renderElement('moznav/advanced_header'), array('foo' => $bar)) ?><br />
<? $this->ext = $tmp; ?>
When flow returns to the caller, you keep on using your native file extension.
How can I change the extension for CakePHP Views from .ctp to .php
I have seen there is this line in /cake/libs/view.php var $ext =
'.ctp'; that sets the extension but how can I do it from my /app/
folder so it doesn't effect Cake core files.
example:
you have view posts/add.ctp
now you rename add.ctp into add.php
and then you run .../posts/add the message error show:
Error: The view for PostsController::add() was not found.
to your app can understand extention .php, you add line public $ext = '.php' in PostsController.php
now, you run again ..posts/add => okie, cakephp understand extention .php
Notice: if you use atrribute $ext = '.php' but file view named .ctp, cakephp extention .ctp will use by default
I found this post because I had the same problem. This is not mentioned in the Predominant TwigView plugin documentation on Github. I'm tired of those documentations that explains only half of things and with which we have to guess the second half. This is a big waste of time that slows down projects pointlessly.