Php abstract class site configuration - php

i have a config class which is an abstract class. I would like to set it up so it automatically detects which server the site is on and then assigns appropriate constants. I get an error on line ten $this->hostName = $_SERVER['SERVER_NAME']; expecting `T_FUNCTION.
What is the correct way to do this and is there a better way to do this? Here is the first part of my class
abstract class config{
public $hostName;
public $hostSlices;
public $domain;
echo $_SERVER['SERVER_NAME'];
//strips out the "www" from the server name but only if it has the name on it .
$this->hostName = $_SERVER['SERVER_NAME'];
$this->hostSlices = explode(".",$this->hostName);
if($this->hostSlices[0]=="www"){array_shift($this->hostSlices);}
$this->domain = join(".",$this->hostSlices);
//depending on which domain is used, different config setup is used.
switch ($this->domain){
case "localhost":*/
const HOST = "localhost";//would http://localhost/ work as well. In that case, then this and the SITE_ROOT could be the same variable and i would preferentially set them depending on the host that the site is on.
const USER = "root";
const PWD = "xxxxxxx";
const NAME = "hurunuitconz";//database name
//public $name = "hello from the config class";//you cannot access variables from an abstract class you should define constants and then the can be used anywhere
###########Location of file groups########
const SITE_ROOT = "http://localhost";
const ADMIN_IMAGES = 'http://localhost/images/user_images/admin_images';
break;
case "charles.hughs.natcoll.net.nz":
const HOST = "charles.hughs.natcoll.net.nz";//would http://localhost/ work as well. In that case, then this and the SITE_ROOT could be the same variable and i would preferentially set them depending on the host that the site is on.
const USER = "charles_andrew";
const PWD = "xxxxxxx";
const NAME = "charles_hurunuitconz";//database name
###########Location of file groups########
const SITE_ROOT = "http://charles.hughs.natcoll.net.nz/_Assignments/Industry/www";//this is just confusing the way natcoll makes us do this.
const ADMIN_IMAGES = 'http://charles.hughs.natcoll.net.nz/_Assignments/Industry/www/images/user_images/admin_images';
break;
}

An abstract class shouldn't allow you to set private data (only an inherited concrete class).
Also, take a look at this link in stackoverflow for an interesting discussion on SERVER_NAME vs. HTTP_HOST

You have to wrap all that code in a constructor or better yet a function called init() or somthing. Then when you override init in the child classes you would call parent::init(). Did you mean to make this class static, not abstract?

The way you're structuring your code is just not right. PHP does allow for many crazy things, but defining constants and outputting code as a part of an abstract class makes no sense whatsoever in terms of OOP.
What you probably mean to do is to have a helper class that defines configuration settings based upon the local server name. To do so, you have a couple options:
Option 1) Create a regular class with a constructor.
class Config {
public $x;
public $y;
public function __construct() {
switch (...) {
$this->x = 2;
$this->y = 3;
}
}
}
And use it like this:
$config = new Config();
echo "Variable y: " . $config->y;
Option 2) Static method in an abstract class.
abstract class Config {
public $boolInitialized = false;
public static function init() {
if (self::$boolInitialized) {
return;
}
self::$boolInitialized = true;
switch (...) {
self::$x = 1;
self::$y = 2;
}
}
public static function getX() {
self::init();
return self::$x;
}
}
And use it like this:
echo Config::getX();

You cant output something in a class without declaring first a method
this will fail
abstract class fo
{
public $fo;
echo $fo;
}
**but this will work**
abstract class fo
{
public $fo;
public function __construct()
{
$this->fo = $_SERVER['SERVER_NAME'];
}
public function sayFo()
{
echo $this->fo;
}
}

Related

PHP instanceof and abstract class

I have an abstract class like this :
<?php
abstract class NoCie {
const SC = 01;
const MTL = 02;
const LAV = 03;
}
?>
I would like to test if a variable $x contain value from this abstract class only.
For now i used $x instanceof NoCie but this is not working probably because this class is abstract and can't be instantiated.
Here is the code that i'm trying to use to validate.
class CustomersTaxes
{
public $NoCie;
private $_file;
public function __construct($file)
{
$this->_file = $file;
}
public function CheckValidAndWrite()
{
$error = false;
//Numéro de compagnie
if (!($this->NoCie instanceof NoCie)) {
$error = true;
}
}
}
Here is my code that instantiate this class :
$t = new CustomersTaxes($_SERVER['DOCUMENT_ROOT'] . '/test.xlsx');
$t->NoCie = NoCie::SC;
$t->NoClient = "d";
$t->CheckValidAndWrite();
How can i do that?
I think you are confusing two concepts, but maybe what you want can be achieved in some other way. The only thing I can think of right now is to use PHP method type-hinting. But I would refactor slightly, making the NoCie property protected to be manipulated only by a getter and a setter. Like this:
class CustomersTaxes
{
private $NoCie;
private $_file;
public function __construct($file)
{
$this->_file = $file;
}
public function getNoCie()
{
return $this->NoCie;
}
public function setNoCie(NoCie $NoCie)
{
$this->NoCie = $NoCie::VALUE;
}
}
You still need a class that extends the abstract one, though, otherwise it'll never work:
class SCA extends NoCie
{
const VALUE = '01';
}
Since the NoCie property on CustomersTaxes is private, you have to set it a bit differently:
$t = new CustomersTaxes($_SERVER['DOCUMENT_ROOT'] . '/test.xlsx');
$t->setNoCie(new SCA());
// ...
That way you can make sure that whenever a NoCie property is set, it will be the class you want. No need to validate -- if setNoCie is triggered by an invalid value, it'll throw an exception.
I figured out another way to do this job without type hinting. Type hinting seem to be a good way but need to much files to work with psr-4 autoloader.
My choice is to use ReflectionClass to get all constant as array and compare value from $this->SC.
$NoCieReflection = new \ReflectionClass('\\Ogasys\\Enum\\NoCie');
if (!in_array($this->NoCie, $NoCieReflection->getConstants())) {
$error = true;
array_push($msg, "# de compagnie invalide");
}

PHP - disabling classes that are only needed in development

I am writing a small script in PHP and am using a Profiler for the development zone to see which functions/actions are slow etc.
$this->profiler = new \Fabfuel\Prophiler\Profiler();
Then I am using it in different methods all over the place (passing it via DI, using League\Container\Container class):
$profilerSeg = $profiler->profilerStartSegment('Page Load','CMS');
...
$profiler->profilerStopSegment($profilerSeg);
Problem is, I only want to use this in development. Thought about an IF statement:
if($this->environment === 'DEV')
$profilerSeg = $profiler->profilerStartSegment('Page Load','CMS');
...
if($this->environment === 'DEV')
$profiler->profilerStopSegment($profilerSeg);
but it looks ugly to have it everywhere. Then I thought about making a "fake profiler" that gets passed if the script is in production so all the calls would return NULL.
What is the best way to handle such a case: a class needed only in development but that should not be loaded in production?
Typical oop uses inheritance
Most approaches define a root class that all (or most) other classes extend
Class main {
private $profiler;
public __construct(){
$this->profiler = new \Fabfuel\Prophiler\Profiler();
// you can comment and uncomment the above line.
}
public profStart(){
if (!empty($this->profiler)) {
$this->profiler->profilerStartSegment($a,$b);
}
}
}
Class someThing Extends main {
// $profiler is already set as part of the constructor
$this->profStart('someThing','strange');
}
Class otherThing Extends someThing {
// but if you want a constructor, you have to daisy-chain the class constructors
public __construct() {
parent::__construct();
}
}
Alternately, swap out an empty object
...but this is generally considered bad practice
Class deadendObject {
public __get($var){}
public __set($var,$val){}
public __call($var,$args){}
// see: http://php.net/manual/en/language.oop5.magic.php
}
if ($profileMe) {
$this->profiler = new \Fabfuel\Prophiler\Profiler();
} else {
$this->profiler = new deadendObject();
}
Set whether to do stuff in the Profiler object itself
Class Profiler {
public $enabled = true;
public function doSomething(){
if($this->enabled) {
// do stuff
}
}
}
$profiler = new \Fabfuel\Prophiler\Profiler();
$profiler->enabled = false;
Best is a combination of inheritance, and having the profiler handle behavior changes.
Class Profiler {
public $enabled = true;
public function doSomething($var = "unknown"){
if($this->enabled) {
// do stuff
}
}
}
Class main {
public $profiler;
public __construct(){
$this->profiler = new Profiler();
$this->profiler->enabled = true;
// better still would be to define this behavior according to a settings file, or environment variables with getenv()
}
}
Class someThing Extends main {
// $profiler is already set as part of the constructor
$this->profiler->doSomething('neighborhood');
}
I ain't afraid 'o no ghosts!

Variable not being picked up

In my config.php file I have a variable that is set to 'localhost'.
$CONFIG['MySQLi']['host'] = "localhost";
However, when I include this config.php in my database class, I test it by calling the variable in an echo through the __construct() method
public function __construct() {
echo $CONFIG['MySQLi']['host'];
}
But then for some reason, I get this error:
Notice: Undefined variable: CONFIG in C:\xampp\htdocs\Muse\classes\class.database.php on line 15
However I get no errors for importing the config.php file. Would someone be able to explain why this is happening? Thankyou
The function doesn't know about variables that were defined outside due to variable scope.
public function __construct() {
global $CONFIG;
}
should resolve this. However, this is usually considered bad practice.
Alternatively you can use static attributes as shown by Kohjah Breese, pass the config array to the constructor (as suggested by AlexP) or use a construct like the following.
/config/mysqli.php
<?php
return array(
//what now is $CONFIG['MySQLi']
);
and in the function
public function __construct() {
$config = include '/config/mysqli.php';
}
For anybody who still wants the answer to this question, another good way to do it is by DEFINING a variable.
define('VARIABLE', 'VALUE');
And then call it by doing VARIABLE. E.g.
<?php echo VARIABLE; ?>
AS above, function do not have access to standard variables stored outside of them, but a better solution is to create a class you want to store global variables in. I use something like this:
class Conf
{
// Project
static $CODE = 'F';
static $NAME = 'For';
static $ACCESS = 'public';
static $CHARSET = 'utf-8';
static $DATA = array();
static $CACHE = false;
static $HTMLINDENT = true;
// Diagnostic
static $SHOWEXECTIME = true;
// Paths
static $PATH_FILESYSTEM = '';
static $PATH_CORE = '/var/www/sites/core';
static $PATH_DOMAIN = 'localhost';
static $PATH_URL = 'http://localhost/sites/for/';
static $PATH_CACHE = 'cache/';
static $PATH_CSS = 'css/';
static $PATH_DATA = 'data/';
static $PATH_JS = 'js/';
static $PATH_LOG = 'logs/';
static $PATH_XML = 'xml/';
static $PATH_XSL = 'xsl/';
// DB Details
static $DB_USER = 'root';
static $DB_PASS = 'pass';
static $DB_DSN = 'mysql:host=localhost;dbname=for;charset=utf8';
}
My tests showed this to be the quickest solution. Some people use constants, which are very slow. Globals have been depreciated, and are a security risk.
You can access any of these vars from anywhere in PHP using Conf::$NAME; etc.

Design nightmare with PHP

I've been trying for a long time now to find a correct design using PHP to achieve what I want, but everything I've tried failed and I'm guessing it's probably because I'm not looking from the right angle, so I wish some of you can enlighten me and give me some good advice!
The design might seem a little weird at first, but I assure you it's not because I like to make things complicated. For the sake of simplicity I'm only giving the minimal structure of my problem and not the actual code. It starts with these:
<?php
// ------------------------------------------------------------------------
class Mother_A
{
const _override_1 = 'default';
protected static $_override_2 = array();
public static function method_a()
{
$c = get_called_class();
// Uses $c::_override_1 and $c::$_override_2
}
}
// ------------------------------------------------------------------------
class Mother_B extends Mother_A
{
public function method_b()
{
// Uses self::method_a()
}
}
Class Mother_A defines a static method that uses constants and statics to be overridden by children. This allows to define a generic method (equivalent of a "template" method) in the derived class Mother_B. Neither Mother_A or Mother_B are intended to be instanciated, but Mother_B should not be abstract. This exploits Late Static Binding, which I find very useful btw.
Now comes my problem. I want to define two classes, in n distinct 'situations' (situation 1, situation 2, etc):
<?php
// ------------------------------------------------------------------------
class Child_A_Situation_k extends Mother_A
{
// Uses method_a
}
// ------------------------------------------------------------------------
class Child_B_Situation_k extends Mother_B
{
// Uses method_a and method_b
}
Of course I'm not actually giving these stupid names; both classes have different names in each situation, but both follow the same derivation pattern from Mother_A and Mother_B. However, in each individual case ('situation'), both classes need the exact same constants/static override, and I don't know how to do that without duplicating the override manually in both classes.
I tried many things, but the closest I got was to implement an interface Interface_Situation_k that defined constants and statics for the situation k, and make both children implement this interface. Of course, you can't define statics in an interface, so it failed, but you get the idea. I would have traded the interface for a class, but then there's no multiple inheritance in PHP, so it's not valid either. :/ I'm really stuck, and I can't wait to read a possible solution! Thanks in advance!
this is the best i can do, i don't think there is a way to do it with less code.
Look at the comments inside the code for more info.
Fully working code:
<?php
class Mother_A
{
// you're using '_override_1' as a variable, so its obviously not a constant
// also i made it public for the setSituation function,
// you could keep it protected and use reflections to set it
// but i dont really see a reason for that.
// if you want that, look up how to set private/protected variables
public static $_override_1 = 'default';
public static $_override_2 = array();
public static function method_a()
{
$c = get_called_class();
var_dump($c::$_override_1);
var_dump($c::$_override_2);
// Uses $c::_override_1 and $c::$_override_2
}
public static function setSituation($className)
{
$c = get_called_class();
// iterate through the static properties of $className and $c
// and when the you find properties with the same name, set them
$rBase = new ReflectionClass($c);
$rSituation = new ReflectionClass($className);
$staBase = $rBase->getStaticProperties();
$staSituation = $rSituation->getStaticProperties();
foreach($staSituation as $name => $value)
{
if(isset($staBase[$name])) $c::$$name = $value;
}
}
}
// ------------------------------------------------------------------------
class Mother_B extends Mother_A
{
public function method_b()
{
self::method_a();
}
}
class Situation_k
{
public static $_override_1 = 'k';
public static $_override_2 = array('k','k');
}
class Child_A_Situation_k extends Mother_A { }
Child_A_Situation_k::setSituation('Situation_k');
// This is not as short as writing 'extends Mother_A, Situation_k'
// but i think you wont get it shorter
class Child_B_Situation_k extends Mother_B { }
Child_B_Situation_k::setSituation('Situation_k');
echo '<pre>';
Child_A_Situation_k::method_a();
echo "\n";
Child_B_Situation_k::method_a();
echo "\n";
Child_B_Situation_k::method_b();
echo "\n";
echo '</pre>';
?>

Change class, private or public string

There is a php class in which I like to change the variable, but I can't make it happen.
The Class:
class ShopCart
{
private $maincurrency = 'USD';
private function set_Currency() {
$maincurrency = 'GBP';
return $maincurrency;
}
}
This doesn't work. Even if I make it public. What am I doing wrong?
You have to use $this->maincurrency in the body of your method. Your current code creates and sets local variable, not a member.
You need $this:
class ShopCart {
private $maincurrency = 'USD';
private function set_Currency() {
$this->$maincurrency = 'GBP';
return $this->$maincurrency;
}
}
Otherwise you're creating a new variable local to the function and just using that.
The manual does actually tell you this already:
Within class methods the properties, constants, and methods may be
accessed by using the form $this->property (where property is the name
of the property) unless the access is to a static property within the
context of a static class method, in which case it is accessed using
the form self::$property.
The documentation is your friend; consult it before asking here please.
You may also want to consider not returning anything from a setter, though that's up to you. There are advantages to doing so, even if it's not all that conventional in PHP.
class ShopCart {
private $maincurrency = 'USD';
private function setCurrency() {
$this->maincurrency = 'GBP';
}
}
change $maincurrency = 'GBP'; to $this->maincurrency = 'GBP';,
and also return $this->maincurrency;

Categories