Why the "use" command in PHP not working with include? - php

I have this script:
<?php
error_reporting(E_ALL);
require 'vendor/autoload.php';
use Church\Config;
use Church\SQLiteConnection;
use Church\Template;
use Church\User;
$ERROR = "";
if(isset($_POST['username']) && isset($_POST['username']))
{
$login = new User((new SQLiteConnection())->connect());
if($login->loginUser($_POST['username'], $_POST['password']))
{
}
else {
$ERROR = "login";
}
}
if(isset($_GET['go']))
{
}
else {
if (!file_exists(Config::PATH_TO_SQLITE_FILE)) {
include('init/install.php');
}
}
When I make it with this part:
include('init/install.php');
instead of this:
$tpl = new Template('templates/install.tpl');
$tpl->set('HEADER', $tpl->getFile('templates/header.tpl'));
$tpl->set('FOOTER', $tpl->getFile('templates/footer.tpl'));
$tpl->set('APP_NAME', Config::APP_NAME);
$tpl->set('APP_VERSION', Config::APP_VERSION);
$tpl->set('BASE_URL', $_SERVER['PHP_SELF']);
$tpl->render();
I get this error:
Fatal error: Uncaught Error: Class 'Template' not found in
I do not understand why it is working without include but with include is the auto loading not working. What did I miss?

Take a look at the docs here: https://www.php.net/manual/en/language.namespaces.importing.php
The use keyword must be declared in the outermost scope of a file (the global scope) or inside namespace declarations. This is because the importing is done at compile time and not runtime, so it cannot be block scoped. The following example will show an illegal use of the use keyword:
And then:
Importing rules are per file basis, meaning included files will NOT inherit the parent file's importing rules.
The conclusion is that you can't do what you want to do. You need to import (aka use) in your included file too.

Related

Cannot declare class because its already defined

I want to make my own class in php to handle my errors I want to show to the user, for example when the user are logging in but the password or username is false.
I have a map classes with the files:
errorHandling.class.php
class errorHandling
{
public $customError;
public function setCustomError($error)
{
$this->customError = $error;
}
public function getCustomError()
{
echo $this->customError;
}
}
And in the users.class.php
when the user try's to login and it fails the else will be like:
else {
include 'errorHandling.class.php';
$errorHandle = new errorHandling();
$errorHandle->setCustomError("Username or password are wrong!");
}
Then in the login.php in the root map I have this code to call the function:
include 'classes/errorHandling.class.php';
include 'classes/users.class.php';
$errorHandle = new errorHandling();
$errorHandle->getCustomError();
Well now I get this error message but I don't understand it so I hope some of you guys can helping me out or give me some tips to improve my class.
Fatal error: Cannot declare class errorHandling, because the name is already in use in /classes/errorHandling.class.php on line 1
Every time you include a file in php, it will be loaded and run. For class definitions, you want to use require_once, which as it says, will only be loaded once.

Undefined variable error on a variable inside an included file

