PHP- can't see class member after include - php

ok i have an index.php as so:
<?php
require 'php/stdlib.php';
$site->page->render();
foreach($page as $var => $value) {
echo $var ." is ". $value." <br/>";
}
?>
the obj creation for site and page is in the stdlib file and is obviously working cuz
the -for each- loop prints out:
name is welcome
headers is inc/index_h.php
footers is inc/index_f.php
contents is inc/welcome.php
It show that the object is created.
I also did a var dump with proper results
here is site---page---render:
public function render_page(){
$this->page->render();
}
here is page---render:
public function render(){
include $this->headers;
include $this->contents;
include $this->footers;
}
however the result of the script is the following:
Undefined variable:
and also
Trying to get property of non-object:
both errors point to my $page object that i used in the include file for the page header:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><?php echo $page->name; ?></title>
<script src="/scripts/jquery.js"></script>
</head>
<body>
The errors actually print out in the html title tag not on the screen meaning i have to use View Source on my browser to see it
How do i get the $page object to be visible when using an include
Im usually pretty good about finding answers myself but this thing has me stumped for two days now.(I have learned alot about many other things while searching for answer tho so I guess not all is lost) If anyone could help me I would greatly appreciate it.
Probably should have added that the page and site object are instantiated in stdlib.php with the following
$site = new csite();
site_ini($site);
$page = new cpage("welcome");
$site->setPage($page);

When you use PHP's build-in include function, the contents of the included file are executed in the same scope as the call to include. Therefore, you really want to call $this in the included files, as their code is executed as-though it were actually written inside the render() method, and you will note that no $page variable was declared in that method.
On the other-hand, it may make more syntactic sense to set $page = $this prior to the first include.
I up-voted for you because, while the title does not suggest it, you are actually highlighting an important aspect of the PHP include and require functions: the way they pass scope.
For more information about this topic, have a close read of the PHP.net documentation on the function:
http://www.php.net/manual/en/function.include.php
Edit: To clarify why one example works, and another does not, it is because $page, from the include, has the same scope as your foreach, but is not declared inside the render.
Do not pull it in as a global, however. As syntactically you want to render the page you call render on, so: $this

Related

Why is my conditional statement not working?

I'm trying to use one header.php to process both my public pages and my admin pages using conditional statements. I can get this technique to work when I use an include, but I learned a different technique for including files using a function and now my conditional statements for admin and public are not working.
So this code is at the top of my header.php wrapped in php tag.
if (!isset($layout_context)) {
$layout_context = "public";
}
Then in my header tag I have sections of code like this
<?php if($layout_context == "public") { ?>
<header id="home">
<?php ; } elseif($layout_context == "admin") { ?>
<header id="cms-pages">
<?php ; } ?>
Then in all my pages I put this code at the top
<?php $layout_context = "public"; ?>
or
<?php $layout_context = "admin"; ?>
When I use this code:
<?php include("includes/layouts/header.php"); ?>
I can get those conditional public and admin codes to work, but when I try and use this technique to include my header.php
<?php include_layout_template('header-admin.php'); ?>
function lives in the functions.php in the includes folder.
function include_layout_template($template="") {
include(SITE_ROOT.DS.'includes'.DS.'layouts'.DS.$template);
}
I can't get the conditional code to work. Does anyone know why that might be?
Thank you :)
You state that after a standard include include("includes/layouts/header.php");, you are able to use $layout_context, but that after an include using a function include_layout_template('header-admin.php');, you are not.
This is to problems with variable scoping.
Your $layout_context is defined within the header.php file, outside of any function declaration.
In a file like this, if you include it at the global level, then the variables in it will be come global variables.
However, if you include it from within a function, then those variables become variables within that function.
Thus when you call include_layout_template(), the variables are created, but are only scoped within include_layout_template(). As soon as the function returns, those variables are no longer available.
The quick and dirty solution here is to define them as global within the header.php file. So add global $layout_context; to the top of the code in this file, and the same for any other variables declared within it.
That will probably get you up and running with the minimal work from where you are now.
However, global variables are a very blunt tool and generally considered very poor practice for a number of reasons. You would be much better off rewriting your config variables so that you can reference them from a function call or object. This way you can include them from wherever, any they will still be accessible in the same way.
Dont use == for string comparison. Always use strcmp() for string comparison.
Change
if($layout_context == "public")
to
if (strcmp($layout_context, "public") == 0)
{
//string is equal
}

PHP: Echo function output in function-line, not line of function call

I have a problem with my self-coded template system. The content is inserted by Include(). Now I need to add a meta redirect to one page. I know, meta redirect is not the safest way, but I need it because of it's delay possibility.
Now i'm looking for a way to influence the wrapping page (template) by the wrapped page (content).
So I thought a function can do this job.
<?php function test($testvar){
echo $testvar;}
?>
<hr />
<?php
test("testtext");
?>
Of course the text echos in the line of the function call, not in the function line. Is there a way to make the function echo in the line of the function itself? In this case above the horizontal rule, not below?
Of course every other best pratice for this "template problem" ist welcome!
THX
EDIT:
<html>
<title>testpage</title>
<? a_function_that_echos_a_metatag_for_redericetion($param){
echo $param;
}
?>
<head>
<body>
<? include("test.php");
INCLUDED script---->
a_function_that_echos_a_metatag_for_redericetion("\"<meta http-equiv=\"refresh\"...")
Procedural programming cannot have the logic you request.
If you want to add the meta redirect element before the page content, you HAVE to know that you are GOING to make this redirect before the <head> is closed.
Is there a way to make the function echo in the line of the function
itself?
No. Functions are declarations and aren't executed until they are called.
If you wish to modify the request headers later down the page, then you'll need to employ output buffering. However, this approach will likely be overkill if only one page needs the special header consideration. It may be better to just detect the page via some parameter (such as REQUEST_URI) and insert the header conditionally from that.

