Strange trait behavior in PHP - php

Consider the following. I have 4 files.
sub.php
<?php
class sub extends main {
function __construct() {
parent::__construct();
echo "constructor in sub<br>";
}
}
trait.php
<?php
trait t1 {
function tProcess() {
echo "in tprocess in trait<br>";
}
}
main1.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
require_once 'sub.php';
require_once 'trait.php';
class main {
function __construct() {
echo "constructor in main<br>";
}
function process() {
echo "doing something in main<br>";
}
}
$t = new sub();
$t->process();
and main2.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
require_once 'sub.php';
require_once 'trait.php';
class main {
use t1;
function __construct() {
echo "constructor in main<br>";
}
function process() {
echo "doing something in main<br>";
}
}
$t = new sub();
$t->process();
main1 works as expected, but main2 gives me a Fatal error: Class 'main' not found error. Just including the trait is changing something in the behavior of how the file inclusions work.

Yup, it is just an include ordering issue. This is one of the countless reasons people use the autoloader.
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
require_once 'trait.php';
class main {
use t1;
function __construct() {
echo "constructor in main<br>";
}
function process() {
echo "doing something in main<br>";
}
}
require_once 'sub.php';
$t = new sub();
$t->process();

Related

Require has failed in php

I'm new to PHP, I'm trying to require UserController.php from Controller.php but all I get is "HTTP ERROR 500" in browser. What's going on here?
Controller.php
class Controller
{
public function __construct()
{
}
public function call(){
// echo 1;
require_once "../Controllers/UserController.php";
}
}
UserController.php
class UserController
{
public function __construct()
{
echo '111111111';
}
public function hi(){
echo '1';
}
}
$a = new UserController();
$a->hi();
Class definitions can't be nested inside functions or other classes. So you shouldn't have that require_once line inside a function definition. Move it outside the class.
require_once "../Controllers/UserController.php";
class Controller
{
public function __construct()
{
}
public function call(){
// echo 1;
}
}
<?php
require_once "../Controllers/UserController.php";
class Controller
{
public function __construct()
{
}
public function call(){
// echo 1;
$a = new UserController();
$a->hi();
}
}

Why I am getting "Cannot redeclare class" error?

