Using css variables with php in joomla 3 template - php

My idea is to use template parameter in joomla to set the color for a background, text or buttons.
I want to define a css class instead of each time using style="background-color:<?php echo $buttoncolor ?>;" as I don't want to write countless template overrides.
I believe that could be very usefull feature.
The parameter in my templateDetails.xml looks like
<field name="buttoncolor" type="color" default="#309000"
label="TPL_BUTTON_COLOR_LABEL"
description="TPL_BUTTON_COLOR_DESC" />
The idea how to use php variable in css I found on CSS-Tricks
To use a php variable within a css I linked to this file in my index.php
<link rel="stylesheet" href="<?php echo $this->baseurl ?>/templates/<?php echo $this->template; ?>/css/style.php" type="text/css" />
My style.php looks like:
<?php
header("Content-type: text/css; charset: UTF-8");
$buttoncolor = $this->params->get("buttoncolor");
?>
.buttoncolor {background-color: <?php echo $this->params->get('buttoncolor'); ?>;}
Usally I set a variable to a template parameter in the index.php like
<?php
//parameter
$app = JFactory::getApplication();
$doc = JFactory::getDocument();
$params = $app->getParams();
$buttoncolor = $this->params->get('buttoncolor');
?>
Unfortunately I got the following error:
Fatal error: Using $this when not in object context in style.php
Any ideas, workaround and help is highly appreciated!

Please try to remove $this. Your code has to be:
$app = JFactory::getApplication();
$template = $app->getTemplate(true);
$params = $template->params;
$buttoncolor = $params->get("buttoncolor");
Joomla has a specific way to set css style. You have to do it like:
$document = JFactory::getDocument();
$style = ".buttoncolor {background-color: ".$buttoncolor."}";
$document->addStyleDeclaration($style);
Good Luck!

Related

How to include a PHP object in CSS?

When using an external stylesheet, is it possible to use a PHP object within CSS - without creating another object?
I have found workarounds with internal and inline CSS (e.g. How to include PHP code in CSS?) Below is some minimal code to show the problem and the workarounds I have found thus far.
in MyClass.php:
class MyClass{
public $color = "blue";
}
in PHP/HTML file:
<?php
include_once('MyClass.php');
$myClass = new MyClass();
?>
... (in head - internal CSS workaround):
<style type="text/css">
h1{color: <?php echo $myClass->color;?>;}
</style>
... (in head - external CSS workaround):
<link rel="stylesheet" href="external.css") />
... (in body):
<h1> 1. Internal </h1>
<h2 style="color:<?php echo $myClass->color;?>"> 2. Inline </h2>
<h3> 3. External </h3>
In external.css [here is the "problem" - I need to create a new object]:
<?php
header('Content-type: text/css');
include('myClass.php');
$myClass = new MyClass(); //<--ANOTHER OBJECT
?>
h3 {
color: <?=$myClass->color?>;
}

Manually rendering Zend_View with layout enabled

I'm creating a mail service within my application that has the body of the email stored in the database prior to sending it out to recipients.
Each mail body is a partial view script that has the necessary parameters injected into it via Zend_View.
What I want to do is create a 'mail' layout that can wrap around each of these partials,
but I can only seem to get either the layout content or the view content; not both at once.
What I've got
$scriptPath = 'test_mail';
$view = Zend_Controller_Front::getInstance()->getParam('bootstrap')->getResource('view');
$view->setScriptPath(APPLICATION_PATH . '/modules/mail/views/scripts/partials/');
$view->layout()->setLayout('mail');
var_dump($view->layout()->render($scriptPath));
However, all I receive is the view script content.
My layout is looking something like this:
<table class="mail">
<!-- Snip -->
<?php echo $this->layout()->content; ?>
<!-- Snip -->
</table>
I know this is possible. I don't want to do:
$layout->content = $view->render($scriptPath);
I assume I'm going the wrong way about this. Is it that I need/ don't have the layout controller plugin registered and somehow need to trigger this to get the output?
I suppose I could just create a custom layout class and take care of the rendering myself but wanted to see what others said first.
Any tips? Thanks!
I am using email layout, multiple view templates for different kinds of emails and extended Zend_Mail class for setting desirable body:
class MyMail extends Zend_Mail
{
public function setBodyView($script, $params = array())
{
$layout = new Zend_Layout(array('layoutPath' => APPLICATION_PATH . '/layouts/scripts'));
$layout->setLayout('email'); // Your email layout
$view = new Zend_View();
$view->setScriptPath(APPLICATION_PATH . PATH_TO_MAIL_TEMPLATES);
foreach ($params as $key => $value) {
$view->assign($key, $value);
}
$layout->content = $view->render($script . '.phtml');
$html = $layout->render();
$this->setBodyHtml($html);
}
}
I using %mail_body% pattern in my mail template.
$layout = Zend_Layout::getMvcInstance();
$view = $layout->getView();
$mail_template = $view->render('template.phtml');
$returnYourReadyTemplate = str_replace('%mail_body%', $mail_body, $mail_template);
in template.phtml :
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body >
<div style="margin:30px 20px 10px 20px">
%mail_body%
</div>
</body>
</html>
Hope this helps you!

