I need to instance 2 or more classes on top of my controller class, so I can use them with $this->filter or $this->logger_instance inside any method of my controller class. Right now it is not letting me, I get an error. (I do not want to extend the class if possible.) Is it okay to instance in construct if it is possible.
Parse error: syntax error, unexpected T_NEW in controller.php
(I am in the process of transferring my coding habits from procedural to OOP so I am really bad at it.)
class ID_Controller
{
public $input;
public $register_attempt = 2;
public $maximum_attempts = 3;
public $log_data_attempts = 2;
public $query_log_file_path;
public $sql_filtering = true;
public $xss_filtering = true;
public $sql_register_attempt = 3;
public $xss_register_attempt = 6;
public $filter = new ID_Algorithm;
public $logger_instance = new ID_Logger;
function __construct()
{
}
}
Why not try initializing these classes through the __construct() method?
/*
If the two classes are located in seperate files, be sure to require them:
*/
require("ID_Algorithm Page");
require("ID_Lodder Page");
class ID_Controller {
/* previous lines here */
/*
Comment out the next two lines and initiate them within the construct class
*/
// public $filer = new ID_Algorithm;
// public $logger_instance;
public $filer;
public $logger_instance
public function __construct(){
$this->filter = new ID_Algorithm;
$this->logger_instance = new ID_Logger;
}
}
Then when calling:
$Class = new ID_Controller();
this will set the necessary internal pointers correctly.
Related
Im trying to create a class extending GearmanClient so i can centralize and use gearman across my app according to my own specifications. One of the reasons im doing my own class is to store easily failed tasks into a database so they can be later processed again.
Im getting a basic error
Warning: GearmanClient::runTasks():
_client_run_task(GEARMAN_NO_SERVERS) no servers added -> libgearman/run.cc:66 in /var/www/html/app/forecast/Forecast.php on
line 37
<?php
namespace app\service;
use helpers\Config_helper;
use \GearmanClient;
class Gearman_service extends GearmanClient
{
public $client;
private $servers = array();
private $tasks = array();
private $completedTasks = array();
private $failedTasks = array();
private $maxRetryAttempts;
public function __construct()
{
$this->client = new GearmanClient();
$this->servers = Config_helper::get_config_option('gearman_servers');
$this->maxRetryAttempts = Config_helper::get_config_option('gearman_retry_attempts');
$this->initialize();
}
protected function initialize()
{
foreach($this->servers as $key => $value):
$this->client->addServer($value[0],$value[1]);
endforeach;
}
}
I must assume something is wrong with this implementation but i would like to know why.
The Config_helper::get_config_option('gearman_servers'); is retrieving correctly my list of servers.
This is my Forecast class
<?php
namespace app\forecast;
use app\service\Gearman_service;
use helpers\Config_helper;
use helpers\Urlrequest_helper;
use app\warehouse\models\Client_time_forecast;
abstract class Forecast
{
public $coordinates = array(); # set of coordinates
public $servers = array();
public $variables = array();
public $url = array();
public $prevision;
public $client;
public $gearmanclient;
public function __construct()
{
$this->servers = Config_helper::get_config_option('forecast_servers');
$this->variables = Config_helper::get_config_option('surface_variables');
$this->prevision = Config_helper::get_config_option('forecast_prevision');
$this->gearmanclient = new Gearman_service();
}
public function storeResults()
{
$this->gearmanclient->setCompleteCallback(array($this, 'requestComplete'));
foreach($this->url as $key => $value):
$this->gearmanclient->addTask('request_forecast', serialize($value[0]));
endforeach;
$this->gearmanclient->runTasks(); // **line 37**
}
/**
* [requestComplete store request results in cassandra db]
* #param \GearmanTask $task [description]
* #return [boolean]
*/
public function requestComplete(\GearmanTask $task)
{
$persistent = new Client_time_forecast($this->client, unserialize($task->data()));
$persistent->storeData();
}
}
Anyone can share me a light on this?
Thank you!
As suspected the cause of the problem is that you are mixing inheritance and composition. You extended the GearmanClient class and at the same time you are creating a new instance of the GearmanClient class in the constructor and configuring this new instance in method initialize.
class Gearman_service extends GearmanClient
{
public $client;
// other properties
public function __construct()
{
$this->client = new GearmanClient();
// more code
$this->initialize();
}
You could change the line 37 and all other calls to GermanClient public methods to call the instance initiated in constructor and do not extend GearmanClient class.
$this->gearmanclient->client->runTasks();
However it would be better to change visibility of the property Gearman_service::client to private and implement GeamanClient class public interface.
class Gearman_service extends GearmanClient
{
private $client;
// constructor etc
public function addTask($name, $workload, $context = null, $unique = "")
{
return $this->client->addTask($name, $workload, $context, $unique);
}
If you do so the line 37 should stay as it is.
Alternatively you could opt for inheritance. In that case you would need to remove public property client, do not create a new instance of the GeamanClient class in the constructor and change initialize methods.
protected function initialize()
{
foreach($this->servers as $key => $value):
$this->addServer($value[0],$value[1]);
endforeach;
}
In this case as well you don't need to change the line 37 nor any other calls GeamanClient class public methods.
I've been running in circle for a couple hours with this problem.
Maybe it's not possible at all, or maybe there's a better OOP solution for this...
For example: I have two classes
class Base
{
public static $config;
}
class System extends Base
{
public function __construct()
{
self::$config = 2;
}
}
class Core extends Base
{
public function __construct()
{
self::$config = 3;
}
}
I always access those classes as singletons: System::HelloWorld(), Core::DoStuff();
I want the $Config attribute to be inherited from the Base class because I'm gonna need it in
almost every single class, so why define it every time over and over again.
The problem is, $Config attribute overrides itself as sonn as another class sets it's own value to it:
System::$config = 2;
Core::$config = 3;
print System::$config // it's 3 instead of 2
I do understand why that happens: Because the Base::$Config is Static - and that way - shared trough all the children. I do not want this, I want it to be static in each child, but not trough of it's children. It would be no problem, if I would actually instantiate the System and the Core classes, but I need them as Singletons...
Help me out here, maybe you know a better design pattern then this.
You don't need to use static variable at all,
<?php
Class Base{
public $Config;
}
Class System Extends Base{
Public static $obj = null;
Public static Function HelloWorld() {
if (!System::$obj) System::$obj = new System();
// call the object functions
// $obj->HelloWorld();
}
Public Function __Construct()
{
$this->Config = 2;
}
}
Class Core Extends Base{
Public Function __Construct()
{
$this->Config = 3;
}
}
?>
I came up with a relatively good solution for this. For those who may face the same problem, see here
<?php
// static change the attributes of the scope
class base
{
public static $config;
}
class a extends base
{
public function __construct()
{
self::$config = 1;
}
}
class b extends base
{
public function __construct()
{
self::$config = 2;
}
}
a::$config = 2;
b::$config = 3;
echo a::config, ',', b::$config; // 3,3
$a = new a();
echo base::$config, a::$config, b::$config, $a::$config; // 1 1 1 1
I have two static values: "type" and "typeID". Type is human readable and constant, and typeID needs to be looked up from the database, based on the value of type. I need the lookup to happen once, when the class definition is first loaded
To illustrate, here is some code that doesn't work because you can't call functions in the declaration space.
MyClass extends BaseClass {
protected static $type = "communities";
protected static $typeID = MyClass::lookupTypeID(self::$type);
}
Is there a magic method that is called exactly once when the class definition is loaded? If there is something obvious I'm missing it.
shamelessly pulled from the php manual's static keyword comments:
Because php does not have a static constructor and you may want to initialize static class vars, there is one easy way, just call your own function directly after the class definition.
for example.
<?php
function Demonstration()
{
return 'This is the result of demonstration()';
}
class MyStaticClass
{
//public static $MyStaticVar = Demonstration(); //!!! FAILS: syntax error
public static $MyStaticVar = null;
public static function MyStaticInit()
{
//this is the static constructor
//because in a function, everything is allowed, including initializing using other functions
self::$MyStaticVar = Demonstration();
}
} MyStaticClass::MyStaticInit(); //Call the static constructor
echo MyStaticClass::$MyStaticVar;
//This is the result of demonstration()
?>
Simple and no magic needed, don't forget you can always define a variable as null and test that it is null (doing the db call only then). Then it's just a matter if you want that to happen when the class is constructed or included (include_once etc...)
MyClass extends BaseClass {
protected static $type = "communities";
protected static $typeID = null;
public function __construct(){
if(is_null(self::$typeID)){
self::lookupTypeID(self::$type);
}
}
public static lookupTypeID($type){
self::$typeID = //result of database query
}
}
or
MyClass::lookupTypeID(); //call static function when class file is included (global space)
MyClass extends BaseClass {
protected static $type = "communities";
protected static $typeID = null;
public function __construct(){
}
public static lookupTypeID($type=null){
if(is_null($type)){
$type = self::$type;
}
self::$typeID = //result of database query (SELECT somefield FROM sometable WHERE type=$type) etc..
}
}
a static constructor is more like a factory method
if(!function_exists(build_myclass)){
function build_myclass(){
return MyClass::build();
}
}
MyClass extends BaseClass {
protected static $type = "communities";
protected static $typeID = null;
public function __construct(){
}
public static function build(){
return new self(); //goes to __construct();
}
}
$class = new MyClass(); //or
$class = MyClass::build(); //or
$class = build_myclass();
Such a thing would normally be called a "static constructor", but PHP lacks such things. You might want to consider one of the workarounds suggested in the PHP manual comments, e.g. http://www.php.net/manual/en/language.oop5.static.php#95217
This is what I have: All objects that can be persisted on the database extend the DatabaseObject abstract class, which has all the logic code to actually watch for attribute changes and run the databas queries.
I'm using two static variables to define object-specific details. I define them generically in the base class, and then supposedly I overwrite them in the actual database objects.
The problem is: When the code in the parent class is actually executed, it uses the old parent value instead of the current object value.
Here's the code for the base class:
abstract class DatabaseObject {
public $id;
private static $databaseTable = NULL;
private static $databaseFields = array();
private $data = array();
private $changedFields = array();
public function IDatabaseObject($id) {
$this->id = $id;
$this->data = Database::GetSingle(self::$databaseTable, $id);
Utils::copyToObject($this, $this->data, self::$databaseFields);
}
public static function Load($id) {
return new self($userID);
}
public static function Create($data) {
$id = Database::Insert(self::$databaseTable, $data);
return new self($id);
}
public function Save() {
$data = Utils::copyFromObject($this, $this->changedFields);
Database::Update(self::$databaseTable, $data, $this->id);
}
public function __constructor() {
// We do this to allow __get and __set to be called on public vars
foreach(self::$databaseFields as $field) {
unset($this->$field);
}
}
public function __get($variableName) {
return $this->$variableName;
}
public function __set($variableName, $variableValue) {
// We only want to update what has been changed
if(!in_array($variableName, $this->changedFields) && in_array($variableName, self::$databaseFields)) {
array_push($this->changedFields, $variableName);
}
$this->$variableName = $variableValue;
}
}
And here's the code for one of the objects extending the base class above:
class Client extends DatabaseObject {
public static $databaseTable = "clients";
public static $databaseFields = array("name","contactName","primaryUserID","email","is_active","rg","cpf","cnpj","ie","addrType","addrName","addrNumber","addrComplement","addrPostalCode","addrNeighborhood","addrCity","addrState","addrCountry","phoneLandline","phoneFax","phoneMobile");
public $name;
public $contactName;
public $primaryUserID;
public $email;
public $is_active;
public $rg;
public $cpf;
public $cnpj;
public $ie;
public $addrType;
public $addrName;
public $addrNumber;
public $addrComplement;
public $addrPostalCode;
public $addrNeighborhood;
public $addrCity;
public $addrState;
public $addrCountry;
public $phoneLandline;
public $phoneFax;
public $phoneMobile;
public static function Load($id) {
return new Client($id);
}
}
What am I doing wrong here? Is there another way I can achieve the same result?
A brief addendum: I declare the attributes in the class body mainly to let it be seen by the NetBeans' auto-complete feature.
You are looking for Late Static Binding.
So you need to use:
static::$databaseTable
instead of
self::$databaseTable
This feature is available as of PHP 5.3. Simulating this in PHP 5.2 is very hard, because of two reasons: get_called_class is available only since PHP 5.3, too. Therefore it must be simulated, too, using debug_backtrace. The second problem is, that if you have the called class, you still may not use $calledClass::$property because this is a PHP 5.3 feature, too. Here you need to use eval or Reflection. So I do hope that you have PHP 5.3 ;)
I am going to use singleton classes to manage both DB connections and references to application settings.
It seems a little messy to have to use the following code in every method in order to access the db class.
$db = DB::getInstance();
Is there a more efficient way of going about it?
Any advice appreciated.
Thanks
I often use the Registry pattern, where this behavior occurs as well. I always set a instance variable in the constructor of my models to point to the Registry entry;
class Registry {
private static $_instance;
private $_registry;
private function __construct() {
$_registry = array();
}
public static function getInstance() {
if (!Registry::$_instance) {
Registry::$_instance = new Registry();
}
return Registry::$_instance;
}
public function add($key, &$entry) {
$this->_registry[$key] = &$entry;
}
public function &get($key) {
return $this->_registry[$key];
}
public function has($key) {
return ($this->get($key) !== null);
}
}
Model example;
class MyModel {
private $_db;
public function __construct() {
$this->_db = Registry::getInstance()->get('dbKey');
}
/* Every function has now access to the DAL */
}
Instantiation example;
$dal = new Db(...);
Registry::getInstance()->add('dbKey', $dal);
...
$model = new MyModel();
$model->doDbStuff();
Another approach is to always pass the reference as a parameter to each constructor.
Of course I only use this behavior when most of the methods in my model use the reference, if only a few (one or two) methods have use of the reference, I call the Registry/Singleton like you showed.
It is not messy. This is an intended behavior of Singletons. And, actually, this is just one line of code. Do you wish to make it even more compact? :)
My preferred method is to create a Base class which all the classes that need db access descend from. Base calls the singleton(s) in its constructor. All its children call their parent constructor. e.g.:
class Base {
protected $db;
public function __construct(){
$this->db = DB::getInstance();
}
}
class Achild extends Base {
protected $var1;
public function __construct($arg){
parent::__construct();
$this->var1=$arg;
}
}
I know what you mean... hate that ::getInstance() stuff! So go and use static methods:
class DB {
private static $db;
public static function getInstance() {
if(!self::$db) {
self::$db = new DBconnector();
}
}
public static function query($query) {
return self::$db->query($query);
}
}
Usage is much nicer:
$result = DB::query('SELECT whatever;');
And if you use PHP 5.3 you can write a __callStatic similar to this, to forward all the method calls to the object:
public static function __callStatic($method, $args) {
call_user_func_array(array(self::$db, $method), $args);
}
And to make me happy, add an __autoloader so that you can access DB without any worries any time!