I have Apache running on port 81. My project folder is MyPhpProject. Inside it I have 2 folders: Domain and Testing.
In Domain folder I have 3 PHP files:
BaseDomain.php which contains an abstract class BaseDomain
Location.php which contains a concrete class Location inherited from BaseDomain
Employee.php which contains a concrete class Employee inherited from BaseDomain
Employee class has a reference of Location class.
This is the BaseDomain.php:
<?php
abstract class BaseDomain {
}
?>
This is the Location.php:
<?php
$returnRequire = require 'BaseDomain.php';
class Location extends BaseDomain {
private $locationIdInt;
private $codeNameString;
private $descString;
public function setLocationId($locationId) {
$this->locationIdInt = $locationId;
}
public function getLocationId() {
return $this->locationIdInt;
}
public function setCodeName($codeName) {
$this->codeNameString = $codeName;
}
public function getCodeName() {
return $this->codeNameString;
}
public function setDesc($desc) {
$this->descString = $desc;
}
public function getDesc() {
return $this->descString;
}
}
?>
This is Employee.php:
<?php
$returnRequire = require 'BaseDomain.php';
class Employee extends BaseDomain {
private $employeeIdString;
private $locationObject;
public function setEmployeeId($employeeId) {
$this->employeeIdString = $employeeId;
}
public function getEmployeeId() {
return $this->employeeIdString;
}
public function setLocation($location) {
$this->locationObject = $location;
}
public function getLocation() {
return $this->locationObject;
}
}
?>
Now in the Testing folder I created a Test_Employee.php and this is its code:
<?php
set_include_path('../Domain');
$getIncludePath = get_include_path();
echo "getIncludePath = " . $getIncludePath;
echo "<br>";
$returnRequire1 = require 'Location.php';
echo "returnRequire for Location.php = " . $returnRequire1;
echo "<br>";
$returnRequire2 = require 'Employee.php';
echo "returnRequire for Employee.php = " . $returnRequire2;
echo "<br>";
?>
When I try to run it http://localhost:81/MyPhpProject/Testing/Test_Employee.php I got a fatal error regarding cannot redeclare BaseDomain class. This is what I see in browser:
getIncludePath = ../Domain
returnRequire for Location.php = 1
Fatal error: Cannot redeclare class BaseDomain in C:\Program Files
(x86)\Apache Software
Foundation\Apache2.2\htdocs\MyPhpProject\Domain\BaseDomain.php on line
2
I have not created BaseDomain class more than once. So this error is bizarre. Can somebody please explain why I am getting error message? And how to fix it.
Thanks for your time.
The line $returnRequire1 = require 'Location.php'; loads Location.php, which in turns loads BaseDomain.php in the line $returnRequire = require 'BaseDomain.php';. Then, the line $returnRequire2 = require 'Employee.php'; loads Employee.php, which loads (again) BaseDomain.php (the line $returnRequire = require 'BaseDomain.php';). The second load of BaseDomain.php causes php to try to redefine the BaseDomain class, which is no allowed.
The easiest way to solve this problem is to change your require calls to require_once. This will ensure that each file is loaded exactly once per run, which will prevent the error you are experiencing.
BaseDomain.php:
<?php
abstract class BaseDomain {
}
?>
Location.php
<?php
class Location extends BaseDomain {
private $locationIdInt;
private $codeNameString;
private $descString;
public function setLocationId($locationId) {
$this->locationIdInt = $locationId;
}
public function getLocationId() {
return $this->locationIdInt;
}
public function setCodeName($codeName) {
$this->codeNameString = $codeName;
}
public function getCodeName() {
return $this->codeNameString;
}
public function setDesc($desc) {
$this->descString = $desc;
}
public function getDesc() {
return $this->descString;
}
}
?>
Employee.php:
<?php
class Employee extends BaseDomain {
private $employeeIdString;
private $locationObject;
public function setEmployeeId($employeeId) {
$this->employeeIdString = $employeeId;
}
public function getEmployeeId() {
return $this->employeeIdString;
}
public function setLocation($location) {
$this->locationObject = $location;
}
public function getLocation() {
return $this->locationObject;
}
}
?>
Test_Employee.php
<?php
set_include_path(__DIR__.'/MyPhpProject/Domain');
require 'BaseDomain.php';
$getIncludePath = get_include_path();
echo "getIncludePath = " . $getIncludePath;
echo "<br>";
$returnRequire1 = require 'Location.php';
echo "returnRequire for Location.php = " . $returnRequire1;
echo "<br>";
$returnRequire2 = require 'Employee.php';
echo "returnRequire for Employee.php = " . $returnRequire2;
echo "<br>";
?>

Include Extern Variable inside Method PHP

I have this code:
//config.php
$EXAMPLE['try1'] = "...." ;
$EXAMPLE['try2'] = "...." ;
So, i have another file with a php class:
class try {
public function __construct() {
if($this->try1() && $this->try2()){
return true;
}
}
public function try1(){
require_once 'config.php' ;
echo $EXAMPLE['try1'];
return true;
}
public function try2(){
require_once 'config.php' ;
echo $EXAMPLE['try2'];
return true;
}
}
But in my case, $EXAMPLE['try1'] is ..... , but $EXAMPLE['try2'] is null... why? I've tried to include require_once 'config.php' ; on top page, and add after global $EXAMPLE; , but $EXAMPLE is ever null, why?
Use require, not require_once. Otherwise, if you load the file in one function, it won't be loaded in the other function, so it won't get the variables.
It would be better to require the function outside the functions entirely. Then declare $EXAMPLE as a global variable.
require_once 'config.php';
class try {
public function __construct() {
if($this->try1() && $this->try2()){
return true;
}
}
public function try1(){
global $EXAMPLE
echo $EXAMPLE['try1'];
return true;
}
public function try2(){
global $EXAMPLE
echo $EXAMPLE['try2'];
return true;
}
}
Require your file inside __construct method. So require once requires file once in try1 method.
class try {
private $_example = array();
public function __construct() {
require_once 'config.php';
$this->_example = $EXAMPLE;
return $this->try1() && $this->try2();
}
public function try1(){
echo $this->_example['try1'];
return true;
}
public function try2(){
echo $this->_example['try2'];
return true;
}
}

using php include function for classes