how and where to include js and css for modules?

I have modules for category:
+modules/
+category/
+assets/
+css/
+js/
+images/
+components/
+controllers/
+models/
+views/
-CategoryModule.php
What is the best way to includes the css and jss to all views?
Publish and register in CategoryModule init method - this will make available your css and js in category module.
Something like this:
public function init() {
$path = $this->assetManager->publish(Yii::getPathOfAlias('application.modules.category.assets'));
$this->clientScript->registerCssFile($path . '/css/some-css.css', 'screen, projection');
$this->clientScript->registerScriptFile($path . '/js/some-js.js');
}
create module layout file under views/layout and call it in module config file as
$this->layoutPath = Yii::getPathOfAlias('application.modules.moduleName.views.layouts');
$this->layout = '/layouts/layoutname';
register all the js and css file as #PeterM mentioned
Create a folder "layouts" in your views folder. Create main.php in that layouts folder.
In your , add following code:
<link rel="stylesheet" href="<?php echo Yii::app()->request->baseUrl; ?>/css/style.css" type="text/css" media="screen"/>
<script type="text/javascript" src="<?php echo Yii::app()->request->baseUrl; ?>/js/cycle.js"></script>
This is your default layout. So add,
<?php echo $content; ?>
This is another method to include css and js in all views.
Easy using this static method
<?php Yii::app()->clientScript->registerCssFile(Yii::getPathOfAlias('application.modules.curriculo.assets') . '/bootstrap/datepicker/css/datepicker.css'); ?>
<?php Yii::app()->clientScript->registerScriptFile(Yii::getPathOfAlias('application.modules.curriculo.assets') . '/bootstrap/datepicker/js/bootstrap-datepicker.js'); ?>
This should help you:
http://www.yiiframework.com/wiki/249/understanding-the-view-rendering-flow/
All three sections (beginContent, container and endContent) are explained in detail.

Dynamic content in css file

