Capture content after function is called - php

Is it possible (in PHP) to call a function that triggers some capturing process so all HTML output after that function is captured up until an ending function? For example, some profiling applications do very similar procedures to this, and with functions such as ob_start(), it seems logical to me.
Example of concept:
<?php beginSection("hello"); ?>
<b>Hi there!</b>
<?php endSecton("hello"); ?>
<!-- Section "hello" now contains "<b>Hi there!</b>" -->

The way output buffering works does not allow you do this in a named fashion - ob_start and its friends stack on eachother, and unwind in order. You could implement it like this:
<?php ob_start(); ?>
<b>Hi there!</b>
<?php $sections['hello'] = ob_end_clean(); ?>
This would answer your question.

Related

PHP buffer included file as anonymous function

I have a kind of template file that may be called filename.php:
<h1>
<?= $test . ' world'; ?>
</h1>
<p>
Some text
</p>
Then I have a function in an index.php file that looks like this?
<?php
function test($args) {
$test = $args;
include 'filename.php';
}
test('Hello');
test('Hello');
test('Hello');
This code works. It output the included data 3 times.
I can also use output buffering to get the output as a string if I want. However, that's not exactly what I want.
Problem
I can't figure out a way to only need to include the filename.php one time (now it's loaded 3 times). Because it accepts arguments it can't be returned as string. It needs to be returned as an anonymous function, I guess. Then I could buffer my template and still use it with new values.
Any creative ideas are welcome.

PHP Literal output with ?> in function definition

When writing PHP code in the past, I have often been plagued by the awkwardness of having to nest my HTML code in calls to print, echo or similar. This is alleviated to some degree by the ability to make parts of the code be literally outputted by closing the PHP tag and reopening it again after the output, eg:
<?php /*DoSomeStuff*/ ?>
Some HTML code.
<?php /*SomeMorePHP*/ ?>
However, I have never been clear on how this interracts with functions. For example, it is unclear to me if writing:
<?php
function myFunction() {
?>
Some HTML
<?php
}
?>
Will produce a function which upon being called will output that HTML, if the function will be parsed as empty but output that HTML during parsing, or neither, both or if this construct is just illegal entirely?
I am reluctant to base all my results on just trying this on some particular instance of PHP as I do not wish to beleive it works while in reality it might be undefined behaviour or think it doesnt work while I might just have an old or buggy PHP and I have never seen this construct used in any code.
Ideally I am looking for some kind of reference to documentation or specification which would clear this up.
I know this is not exactly answering your questions with a lot of references, but: This is valid (PHP Docs), although it doesn't look very nice, it's a common practice in some old but BIG frameworks.
You can try this and see what happens:
function htmlOut() {
?>
Some HTML output
<?php
}
htmlOut();
By the way I found an example, the default skin of MediaWiki (I would say they know what they are doing) is using just the method you have described.
/**
* Outputs the entire contents of the (X)HTML page
*/
public function execute() {
/**
* some code
*/
// Output HTML Page
$this->html( 'headelement' );
?>
<div id="mw-page-base" class="noprint"></div>
<div id="mw-head-base" class="noprint"></div>
<div id="content" class="mw-body" role="main">
<a id="top"></a>
<?php
/**
* some more code
*/
}
See the full code here: MediaWiki GitHub
Basically it will work as you expect it to be, which means that this HTML will be printed only on function invoke.
There's probably no documentation for your use case, but it's similar to condition expressions.
You could ask if similar question for code below:
<?php if ($expression == true): ?>
HTML1
<?php else: ?>
HTML2
<?php endif; ?>
Will PHP print both HTML parts, or only one depending on the condition?
Well, the doc says clearly that it works as it is expected to be.
I think we can say it's the same for functions/methods, because it's just "a block of code". It works with the same rule in many other cases like loops or swich
Reference: http://php.net/manual/en/language.basic-syntax.phpmode.php Example #1

PHP alias of specific line in php script?

I am working with levels of security with my app and i have written a function that simply checks - depending on it's session user id what kind of priviligies he/she has. It works fine but in some pages i want to output some information if the user is superuser, and forbid to output information if user is a guest.
I do it with such a syntax:
1. <? if admin('superuser', $_SESSION['user_id']) { ?>
2. <div></div>
3. <? } ?>
It works good but it's not elegant, and in case long code between curling brackets it messess with purity of my code.
Is there a way to "alias" a line 1 and 3 to some kind of shortcut, ie
1. <? admin_superuser ?>
2. <div></div>
3. <? admin_super_user_end ?>
Maybe you have some other ideas to perform such levels of security?
The idea came from ob_start() and ob_end() commands.
I am waiting for your ideas.
Kalreg.
you could simply set a bool at the beginning of the page:
$isSuperUser = admin('superuser', $_SESSION['user_id']);
Then, just do
<? if ($isSuperUser) { ?>
<div></div>
<? } ?>
If you don't like the $, you could define a constant:
define("SUPERUSER", admin('superuser', $_SESSION['user_id']));
Then, just do
<? if (SUPERUSER) { ?>
<div></div>
<? } ?>
Good thing about a constant is that it is global, and if using in a function, you wouldn't have to declare it global first, or pass it as an argument.
I would go with something like this. I think this totally acceptable.
To simplify it you just need a wrapper for your user.
<?php if ($user->isAdmin()): ?>
<div></div>
<?php endif; ?>
you can include another php file that contains the corresponding html / php code with the "include" function. i also recommend to use <?php instead of just <? due short open tag issues with xml and ini settings.