I'm including this file to collect one of its variables. File path is correct and i don't get file include errors. But when i try to print a variable inside that file it gives undefined variable error. Following is the code.
include_once($path . "folder/file.php");
echo($code);
There is a php class. inside the class there is a login function . Within that function I'm including another file assume it's funtions.php.
functions.php has above code in it.
Inside functions.php file i include this file which contains the variable i'm looking for (assume it's test.php).
test.php looks like this (inside php tags)
$code="something";
$another_variable="something else";
so now like i said before when i include this inside functions.php and print $code it why does it gives an undefined error?
Full code
function log($user, $pass) {
global $config;
$this->get_available_accounts();
if (isset($this->Users_obj[$user])) {
if ($this->Users_obj[$user]->userName == $user && $this->Users_obj[$user]->passWord == $pass) {
delete_cache_full();
$_SESSION['username'] = $user;
$_SESSION['log'] = true;
$_SESSION['usergroup']=$this->Users_obj[$user]->level;
$this->set_permission_session($_SESSION['usergroup']);
include_once $config->path . 'config.php';
$newUpdate2=showUpdates2();
if(!empty($newUpdate2)){
$_SESSION['updateremindlater']=$newUpdate2['date'];
}
//file
include_once $config->path . 'functions.php';
$func = new UserFuncs();
$func->validate();
include_once $config->path . 'view/ViewDashboard.php';
return true;
}
}
thats the function im including this file into. include_once $config->$path . 'functions.php'; includes functions.php file
functions.php looks like this
include_once($path. "folder/config.php");
echo($code);
and config.php looks like
$code = "ERGERW2342HV3453WERWEER";
$host_name = "SERV345WERFDGDDFGDGF";
$return_code = "DFGDFSDGFS";
$vurl = "YUIYUJHGJ";
$next_val ="AWERFDFVDV";
$val_exp = "NMGHJGJGH";
Help much appreciated!
Just guessing that you've included config.php somewhere else before, and that it's not being included again due to include_once. Therefore the variables are not created in the scope you're including it in the second time.
This could be a problem with variable scope, where you are trying t access the variable from somewhere (e.g. a function) where it is not available to that particular object (you did mention that you included the file within a class).
I agree with deceze and hakre, it's very hard to answer this question without seeing your code.

PHP not finding function declared in required file

Recently downloaded some code for a minor open-source project related to a small webgame I play. Trying to access it fails and spits out an error message of:
PHP Fatal error: Call to undefined function v() in /Applications/MAMP/htdocs/infocenter/modules/security_mod.php on line 7
After searching, I found that the function v() is defined in a file called "system.php" which is required by a file which is required by a file which is required by the "security_mod.php" file that the error occurs in. No errors occur with any of the require calls (and they're all 'require_once', not an 'include').
This is the whole of the system.php file:
<?php
function v($a, $i)
{
return isset($a[$i]) ? $a[$i] : null;
}
?>
This is the function in 'security_mod.php' that throws the error (also including the require calls):
<?php
require_once("settings_mod.php");
require_once("account_mod.php");//this file requires base_mod.php, which requires system.php
class SecurityMod {
public static function checkLogin() {
$name = v($_REQUEST, "acc");//this is the line that causes the error
$password = v($_REQUEST, "pwd");
if (!isset($name) || !isset($password)) {
return null;
}
$acc = AccountMod::getAccount($name);
if (SettingsMod::USE_ENCRYPTED_PASSWORDS) {
if (is_null($acc) || $acc->getPassword() != md5($password)) {
return null;
} else
return $acc;
} else {
if (is_null($acc) || $acc->getPassword() != $password) {
return null;
} else
return $acc;
}
}
?>
I did a little testing, and found out that I can access variables and functions in some of the other required files. All of those are in classes, though, unlike v(). Would that be the reason?
EDIT to clarify how 'system.php' is required:
'security_mod.php' has these two require_once calls at the beginning of the file:
require_once("settings_mod.php");
require_once("account_mod.php");
'settings_mod.php' is a file containing constants used through the program, and includes no files.
'account_mod.php' has these two require_once calls:
require_once("base_mod.php");
require_once("account.php");
'account.php' has a pair of include_once calls that include inconsequential and unrelated files.
'base_mod.php' is the file with the ultimate requirement for 'system.php':
require_once("system.php");
require_once("settings_mod.php");
Found the issue: the System.php file being successfully included wasn't the same as the one in the downloaded code. Since base_mod.php only provided a filename, not a path, PHP first checked in the directory specified by my include_path, which turns out to contain a file named System.php. Since my filesystem is case-insensitive, that was judged to be the same as system.php, and therefore got included instead.

PHP Namespace and global variable issue within classes

I am stuck with this confusion where I don't understand why my global $error under my HelperClass() returns empty, where I could verify that $class->error is indeed filled up with data earlier on.
Is there some sort of issues with namespace in this case that I am not aware about? Please give me some pointers.
Here are some of the codes that are relevant.
Under Main file
namespace Core;
$class = new ControllerClass();
$error = $class->error;
// verified that $error prints correctly here
include ViewFile.php;
Under ViewFile.php
$helper = new HelperClass();
// __autoload function took care of the include
Under HelperClass:
namespace Core\Skeleton;
class HelperClass {
public function __construct() {
global $error;
// $error != $class->error as defined earlier
// $error is empty here
}
If you're using an autoloader or include your classes from within another helper function, then the $error variable was never declared in the 'global' scope. It ended up in some local, and got disposed.
Declare it shared right before you assign it a value.
namespace Core;
$class = new ControllerClass();
global $error;
$error = $class->error;
Also while there is nothing wrong with shared variables per se. The name $error seems slightly too generic. Maybe you can up with a less ambigious or more structured exchange variable. $GLOBALS["/var/log"]["controller_error"] or something arrayish.

PHP global, nested/inherited autoload

PHP 5.3.3-pl1-gentoo (cli) (built: Aug
17 2010 18:37:41)
Hi all, I use a simple autoloader in my project's main file (index.php):
require_once("./config.php");
require_once("./app.php");
require_once("./../shared/SqlTool.php");
function __autoload($className) {
$fn = 'file-not-exists-for-{$className}';
if (file_exists("./specific/php/{$className}.php")) { $fn = "./specific/php/{$className}.php"; } else
{ $fn = "./../shared/{$className}.php";}
require_once($fn);
}
$sql = new SqlHD(); // class SqlHD, in ./specific/php/SqlHD.php extends SqlTool
$web = new HTMLForm($sql); // class HTMLForm in HTMLForm.php
$app = new App($sql, $web); // class App in App.php
$app->Main();
The problem: without that require_once("./../shared/SqlTool.php");, script can't execute SqlHD.php, because it can't find SqlTool.php by itself, and for some reason it doesn't uses autoload routine defined in main file.
I tried this:
spl_autoload_register(__NAMESPACE__ .'\Test::load');
class Test {
static public function load($className){
$fn = 'file-not-exists-for-{$className}';
if (file_exists("./specific/php/{$className}.php")) { $fn = "./specific/php/{$className}.php"; } else
{ $fn = "./../shared/{$className}.php}";}
echo realpath($fn);//"$curRealDir Filename $fn\n";
echo "\n";
require_once($fn);
}
}
Well,
PHP Warning:
require_once(./../shared/SqlTool.php}):
failed to open stream: No such file or
directory in
/home/beep/work/php/hauthd/index.php
on line 20 PHP Fatal error:
require_once(): Failed opening
required './../shared/SqlTool.php}'
(include_path='.:/usr/share/php5:/usr/share/php')
in
/home/beep/work/php/hauthd/index.php
on line 20
So it doesn't reacts to any request from extended class.
Last second idea: put spl_autoload_register to each file. But cannot put it to "extends" directive itself!
P.S. May rewrite SqlTool.php using Factory pattern so it would automatically return an instance of project-specifc class, but it seems to be not a best way, or it is..?
If SqlHD extends SqlTool, then your __autoload() function should include this automatically.
Note you have an extra '}' in your filename which is probably messing this up. (Which you have also copy 'n' pasted into your 2nd code snippet.)
{ $fn = "./../shared/{$className}.php}";}
As an aside, I think you only need to require() inside your __autoload() function, rather than require_once(), since your __autoload() function is only called if it has not already been loaded.
[Edit: removed incorrect relative path suggestion - w3d spotted the real problem. Leaving the rest here just for info]
Also you can change the require_once in the autoload function to just require - by definition the function will only run if the class has not already been included.
You could greatly simplify your autoload by utilising the include path, as then PHP would check the different locations for you. E.g. something like this:
set_include_path(
realpath('./specific/php') . PATH_SEPARATOR .
realpath('./../shared') . PATH_SEPARATOR .
get_include_path()
);
function __autoload($className) {
require "$className.php";
}

Categories