To begin, here is the flow so you can understand the problem. I have four files, three of these are classes, I use two namespaces.
login.php is a form, when the form is submited, it comes back to itself and the code below is executed. The login.php calls the Zcrypt::Decrypt and Zcrypt::Encrypt with out issues. the Login::DoLogin(); is also called inside the login.php file.
In the Login.class.php (where DoLogin lives) file I create a new instance of DB, and can call Zcrypt::Decrypt with out error. In Login.class.php I call dbConnect();
In the DB.class.php (where dbConnect lives) file I am unable to call Zcrypt::Decrypt. It gives me a syntax error or that it can not find Zcrypt. I have tried Zcrypt::Decrypt([string]), \Zcrypt::Decrypt([string]), and even \Zcrypt::Decrypt([string]).
The question is, how come I can call Zcrypt in some classes but not others? Im I missing some code for this to work?
Here are my files
login.php:
require 'NS/helpdesk/Login.class.php';
require 'NS/helpdesk/Cryptv2.class.php';
require 'NS/helpdesk/DB.class.php';
use \net\[domain]\Zcrypt;
use \net\[domain]\helpdesk\Login;
#check to see if the form was submited and that the values are equal.
{
if (strlen($_POST['hvalue']) > 1 && $_SERVER['REMOTE_ADDR'] == Zcrypt::Decrypt($_POST['hvalue']) )
{
Login::DoLogin(); ###### This is where I call my static Login Class
}
else {
echo "bad form";
}
}
Login.class.php
namespace net\[domain]\helpdesk;
use \net\[domain]\helpdesk\DB;
use \net\[domain]\Zcrypt;
class Login
{
public function DoLogin()
{
#call to the database class to open the db
$DB = new DB();
$DB->dbConnect();
#This is to show I can call Zcrypt in this class (note, no \) and it works.
echo $dbPass = Zcrypt::Decrypt("[coded string]");
}
}
DB.class.php
namespace net\[domain]\helpdesk;
use \net\[domain]\Zcrypt;
class DB
{
public $dbHost = '[address]';
public $dbUser = '[un]';
public $dbPass = '[pw]';
######The two commented out lines below will not run. I get a syntax error
# public $dbPass = \Zcrypt::Decrypt("[strint]");
# public $dbPass = Zcrypt::Decrypt("[string]")
public $dbName = '[name]';
public $db;
public function __construct(){}
public function dbConnect()
{
[code]
}
}
Cryptv2.class.php
namespace net\[domain];
use Exception;
class Zcrypt
{
public static function Encrypt($i)
{
[code]
}
public static function Decrypt($i)
{
[code]
}
}
Thanks for your help.
It's syntax error. You cannot use expressions in property definition.
This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.
http://php.net/manual/en/language.oop5.properties.php
You would have to use \net\[domain]\Zcrypt:: for this to work. Or better yet assign an alias like use \net\[domain] as z, then z\Zcrypt::. In other words see the PHP manual http://php.net/manual/en/language.namespaces.php . Find file4. It has the example you need.
Related
I have the following code:
File: class.engine.php (The Main Engine of the website)
<?php
namespace Core;
class Engine {
}
File class.errors.php (The Error trigger if something happens, customized errors)
<?php
namespace Core\Errors;
class Errors {
public function TrigerError($e)
{
die($e);
}
}
File class.mysqli.php (The database connector)
<?php
namespace Core\MySQLiDrv;
class MySQLiDrv {
public $db = null;
public function __construct($database) {
$connector = mysqli_connect($database[0], $database[1], $database[2], $database[3]);
if(!$connector)
{
return new TrigerError("1");
}
}
}
File index.php (Where everything runs)
<?php
include("engine/class.engine.php");
include("engine/class.errors.php");
include("engine/class.mysqli.php");
$engine = new Engine();
$db = new MySQLiDrv(array("localhost", "user", "pass", "db"));
I want to extend Engine class with many multiple files and I want them to be in namespace, how can I do that properly, because I can't trigger the error in this case of the code.
And is it important in this case of code to use namespaces defined as something for easy use?
Your main issue as I see it is the lack of the USE statement and the fact that TrigerError is a method and not a class.
To fix these:
namespace Core\MySQLiDrv;
use Core\Errors\Errors;
class MySQLiDrv {
public $db = null;
public function __construct($database) {
$connector = mysqli_connect($database[0], $database[1], $database[2], $database[3]);
if(!$connector)
{
return (new Errors)->TrigerError("1");
}
}
}
Full working code:
namespace Core{
class Engine {
}
}
namespace Core\Errors{
class Errors {
public function TrigerError($e)
{
die($e);
}
}
}
namespace Core\MySQLiDrv{
use Core\Errors\Errors;
class MySQLiDrv {
public $db = null;
public function __construct($database) {
//$connector = mysqli_connect($database[0], $database[1], $database[2], $database[3]);
//if(!$connector)
//{
return (new Errors)->TrigerError("1");
//}
}
}
}
//default global namesapce
namespace {
use Core\Engine;
use Core\MySQLiDrv\MySQLiDrv;
$engine = new Engine();
$db = new MySQLiDrv(array("localhost", "user", "pass", "db"));
}
Output
1
Sandbox
The only real difference here is that when you use multiple namespaces in a single file (sandbox) you have to enclose the code with {}. You can remove those if these are separate files. Well that and I cant use the DB functions in the sandbox, but that is irrelevant in this example because we want to trigger the error.
However as said in the comments, I would look into Autoloading and Exceptions both of which will help you here.
I have an autoloader on github you can play around with if you want, it's similar to what Composer uses/does. Composer is just more standardized.
Autoloadig basically uses a combination of the namespace and class to find the file at run time (when the class is instantiated). So there are some naming conventions to be aware of, for example take your class Core\Errors\Errors this should be located in Core/Errors/Errors.php The namespace and the file path should be the same. What this does is you can eliminate all the include statements and this loads the files only when needed auto-magically.
Alright I have a few classes and I'm wanting to pass on an initiated class object but I keep getting errors. It'll work one time, then other times I'll get a
PHP Fatal error: Cannot redeclare class
I don't know what I'm doing wrong. I'm basically trying to clean up my code because I'm ALWAYS having 2-3 includes for every one of my pages. I'd rather just include one class and pass on or use the other classes instances from there. Here's an example of what I have now:
Manage.php - Main Class
<?php
include_once('/path/to/DB.php');
class Manage {
public $db;
public function __construct() {
$this->db = new DB($host,$dbName,$user,$pass);
//other constructor stuff
}
//other functions
}
DB.php - Helper Class
<?php
class DB {
public $conn;
public function __construct($host = false, $db = false, $user = false, $pass = false) {
//connect to database
}
//functions for interacting with the database (get,query,update,insert, etc)
}
UseOfClass.php - Shows how I'd like to use it
<?php
include('/path/to/Manage.php');
$manage = new Manage();
$results = $manage->db->get('table_name');
print_r($results);
I have a PHP class with a few functions defined, this class is responsible for database access:
class database {
function open($params) {
// code here to open the db
}
function close() {
// code here to close the db
}
function count_users() {
// code here counts the number of user records
// Return -1 for testing
return -1;
}
function insert_user($user) {
// code here inserts a user record
}
function select_user($user_id) {
// code here selects a user record
}
}
I have accessor classes defined as follows:
require_once("database.php");
class user {
public $user_id;
public $email_address;
// etc, etc
}
class db_user {
static function select_user($user_id) {
$db = new database();
$db->open();
$user = NULL;
$result = $db->select_user($user_id);
// Test the result and decode user record into $user, etc
$db->close();
return $user;
}
static function count_users() {
$db = new database();
$db->open();
$count = $db->count_users();
$db->close();
return $count;
}
}
My issue occurs when I attempt to count the number of users through db_user::count_users(); which always fails with a Fatal Error: call to undefined method database::count_users
If I dump the database class methods using get_class_methods, I can see that the count_users function isn't present in the list but I have no idea why.
I'm very much a PHP n00b so there maybe something really obvious I'm not doing. My db_user and user classes have many other functions which pull data back through the database class and all of these succeed - just this one function.
Please help!
UPDATE
Ok, so, having removed a couple of functions from the database class and re-uploaded the file to the live server, it appears that it is somehow being "cached" as when I dump the methods belonging to the database object, the removed methods are still displayed in the list.
The count_users function is also not present in the method list yet when I inspect the file uploaded to the server, it is there in code.
Is there any way of removing this caching???
Try as follows:
class user extends database {
//code user class goes here
}
or
class user extends db_user {
//code user class goes here
}
simple problem solved.
You can store you instance of Database to the variable.
class db_user {
public static $db;
static function openDatabase(){
self::$db = new database();
self::$db->open();
}
static function select_user($user_id) {
$user = NULL;
$result = self::$db->select_user($user_id);
// Test the result and decode user record into $user, etc
self::$db->close();
return $user;
}
static function count_users() {
$count = $db->count_users();
self::$db->close();
return $count;
}
}
The issue, it would appear, is related to another version of the "database.php" file hiding in a sub-folder which must have been copied there by mistake.
Having removed this troublesome file, all now works as expected.
Thanks for your help.
Tried running your code in on-line phptester tool - first complained about missing $params in $db->open(), removing the argument (or passing the $params) it works fine on php 5.2,5.3,5.4. No complaints about count_users().
I have a php project that uses some functional elements, and some OOP elements, but it seems mixing the two is causing problems. Here are the files that are causing the errors:
DB.php
<?php
function parse_db_entry($from, &$to){
//Function code here
}
?>
User.php
<?php
require_once 'DB.php';
class User{
//Properties
public function __construct(){
//ctor
}
public static function load_user($email, $password){
$entry = //Make MySQL Request
$user = new User();
parse_db_entry($entry, $user);
return $user;
}
}
?>
Everything works as it should, except the call to parse_db_entry which throws:
Fatal error: Call to undefined function parse_db_entry()
I am able to access other things in DB.php, for instance if I made a class it there I am able to instantiate it without error, and if I move the function into User.php, it is functional as well. So what am I doing wrong? Why can't I call this method?
I've figured it out! Thanks to everyone who had ideas, but it seems the problem was something else.
When calling require_once 'DB.php', php was actually getting the file:
C:\xampp\php\pear\DB.php
instead of mine.
This may be a problem exclusive to XAMPP, but a simple rename of my file to DBUtil.php fixed everything.
This is a stretch, and I'm totally taking a shot in the dark here, but...
Are you sure parse_db_entry is in the global or User's namespace?
Note: I added a few lines here and there for testing/debugging.
DB.php:
<?php
namespace anotherWorld; // added this ns for illustrative purposes
function parse_db_entry($from, &$to){
echo 'called it';
}
?>
User.php:
<?php
namespace helloWorld; // added this ns for illustrative purposes
class User {
//Properties
public function __construct(){
//ctor
}
public static function load_user($email, $password){
$entry = //Make MySQL Request
$user = new User();
parse_db_entry($entry, $user);
return $user;
}
}
?>
test.php:
<?php
require_once 'DB.php';
require_once 'User.php';
use helloWorld\User;
$a = new User();
$a->load_user('email','pass');
echo 'complete';
?>
Yields Fatal error: Call to undefined function helloWorld\parse_db_entry() in User.php on line 13, however when removing the NS declaration in DB.php (namespace anotherWorld) thereby putting parse_db_entry in global NS it runs just fine.
To verify, use the __NAMESPACE__ constant.
If namespace is a problem, without compromising DB's namespace, here is an updated User.php:
<?php
namespace helloWorld;
use anotherWorld; // bring in the other NS
class User {
//Properties
public function __construct(){
//ctor
}
public static function load_user($email, $password){
$entry = //Make MySQL Request
$user = new User();
anotherWorld\parse_db_entry($entry, $user); // call the method from that NS
return $user;
}
}
?>
i have 2 classes
for DB
for language
i want to use my language things in the DB
so it outputs the result
ex :
class db_control{
var $db_connection, $lang_var;
//create the function for the connection
function db_connect(){
//define some variables
global $db_host, $db_username, $db_password, $db_name, $lang_var;
$this->db_connection = mysql_connect("$db_host","$db_username","$db_password")or die("can't connect to server with these informations");
//checl that the connection is established
if($this->db_connection){
echo $lang_vars->getvar("$langvals[lang_con_est]");
}
but this
$lang_vars->getvar("$langvals[lang_con_est]");
doesn't work
i mean it outputs many problems
and am sure my problem is that i didn't define my variables and classes correctly
P.S : the language class is in file called language.php and this part is in DB.MySQL.php
EDIT :
this is the language class
class lang_vars{
public static function getvar($variable){
return $variable;
}
}
i want the DB class to display text from the language class
thats why i used
echo $lang_vars->getvar("$langvals[lang_con_est]");
but it doesn't work
cuz when i declare the language class
$lang_vars = new lang_vars;
inside the db_control it shows error unexpected T_something expected T_Function
and when i declare it outside nothing up
hope i made things more clear now
Any reason why you are still using PHP4 syntax?
When creating an instance of the db_control class, pass the object to be stored as $lan_var into the constructor or set it via a dedicated setter. See Dependency Injection.
class DBControl
{
protected $_lang;
public function __construct($lang = NULL)
{
if($lang !== NULL) {
$this->_lang = $_lang;
}
}
public function setLang($lang)
{
$this->_lang = $lang;
}
}
Then do either
$dbControl = new DBControl(new LangThing);
or
$dbControl = new DBControl;
$dbControl->setLang(new LangThing);
Also, get rid of the globals. Pass those in via Dependency Injection too.
Make your language class methods static . Read more here.
class LangClass
{
public static function getvar()
{
// your code here
}
}
Then, you can use its functions without creating objects like this:
$LangClass::getvar("$langvals[lang_con_est]");
This can do the trick.
$lang_vars = new LanguageClassOrWhateverItIsCalled();
$lang_vars->getvar($langvals[lang_con_est]);
But maybe you should think of making it a static method. In that case you can call it with:
LanguageClassOrWhateverItIsCalled::getVar($langvals[lang_con_est]);
You can define the method static like:
public static function getVar() {
// Do something
}
Edit: #SAFAD
You should use the static method for this. To make this work, be sure your class language.php is loaded. To do so just add in the DB.MYSQL.php file the following line:
require_once('language.php');
class db_control {
...
Make sure you have the right path to the language.php file.
Then you should call the method in db_control class like this:
if($this->db_connection){
echo lang_vars::getvar("$langvals[lang_con_est]");
}
Besides, what is the use of a function like this? You should either do:
if($this->db_connection){
echo $langvals[lang_con_est];
}
or change your static getvar method to:
public static function getvar($variable){
return $langvals[$variable];
}
and your function call to:
if($this->db_connection){
echo lang_vars::getvar("lang_con_est");
}