"delay" inclusion of separate file in PHP?

At the very top of my page/site, before <!doctype html> etc., I load my classes with spl_autoload_register().
One of the classes is site, and inside this class I have a static function:
<?php
/**
* A fast and easy way to include content to a page...
* "dir_pages_contents" is a defined constant with the path to the content files
*/
public static function include_content($content_name){
if(file_exists(dir_pages_contents.$content_name.'.cont.php')){
include dir_pages_contents.$content_name.'.cont.php';
} else {
/* echo an error message */
}
}
?>
I was hoping to do something like this i practice:
create a new document with some content and save it with the extension .cont.php into a folder specified for page contents.
Then; On the page where I want this content to be displayed - I do:
site::include_content('test_doc');
This almost works; The document, or content, is included and displayed.
But it seems like it is included where the class is - at the very top where the class is - because PHP-variables set outside of this document is not available within the document at all.
Here's a illustration of the setup:
test_doc.cont.php
<?=$hello?>
index.php
<!-- PHP-classes are included here -->
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
</head>
<body>
<?php $hello = 'Im outside...'; ?>
<!-- this includes the document, but the variable $hello is not -->
<?=site::include_content('test_doc')?>
<!-- this works perfectly -->
<?php include dir_pages_contents.'test_doc.cont.php; ?>
</body>
</html>
The inclusion of a separate file, or document, is done immediately when the include-statement is read by the script i guess? but not displayed until futher down the script where the function was called?
Any suggestion for another way to accomplish this?
I'm not looking for any MVC or other PHP-framework.
EDIT:
user1612290 pointed out to me that the include-statement within my include_content-function only uses the variable scope of my function - meaning that any variables decleared outside my include_content is not passed to the include directive unless I make them global.
It was also suggested that I could pass an array of named keys=>$variables into my function and use extract() on them to make them available.
This is what I came up with:
- added $arr
public static function include_content($content_name,$arr){
if(file_exists(dir_pages_contents.$content_name.'.cont.php')){
if (is_array($arr)){extract($arr);}
include dir_pages_contents.$content_name.'.cont.php';
} else {
/* echo an error message */
}
}
Now I'm able to do this:
<?=site::include_content('test_doc',array('hello'=>$hello))?>
Allthoug I'm not happy with this solution, I now have the variables accessable within the included document - so I'm closer than I was an hour ago :)
Any easier way?

Something wrong with PHP include title

I'm relatively new at PHP and came across a slight problem.
I have a php page called info.php and use an included php file called components.php to pull functions that have html code in them that is then used in page.php (and other pages.) I put the title in a variable called $title and then reference that in my components.php, but for some reason the components.php doesn't recognize that as a title. Here's the code, and thanks for all help ( I know my description of the problem is hard. Let me know if you need any more info)
page.php
<?php
include("components.php");
$title = "This is my page Title!";
echo writeHeader();
?>
components.php
<?php
function writeHeader()
{
echo <<<HED
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>
HED;
echo $title;
echo <<<HED
</title>
HED;
}
?>
Good solution: Pass $title as a parameter to he function.
Less good solution: Declare $title as
global $title
within the function to make it belong to the global scope.
Without declaring it as global, it is a fresh new variable.
To summarize the comments:
Never use global! Anything a function/method depends on, should be passed as a parameter.
Never access $_GLOBALS! Same reason.
Disable register_globals! No GET-parameters should be automatically injected into your application.
Enable the highest error level! Write your application in such a way, that no error or warning gets printed.
Unfortunately, my question regarding PHP newbie practices is closed. But it provides some helpful hints.
In case you like it, click the re-open link.
A variable has a scope. When you declare it, unless it's global you can't use it in another scope. To do that you have to pass it to the other scope using parameters
Your code should be like that :
page.php
<?php
include("components.php");
$title = "This is my page Title!";
echo writeHeader($title);
?>
components.php
<?php
function writeHeader($title)
{
echo <<<HED
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>
HED;
echo $title;
echo <<<HED
</title>
HED;
}
?>
In your code example, you call the echo function at two places :
In your page.php file : This one does nothing
In your component.php : This one prints the text
The best practice is to group the prints into a single component called the "view".
If your view is the file called component.php then you should remove the first echo.

PHP placement problem

I am calling this function halfway down the page:
<div id="leftArea">
<?php
if (isset($id)){
single($id);
}
?>
</div>
The problem is i want use some of the output in the meta tags in the <head>, whats the best way to approach this?
EDIT:
The single function, takes the $id and echo's the data straight to the page, exactly where it is. In the DIV leftArea. But i want to take one of the rows from the DB and insert it into the META tags at the top
Copy the code into the <head> section.
Redesign your System
The best method is to create a class that manages your html page for you, example:
$Page = new HTMLPage("My Page",HTMLPage::Strict);
$Page->addScript("....");
$Page->addScript("....");
$Page->addScript("....");
$Page->addStyle("....");
$Page->addStyle("....");
$Page->addStyle("....");
$Page->SetBody($MyTemplate);
$Page->send();
this way though out your functions you can do
function myfunc()
{
global $Page;
$Page->addScript("....");
}
the main point here is you should build your document up before sending it to the browser, this way you still have control over the content no matter where your code is executing from.
on the final send method you build your content up, and then push the content via echo, and then exit directly. (all processing should be done prior to output to manage errors)

Categories