I am modifying a web app. It allows the user to input hex values for label-color, background-color and font-color. When the user input the values and clicks "update template". I need to be able to update the background color, label color and font color depending on the hex values that the user inputs. I am storing the label-color, background-color and font-color along with other template information in a MySQL table. I can do the following in the all the .phtml files that control the view:
$Idtemplate = $this->user->defaultTemplate;
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$Title_Shiprequest = $Thetemplate->descriptionShipRequestTitle;
$clabel = $Thetemplate->descriptionlabelColor;
$cbackground = $Thetemplate->descriptionBkgColor;
$cfont =$Thetemplate->descriptionFontColor;
$clabel, $cbackground, $cfont are used for the color styling in the .phtml.
The problem is there are about 34 .phtml files. If I want to do it this way I have to find the div classes responsible for the colors and do the respective changes there. It sounds like a very inefficient and lengthy solution to me.
But there are about 4-5 classes in the css file where all the color values are defined and used. Its much easier and efficient for me to do something like the above mentioned code in css file (the only problem is it does not work in css file) and refer to them like below (i have renamed my common.css as common.php):
.panel1
{
width: auto;
height: 22px;
background-color: <?= $cbackground ?>;
padding: 5px;
}
When I try to include the code to fetch color information from the database it messes up all the formatting as if the program cant see my .css file. My hunch is that I am not allowed to instantiate an object inside a heredoc in a css even though I renamed it as common.php. What could be a workaround solution in this situation?
UPDATE:
Well I was already including header("Content-type: text/css"); But i tried the followings again just to make sure:
<?php
header("Content-type: text/css");
$Idtemplate = $this->user->defaultTemplate;
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$clabel = $Thetemplate->descriptionlabelColor;
$cbackground = $Thetemplate->descriptionBkgColor;
$cfont =$Thetemplate->descriptionFontColor;
?>
<style type='text/css'>
.text4
{
color: <?=$clabel?>;// font and bkg colors are referred to likewise
}
</style>
Unfortunately this did not work. I also tried:
<?php
header("Content-type: text/css");
include('C:/sr/public/css/getdata.php');
?>
<style type='text/css'>
.text4
{
color: <?=$clabel?>;// font and bkg colors are referred to likewise
}
</style>
where getdata.php has the code:
<?php
$Idtemplate = $this->user->defaultTemplate;
include('C:/sr/application/models/Template.php');
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$clabel = $Thetemplate->descriptionlabelColor;
$cbackground = $Thetemplate->descriptionBkgColor;
$cfont =$Thetemplate->descriptionFontColor;
?>
It did not work either. As a fourth variation I tried to define a function and call it from common.php:
<?php
function getLabelColor() {
$clabel = '#001122';
return $clabel;
}
function getBkgColor() {
$cbackground = '#002233';
return $cbackground;
}
function getFontColor() {
$cfont = '#004455';
return $cfont;
}
?>
where common.php has :
<?php
header("Content-type: text/css");
include('C:/sr/public/css/getdata.php');
?>
<style type='text/css'>
.text2
{
color: <?php echo getLabelColor();?>; /* Bkg and font colors are referred to likewise*/
}
</style>
Surprising this worked. But when I tried to replace
$clabel = '#001122';
(along with $cbackground and $cfont in the respective functions) with
$Idtemplate = $this->user->defaultTemplate;
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$clabel = $Thetemplate->descriptionlabelColor;
return ('#'.$clabel);
it stopped working. So I moved getdata.php to models made class that included all the above mentioned functions:
<?php
Class fetchData extends Template
{
function getLabelColor() {
$Idtemplate = 101// I had assign a known value here. I was not able to use $this->user->defaultTemplate; Not sure why I wont be able to use $this
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$clabel = $Thetemplate->descriptionlabelColor;//for future usage for dynamic color
return ('#'.$clabel);
}
function getBkgColor() {
$Idtemplate = 101// I had assign a known value here. I was not able to use $this->user->defaultTemplate; Not sure why I wont be able to use $this
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$cbackground = $Thetemplate->descriptionBkgColor;//for future usage for dynamic color
return ('#'.$cbackground);
}
function getFontColor() {
$Idtemplate = 101// I had assign a known value here. I was not able to use $this->user->defaultTemplate; Not sure why I wont be able to use $this
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$cfont =$Thetemplate->descriptionFontColor;//for future usage for dynamic color
return ('#'.$cfont);
}
}
?>
I was calling the functions like below:
include('C:/sr/application/models/getdata.php');
$datafetchObj = new fetchData();
$clabel = $datafetchObj->getLabelColor(); //purple 51:0:153
$cbackground = $datafetchObj->getBkgColor(); //Light blue 102:102:204
$cfont = $datafetchObj->getFontColor();
This only worked from .phtml but not from common.php. I suppose common.php is NOT allowed to instantiate an object.
PS: This what my common.php call looks like:
<link rel="stylesheet" type="text/css" href="<?php echo $this->baseUrl();?>/css/common.php" />
You just use
<link rel="stylesheet" type="text/css" media="screen" href="/css/mycss.php" />
and then you can use php inside your css. you could add appropriate headers (text/css) with header in php.
// mycss.php
<?php
header("content-type:text/css");
?>
<style type='text/css'>
// Stylesheet
</style>
Add this line as a first line of page in common.php:
header("Content-type: text/css");
I was having the same problem as you, then I changed the hex color to the name of the color in the database and everything worked fine. I don't know why the hex color can't come out like other texts, but anyways, simply change the color the name:
E.I.: white for #FFFFFF
I hope that worked out for you.
EDIT: I thought that could be helpful too,
When inserting to database, use hexdec() http://www.php.net/manual/en/function.hexdec.php and when displaying from database, use dechex() http://php.net/manual/en/function.dechex.php .
dechex will return the hex without the hash (#) though, so you might need to print it like that:
<?php echo "#".dechex($decimal_number); ?>
I hope that was useful buddy.

Arguments to PHP template functions

This is more of a style question. I have a template file header.php in which I define a PrintHeader() function.
Callers of this function can specify, via global variables, the title of the page and any Javascript scripts to include when printing the header (because surely not every page will have the same title or want to include the same scripts). I chose to use global variables rather than function arguments because the latter would require the interface to change when adding new arguments.
Is this considered "good" style, and is there a "better" way to do what I'm trying to do?
header.php (simplified)
<?php
function PrintHeader()
{
global $pageTitle, $scripts; // Set by the caller of this function
echo <<<HEADER
<html>
<head>
<title>$pageTitle</title>
HEADER;
if( !empty($scripts) )
{
foreach($scripts as $script)
{
echo " <script type=\"text/javascript\" src=\"$script.js\"></script>\n";
}
}
echo " </head>\n";
}
?>
index.php (simplified)
<?php
$pageTitle = 'Welcome';
$scripts = array('script1', 'script2');
require('header.php');
PrintHeader();
// Print the rest of the page
?>
is there a "better" way to do what I'm trying to do?
sure.
I see no point in defining and calling a function at all. as well as in using heredoc.
header.php (dramatically simplified):
<html>
<head>
<title><?=$pageTitle?></title>
<? if( !empty($scripts) ): ?>
<? foreach($scripts as $script): ?>
<script type="text/javascript" src="<?=$script?>.js"></script>
<? endforeach ?>
<? endif ?>
</head>
index.php:
<?php
$pageTitle = 'Welcome';
$scripts = array('script1', 'script2');
require('header.php');
?>
but still it's not the best way, as it seems you're not using a template where it most valuable - to output page contents itself.
So, I'd make it in three parts:
links.php (simplified):
<?
//include our settings, connect to database etc.
include dirname($_SERVER['DOCUMENT_ROOT']).'/cfg/settings.php';
//getting required data
$DATA = getdata("SELECT * FROM links");
$pagetitle = "Links to friend sites";
//etc
//and then call a template:
$tpl = "links.tpl.php";
include "main.tpl.php";
?>
where main.tpl.php is your main site template, including common parts, like header, footer, menu etc:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My site. <?=$pagetitle?></title>
</head>
<body>
<div id="page">
<? include $tpl ?>
</div>
</body>
</html>
and finally links.tpl.php is the actual page template:
<h2><?=$pagetitle?></h2>
<ul>
<? foreach($DATA as $row): ?>
<li><?=$row['name']?></li>
<? endforeach ?>
<ul>
notice native HTML syntax, which is highlighted, readable and centralized in one place instead of being split between numerous functions and files
The point is in having separate template for the every PHP page as well as main site template for them all. With such setup you'll get a lot of advantages such as custom error pages, multiple representations of the same data (say, HTML, JSON or XML) by switching only templates without changing the code and many more
The use of global variables is certainly not advisable, and I question the necessity of using heredoc as you have - not that there is anything inherently wrong with heredoc, just that you seem to have rather arbitrarily utilized it in this sample template.
It is not elegant to use a return-value of a function as the output of each template - this defeats one of the purposes of templates which is re-usability.
Take a look at smarty, if not to directly use it (after all, why re-invent the wheel), at least to get an idea of how a rendering class is used to shuttle in the variables that a template needs without resorting to messy globals.
Here's a very quick overview of a way to do templating:
You have a template class that you can assign data to and then render a template.
Template.php:
class Template
{
protected $data = array();
public function assign($key, $value)
{
$this->data[$key] = $value;
}
public function render($file)
{
extract($this->data);
require $file;
}
}
You then have your template, header.php:
<html>
<head>
<title><?php echo $pageTitle; ?></title>
....
In index.php, you then use the template class to assign data and render your template.
$tpl = new Template;
$tpl->assign('pageTitle', 'My page title!');
$tpl->render('header.php');
This is just a simple example to demonstrate the idea, and could give you a good starting point.
While "better" may be in the eye of the beholder, I would suggest having some sort of functions that set the page bits rather than exposing raw variables. For instance, instead of doing $pageTitle = 'Welcome'; you could have set_page_title('Welcome');.
For JavaScript you could have a function that adds to the current script set -- rather than possibly replacing it all -- such as add_javascript($code);. This will allow a developer to set all of these without having to keep track of what the variable name was, and also without needing to global it as well if they want to set it from within a function.
This is an alternative using output buffering.
p/example_page/index.php is one of your pages:
<?php
ob_start() ?>
<h1>Example</h1>
<p>This is the page content</p>
<?php $main = ob_get_clean();
ob_start() ?>
<script defer src="js/example_page/example.js"></script>
<?php $script = ob_get_clean();
$title = 'Example page';
include 'templates/base.php';
templates/base.php is your reusable layout:
<!doctype html>
<html>
<head>
<script defer src="js/main.js"></script>
<?php echo $script ?>
<title><?php echo $title ?> - Example website</title>
</head>
<body>
<header>
<nav aria-label="Main menu"></nav>
</header>
<main><?php
echo $main;
?></main>
<footer>Example footer</footer>
</body>
</html>
Global variables are generally considered bad, and should be avoided if possible.
Rather than listing every variable in the interface, as you said things could change, pass a single array to the PrintHeader() functions:
<?php
function PrintHeader($opts=array()) {
if(!isset($opts['title'])) $opts['title'] = 'Default Title';
echo <<<HEADER
<html>
<head>
<title>$opts['title']</title>
HEADER;
if(!empty($opts['scripts'])) {
foreach($opts['scripts'] as $script) {
echo " <script type=\"text/javascript\" src=\"$script.js\"></script>\n";
}
}
echo " </head>\n";
}
$opts = array('title'=>'Welcome',
'scripts'=>array('script1', 'script2'));
require('header.php');
PrintHeader($opts);
?>
This way, you can add new capabilities in the function without breaking old code.

Categories