How to write class/function that returns large amount of html

I'm used to using includes with large chunks of html outside of the php code, but I'm trying to move to classes or functions because they have increased flexibility and potential for design patterns etc.
I need a function right now that will return a large amount of html, mixed in with some php variables, but I'm looking for away to keep the code outside of the <?php declaration so that it will be formatted like proper html and have code hinting, rather than being a gigantic string.
If it's possible, how would I go about formatting/writing that?
I would do something like this...
function getPage() {
ob_start();
include("file_with_html.php");
$content = ob_get_clean();
return $content;
}
Of course, you can add other functionality as needed. But, the advantage here is that you're using output buffering. Without this, the data is sent to the user right away. But, using the ob_start() and ob_get_clean(), you can return it and work with it some more.
You can use include('somefile.html');.
include works with vanilla HTML too.
If you need to have it "mixed in with some php variables", just add those when you need them. Remember: PHP, by its very nature, is a templating language.
For example:
outerHTML.php:
<?php function generateCode($username) { ?>
<h1>Welcome back, <?php echo $username; ?></h1>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<?php } ?>
main.php:
<?php
// some PHP code
include('outerHTML.php');
generateCode('John');
// some more PHP code
?>
Also, you can use output buffering within your classes. See comments at http://php.net/manual/en/function.ob-start.php

How could you create a "content_for" equivalent in PHP?

I've been working on a small page in PHP, one that doesn't need the power of a full-fledged framework behind it. One thing that I'm really missing from previous work in Ruby-on-Rails is the ability to effectively pass content up the page using "content_for".
What I was wondering is, how could you create a page lifecycle that would accomplish this same effect in PHP?
So, here's a simple example:
Let's say you have a template that defines an index page, just a recurring header and menu you want to use on all your pages. So your index.php file looks basically like this:
...header stuff...
<body>
<?php include $file.'.php'; ?>
</body>
...footer stuff...
EDIT: Thanks for the tips on URL security, but let's just assume I'm getting the user request safely :)
Now, lets say in the header you want to put this:
<head>
<title><?php echo $page_title; ?></title>
</head>
It would be nice to be able to specify the title in the included file, so at the url http://example.com/index.php?p=test you're loading test.php, and that file looks like this:
<?php $page_title = 'Test Page'; ?>
... rest of content ...
Now, obviously this doesn't work, because the including page (index.php) is loaded before the variable is set.
In Rails this is where you could pass stuff 'up the page' using the content_for function.
My question is this: What would be the simplest, leanest way that you all can think of to effect this kind of 'content_for' functionality in PHP?
Ideally I'd like suggestions that don't involve strapping on some big framework, but some relatively light boilerplate code that could be used in a lot of different applications.
Never do include $_GET['p']. This opens a huge security hole in your site, as include accepts filenames and URLs, so anybody would be able to read any file on your site and also execute any code on your server. You may want to check and sanitize the value first.
If you need something simple, you may put header and footer in separate files, execute your test.php which would set the variables, capture its output using output buffering, then include the header, output the middle part and include the footer. Example:
<?php ob_start(); ?>
<body>
<?php include $filename.'.php'; ?>
</body>
<?php $content = ob_get_clean();
include 'header.php';
echo $content;
include 'footer.php';
?>
If I understand you correctly (I have not used RoR extensively), you could put your data in a variable or a function. If your content was in a variable, your "test.php" could simply hold all your variables and you could load it at the very beginning of your index file (likewise for a function depending on how complicated your needs are; if you're doing a lot of extra work, you may need to use a function as a variable won't work).
For example, your test.php would look something like this:
<?php
$page_title = "Test Page";
$page_content = "Some sort of content";
// Or
function page_content()
{
// Run some functions and print content at the end
}
?>
Then, in your index.php
<?php include $_GET['p'].'.php'; ?>
...header stuff...
<title><?php print $page_title; ?></title>
<body>
<?php print $page_content; ?>
<!-- OR if function -->
<?php page_content(); ?>
</body>
...footer stuff...
This way everything should load properly. You could also split things up, but that would complicate your structure (especially if there is no need for an elaborate framework, this would be unnecessary).
Good luck!
Dennis M.
Are you worried about XSS? Or are you going to filter/whitelist the "filenames" from the query string?
My answer would be to use mod_rewrite -- if you're using PHP, you're likely using Apache!
You could filter out files with a RewriteCond and your RewriteRule could be:
RewriteRule /index.php?p=(.*)$ $1 [L,QSA]
This may be a different approach than the PHP functionality you were looking for, but it comes to mind...

Categories