Removing 'src' attribute from output of $html->image() in CakePHP - cakephp

I am using CakePHP 1.2. I am trying to use jQuery Lazy (http://jquery.eisbehr.de/lazy/example_basic-usage) from CakePHP. Reading the documentation at https://book.cakephp.org/1.2/en/The-Manual/Core-Helpers/HTML.html#image, it shows how
<?php echo $html->image('cake_logo.png', array('alt' => 'CakePHP'))?>
produces the following output:
<img src="/img/cake_logo.png" alt="CakePHP" />
I need to produce this output:
<img class="lazy" data-src="/img/cake_logo.png" />
How can I do that using $html->image() in CakePHP 1.2? The problem is that in the syntax image(string $path, array $htmlAttributes = array()), the first parameter is mandatory and in the output it produces the src=... attribute of img. I need to have an output with <img... /> that does not contain the src=... attribute. How could I achieve that using $html->image() in CakePHP?

Via the built-in HTML helper it's not possible without modifying the tag template. So if you need lazy loading on all images, then you could for example change the image tag template to something like:
<img class="lazy" data-src="%s" %s/>
However this would clash with using the class attribute. So alternatively you could extend the HTML helper and implement a custom image() method (or an additional method). Here's a quick & dirty example, which should be pretty self-explantory:
function image($path, $options = array())
{
$defaults = array(
'class' => null
);
$options += $defaults;
$options['class'] = 'lazy ' . $options['class'];
$originalTemplate = $this->tags['image'];
$this->tags['image'] = '<img data-src="%s" %s/>';
$imageHtml = parent::image($path, $options);
$this->tags['image'] = $originalTemplate;
return $imageHtml;
}
See also
Cookbook > Core Helpers > HTML > Changing the tags output by HtmlHelper
Cookbook > Developing With CakePHP > Helpers > Creating Helpers

Related

Create links to tagged list from an array of tags

I just followed a tag tutorial (https://book.cakephp.org/3.0/en/tutorials-and-examples/cms/tags-and-users.html) on the Red Velvet Cookbook. I was successful in adding tagging to my website. Though I feel it needs a couple more things. The comma separated list of tags is just that, a list. I would prefer a list of links. The links would obviously link to a list of posts that are tagged with the same tag. This list already exists thanks to the tutorial. The url looks like http://localhost:8765/story/tagged/cats/
I have fiddled with the html helper to try and create links but I am unsure how to do this with an array. Any leads or help would be greatly appreciated.
This is the line in my template that shows the list of tags
<p><b>Tags:</b> <?= h($story->tag_string) ?></p>
This is the function that gets the tag_string
class Story extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* #var array
*/
protected $_accessible = [
'*' => false,
'tag_string' => true
];
protected function _getTagString()
{
if (isset($this->_properties['tag_string'])) {
return $this->_properties['tag_string'];
}
if (empty($this->tags)) {
return '';
}
$tags = new Collection($this->tags);
$str = $tags->reduce(function ($string, $tag) {
return $string . $tag->name . ', ';
}, '');
return trim($str, ', ');
}
}
In your $story entity you have tags property, which you already used in computed field tag_string. To get separated tags, you need to iterate over it in a template, eg:
<ul>
<?php foreach($story->tags as $tag): ?>
<li><?= $tag->title ?></li>
<?php endforeach; ?>
</ul>
Assuming you have a method in your StoriesController named tagged, which accepts one parameter: tag title, you can construct link using HtmlHelper for each tag:
<ul>
<?php foreach($story->tags as $tag): ?>
<li>
<?= $this->Html->link($tag->title, [
"controller" => "Stories",
"action" => "tagged",
$tag->title
], [
"class" => "your-tag-link-class" //second array is for properties, in case you would like to add eg class for these links to style them using css.
]) ?>
</li>
<?php endforeach; ?>
</ul>

cakephp 3.x create custom widget

I want to create widget for Cakephp formHelper.
I created a widget file named ImageWidget.php in View/Widget directory (I don't know if this is the right directory but phpstorm loads it so it seems fine)
<?php
namespace App\View\Widget;
use Cake\View\Form\ContextInterface;
use Cake\View\Widget\WidgetInterface;
class ImageWidget implements WidgetInterface
{
protected $_templates;
public function __construct($templates)
{
$this->_templates = $templates;
}
public function render(array $data, ContextInterface $context)
{
$data += [
'name' => '',
];
return $this->_templates->format('myTestTemp', [
'name' => $data['name'],
'attrs' => $this->_templates->formatAttributes($data, ['name'])
]);
}
public function secureFields(array $data)
{
return [$data['name']];
}
}
?>
But I got this error:
Cannot find template named 'myTestTemp'.
I don't know where should I put my template or what is this template at all
(is it like cakephp normal template?)
my template file is like this:
//in myTestTemp.ctp file
<p>some html for test</p>
I tried to put file in these directories and it doesn't work
src/Template
src/View
src/View/Widget
thanks
Like any other widget, your widget works with string templates, and it relies on the template being set in the form helper (respectively to be set on the \Cake\View\StringTemplate object that is being passed to the widgets constructor), like for example:
$this->Form->setTemplates([
'myTestTemp' => '<p {{attrs}}>some html for test</p>'
]);
See also
Cookbook > Views > Helpers > Form > Building a Widget Class
Cookbook > Views > Helpers > Form > Customizing the Templates FormHelper Uses

Use HtmlHelper to add attribute for html tags, CakePhp

I am working on a project with cakephp right now. And I am wondering if there is a way to add attribute for a img tag, this is in my view:
Here is my code:
echo '<img id="image">';
echo $this->Js->get('#image',
array('htmlAttributes' => array('src' => 'somesourcehere')));
Edit:
I found another way to do this without using JsHelper, but use HtmlHelper,
echo $this->Html->image('somesourcehere',array('alt' => 'CakePHP'));
But the issue is the src attribute would be url like, while I was trying to set the src as base64 data, so it would be something like this in HTML
<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
However, I can only get
<img src="/img/data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
Is there a way to get rid of the /img/part in my src ? So I can make the image show up
Update
I am too dumb, only need to do
echo '<img src="data:image/png;base64,'.$source.'">';
CakePHP Html image method produce relative or absolute src path to images.
In your case if need to use Helper, then use HtmlHelper method called tag:
<?php
echo $this->Html->tag(
'img',
null,
array(
'id' => 'image',
'src' => 'data:image/png;base64,'.$source'
)
);
?>
or just simple combine html and php:
<img src="data:image/png;base64, <?php echo $source; ?>">

CakePHP: Adding meta nofollow tag to layout from view

I want to be able to add a meta tag from a view (or controller if possible) in CakePHP
I have a page like /mycontroller/myview but when it is accessed with filters like:
/mycontroller/myview/page:2/max_price:500
Then I want to add meta no follow tags.
There is a meta method on the HtmlHelper class.
When I call it like this:
$this->Html->meta('keywords', 'test test test', array('inline'=>false));
It creates a meta tag like this:
<meta name="keywords" content="test test test" />
However, when I call it like this:
$this->Html->meta('robots', 'noindex, nofollow', array('inline'=>false));
I would naturally expect and want it to create this:
<meta name="robots" content="noindex, nofollow" />
Instead I get this though:
<link href="http://www.example.com/mycontroller/noindex, nofollow" type="application/rss+xml" rel="alternate" title="robots" />
What am I doing wrong?
From the documentation page (last line)
If you want to add a custom meta tag then the first parameter should be set to an array. To output a robots noindex tag use the following code:
echo $this->Html->meta(array('name' => 'robots', 'content' => 'noindex'));
In your case:
echo $this->Html->meta(array('name' => 'robots', 'content' => 'noindex, nofollow'),null,array('inline'=>false));
Hope this helps
Here's a tweaked version of the code from this page. I've tested it, and it does work:
<?php
echo $this->Html->meta(
array('name' => 'robots', 'content' => 'noindex, nofollow'),
null,
array('inline'=>false));
?>
Obviously you can write this in a single line -I just broke it down for ease of viewing here.
You can set variables from the view to the layout in the same way you set from controller to view using $this->set(), I would have a setup like this:
// View
if($condition) {
$this->set('nofollow', true);
}
// Layout (in <head>)
if(isset($nofollow) && $nofollow) {
echo $this->Html->meta(array('name' => 'robots', 'content' => 'noindex, nofollow'));
}
Now you have a short 1-liner to add the nofollow directive from any view file.

How to overdrive FLASH MESSAGE default of cakePHP

For $this->Session->setFlash('this is message','flash_error'); you
only need to create flash_error.ctp in the elements folder to have a different look.
But what is with $this->Session->setFlash('this is message')? How do I modify the standard layout? I don't want to modify it with css or javascript.
Laheab answer is right. But you can override it using the AppController beforeRender function. In your app/app_controller.php write this function :
function beforeRender(){
if ($this->Session->check('Message.flash')) {
$flash = $this->Session->read('Message.flash');
if ($flash['element'] == 'default') {
$flash['element'] = 'flash_error';
$this->Session->write('Message.flash', $flash);
}
}
}
It will override the 'default' flash element with 'flash_error'. Then in app/views/elements create flash_error.ctp
The HTML for flash messages is output in the flash method of the SessionHelper class. I find the easiest way to achieve what you're trying to do is to override the core SessionHelper class. To do this
Copy lib/Cake/View/Helper/SessionHelper.php to app/View/Helper/SessionHelper.php
Cake will now use the SessionHelper class in your app as opposed to it's own. Now you can update the flash method to output the HTML you want. On line 136, you'll see this:
$out = '<div id="' . $key . 'Message" class="' . $class . '">' . $message . '</div>';
As an example, if I'm using Twitter Bootstrap, I'll update this line to be:
$out = '<div class="alert fade in"><a class="close" data-dismiss="alert" href="#">×</a>' . $message . '</div>';
According to CakePHP book entry on flash():
<?= $session->flash(); ?>
in a view file outputs:
<div id='flashMessage' class='message'>My Message</div>
So there is nothing to override but the CSS for this id in cake.generic.css.
Hope I understood the question correctly. =)
You cannot override default HTML for a flash message. What I did is: created the following function in app_controller:
protected function _f($message, $url=false) {
$this->Session->setFlash($message,'message');
if($url) $this->redirect($url);
}
Created my own message.ctp template in views/elements.
Then used the _f function inc all controllers like this:
$this->_f('This is a flash message','/page_to_redirect/');
Have you tried to create a default.ctp in elements folder?
That might be what you wanted?

Resources