Trying to get a hang of classes in php, trying to include carClass.php into new_file.php.
carClass.php
<?php
class carClass
{
private $color;
private $gear;
private $model;
private $gas;
function paintCar($carColor) {
$this->color = $carColor;
}
function findCarColor() {
echo "$color";
}
function shiftGear($newGear) {
$this->gear=$newGear;
}
function findGear() {
echo "$gear";
}
function chooseModel($newModel) {
$this->model = $newModel;
}
function findModel() {
echo"$model";
}
function fillCar($gasAmount) {
$this->gas = $gasAmount;
}
function lookAtGauge() {
echo "$gas";
}
}
?>
its just a bunch of getters and setters. Im trying to include this class to new_file.php
new_file.php
<?php
include("carClass.php");
$car = new carClass;
$car->chooseModel("Mustang");
$car->paintCar("black");
$car->shiftGear("5th");
$car->fillCar("half");
$car->findModel();
$car->findCarColor();
$car->findGear();
$car->lookAtGuage();
?>
When I try to execute this file I get these error messages
Warning: include(carClass.php): failed to open stream: No such file or directory in C:\xampp\htdocs\testFile\new_file.php on line 4
Warning: include(): Failed opening 'carClass.php' for inclusion (include_path='.;C:\xampp\php\PEAR') in C:\xampp\htdocs\testFile\new_file.php on line 4
Fatal error: Class 'carClass' not found in C:\xampp\htdocs\testFile\new_file.php on line 6
I believe both files are in testFile directory so I'm not sure whats going on. I appreciate any help you guys can give me as usual.
The include path is set against the server configuration (PHP.ini) but the include path you specify is relative to that path so in your case the include path is (actual path in windows):
<?php
include_once dirname(__FILE__) . '/carClass.php';
$car = new carClass;
$car->chooseModel("Mustang");
$car->paintCar("black");
$car->shiftGear("5th");
$car->fillCar("half");
$car->findModel();
$car->findCarColor();
$car->findGear();
$car->lookAtGuage();
?>
You can use PHP's auto loading feature which will automatically load a class when an object is created. If you have many classes then you can use it an header file so that you don't need to worry about using this include every time.
<?php
function __autoload($class_name) {
include $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
Try this:
<?php
class carClass
{
private $color;
private $gear;
private $model;
private $gas;
function paintCar($carColor) {
$this->color = $carColor;
}
function findCarColor() {
echo $this->color;
}
function shiftGear($newGear) {
$this->gear=$newGear;
}
function findGear() {
echo $this->gear;
}
function chooseModel($newModel) {
$this->model = $newModel;
}
function findModel() {
echo $this->model;
}
function fillCar($gasAmount) {
$this->gas = $gasAmount;
}
function lookAtGauge() {
echo $this->gas;
}
}
?>
//
<?php
include("carClass.php");
$car = new carClass;
$car->chooseModel("Mustang");
$car->paintCar("black");
$car->shiftGear("5th");
$car->fillCar("half");
$car->findModel();
$car->findCarColor();
$car->findGear();
$car->lookAtGauge();
?>

How call code within class function from require_once?

If I create a class that uses a variable defined in another php file that is included via require_once, I get the following outcomes:
If require_once is at the top of the class's php file and the variable is used in myclass->someFunction() it will throw the error: Undefined variable
If require_once is inside myclass->someFunction() it work once and thereafter throw the error: Undefined variable
How do I properly handle this?
Example showing the problem:
test.php
<?php
require_once( "holds_var.php" );
class T
{
function __construct()
{
$this->useVariable();
}
function useVariable()
{
echo $something;
}
}
$t = new T();
?>
holds_var.php
<?php $something = "I am something"; ?>
EXAMPLE 2 (uses the same "holds_var.php" ):
test.php
<?php
class T
{
function __construct()
{
//This is ok
$this->useVariable();
//This throws an error
$this->useVariable();
}
function useVariable()
{
require_once( "holds_var.php" );
echo $something;
}
}
$t = new T();
?>
Use global keyword:
function useVariable()
{
global $something;
require_once( "holds_var.php" );
echo $something;
}
Sounds like global could help your case.
http://us3.php.net/manual/en/language.variables.scope.php
holds_var.php
<?php
$something = "I am something";
global $something;
?>
test.php
<?php
require_once( "holds_var.php" );
class T
{
function __construct()
{
//This is ok
$this->useVariable();
//This throws an error
$this->useVariable();
}
function useVariable()
{
global $something;
echo $something;
}
}
$t = new T();
?>
How does the above code work out for you?

Categories