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?>;
}
Related
I just started coding PHP, I know how to include PHP however I encountered difficulties in this case.
I have a LAMP server, in the root folder I installed my own framework as below (folders are in capital letters).
index.php
page.php
INCLUDES
- classes.php
- skins.php
- flow_init.php
- flow_head.php
- flow_body.php
SOURCES
- page1.php
- page2.php
...
THEME_HTML
- wrapper.html
VIEWS
- page1.html
- page2.html
...
wrapper.html is created into index.php
<?php // index.php
$skin = new skin('wrapper');
echo $skin->make();
This is my skins.php file
<?php // INCLUDES/skins.php
class skin {
var $filename;
public function __construct($filename) {
$this->filename = $filename;
}
public function mk($filename) {
$this->filename = $filename;
return $this->make();
}
public function make() {
global $CONF;
$file = sprintf('./'.$CONF['theme_path'].'/'.$CONF['theme_name'].'/html/%s.html', $this->filename);
$fh_skin = fopen($file, 'r');
$skin = #fread($fh_skin, filesize($file));
fclose($fh_skin);
return $this->parse($skin);
}
private function parse($skin) {
global $TMPL, $LNG;
$skin = preg_replace_callback('/{\$lng->(.+?)}/i', create_function('$matches', 'global $LNG; return $LNG[$matches[1]];'), $skin);
$skin = preg_replace_callback('/{\$([a-zA-Z0-9_]+)}/', create_function('$matches', 'global $TMPL; return (isset($TMPL[$matches[1]])?$TMPL[$matches[1]]:"");'), $skin);
return $skin;
}
}
?>
Each page of VIEWS is created inside SOURCES and page.php echo it.
Script to integrate
Everything works fine, but now I need to integrate this script between the wrapper (where the head tag is) and one view (where the content is)
<?php
session_start();
require_once('admin/plugins/flow-flow/ff-injector.php');
$injector = new FFInjector();
?>
<!DOCTYPE html>
<html lang="en-US">
<head><?php echo $injector->head(true,true); ?>
</head>
<body>
<table width="100%">
<tr>
<td style="width: 300px;vertical-align: top">
<?php
$stream_id = isset($_REQUEST['stream']) ? $_REQUEST['stream'] : 1;
$injector->stream($stream_id);
?>
</td>
</tr>
</table>
</body>
</html>
For the purpose I tried to create some templates:
<?PHP // index.php
$TMPL['flow_init'] = include './includes/flow_init.php';
$TMPL['flow_head'] = include './includes/flow_head.php';
<?PHP // SOURCES/page1.php
$TMPL['flow_body'] = include './includes/flow_body.php';
Where my included files are set as below
<?PHP // flow_init.php
session_start();
require_once('admin/plugins/flow-flow/ff-injector.php');
$injector = new FFInjector();
?>
<?PHP // flow_head.php
echo $injector->head(true,true);
?>
<?PHP // flow_body.php
$stream_id = isset($_REQUEST['stream']) ? $_REQUEST['stream'] : 1;
$injector->stream($stream_id);
?>
What I would expect to achieve
I tried to include flow_init and flow_head on my wrapper, like this:
// THEME_HTML/wrapper.html
{$flow_init}
<!DOCTYPE html>
<html lang="en">
<head>
{$flow_head}
</head>
<body>
<div id="content" class="wrapper">
{$content}
</div>
</body>
</html>
And flow_body into my content
// THEME_HTML/VIEWS/page1.html
<div class="row-body{$content_class}">
<div class="body-content">
<div class="nine columns" id="main-content">
{$flow_body}
</div>
<div class="three columns">
{$sidebar}
</div>
</div>
</div>
The results is a blank page, however if I include all the 3 templates together in the index.php it works, so I think it's not a source path problem.
What's the right method to divide a PHP script and make it executable?
You need to learn PSR-4 autoloading and how to use Composer if you want to start including files within files. This will make it much easier than having to use require_once everywhere you wish to have a file included.
If you're talking about view templating, Don't Reinvent The Wheel, unless you want to learn more about wheels. The two best templating engines that I've used are Laravel's Blade and Symfony's Twig. You can also try out the League of PHP Developer's templating engine, which only uses raw 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!
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.
I have a PHP script that creates HTML by calling PHP class that I have created. The class creates all the HTML tags one of which is a tag that loads an external JS file. When I try to access the functions from said file nothing happens. Any Ideas?
index page:
function main(){
$content = "Heres some text for you";
$page = new Page($title="MyTitle", $script="external.js", $content=$content)
echo $page->toString();
}
function __autoload($className){
require_once $className . '.class.php';
}
class page:
//class constructor
function __construct($title='untitled', $script='', $content='Default Page class page'){
$this->title = $title;
$this->script = $script;
$this->stylesheet = $stylesheet;
$this->content = $content;
// $this->currentUser = $currentUser;
}
// creates tag structure for HTML pages
function toString(){
return <<<END
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="jquery.js"></script>
// Heres the link to the external JS file
<script type="text/javascript" src="$this->script"></script>
<script type="text/javascript">
test();
</script>
<title>$this->title</title>
<link type="text/css" rel="stylesheet" href="$this->stylesheet" />
</head>
<body>
$this->content
<p id='content'>page content</p>
</body>
</html>
END;
}// end toString function
} // end class Page
?>
External JS:
function test(){
alert("ext. JS test works");
}
You cannot have any spaces before the ending identifier of your heredoc:
END;
should be:
END;
I would also check to make sure that the path to your external.js file is correct. Are any of the other things working? Like the title or css? You also are not passing $stylesheet into your __construct anywhere which produces an error trying to set $this->stylesheet, maybe the whole script is failing to load because of that?
Don't see anything that stands out....
Are you sure the JS file is accessible in the same directory as your script (may want to apply an absolute or relative path if necessary)?
You might also, since you have jquery (assuming it's loaded), try putting the call to test(); in an "on ready" block, like so:
$(document).ready(function () {
test();
});
Other than that, I'd use your given browsers debugging tools to see if you can glean anything useful (like the script not even being loaded as a resource).
Good luck!
thank you for viewing.
My website includes the same header and footer for each page using PHP.
I wanted a style sheet that only applied specifically for a certain page, so put the style in using the appropriate tag.
...<body><style type="text/css"> /* what ever */ </style></body>...
The style sheet is processed correctly in all browsers I tested, however it is not validated correctly by W3C because it's located inside the body tag instead of the head.
My question is:
If I can't put the style sheet in the body tag, what is the best way to include it? I can reference the style sheet in the PHP header, but I'd rather not have another HTTP Request for such a small file. How would you do it? What is the least sloppy way to do it? Although the style tag shouldn't be in <body>, it is still processed correctly by browsers.
What about giving the body an id and then just including the page specific files in the general CSS but with the styles prefixed by the id selector? Something like this:
On page
<body id="pageSpecificId">......</body>
In CSS file:
#pageSpecificId p {
... paragraph specific styles ...
}
#pageSpecificId li {
... list item specific styles ...
}
The best way would be to use a MVC framework that buffers your view file, and allow tag to be dynamically added to the head before output.
Here is a ultra simple way of doing it:
index.php:
<?php
class Page {
private static $head = array();
private static $content = '';
static function add_head($tag) {
self::$head[] = $tag;
}
static function render_head() {
foreach (self::$head as $tag) echo $tag;
}
static function render_content() {
echo self::$content;
}
static function read_content($file) {
ob_start();
require $file;
self::$content = ob_get_clean();
}
static function render_layout($file) {
require $file;
}
}
Page::read_content('view.php');
Page::render_layout('layout.php');
?>
layout.php:
<html>
<head><?php Page::render_head(); ?></head>
<body>
<div id="header"></div>
<div id="content"><?php Page::render_content(); ?></div>
<div id="footer"></div>
</body>
</html>
view.php:
<?php Page::add_head('<title>Hello World!</title>'); ?>
<h1>Hello</h1>
<p>World</p>