I have been banging my head against the wall for more than a hour now, looking for solutions on the internet (including stackoverflow), but couldn't really find any help, so I decided to ask you guys.
I have the following classes.php file
<?php
class System {
public $domain;
public function __construct() {
$this->domain = 'http://google.com';
}
public function getDomain() {
echo $this->domain;
}
}
class User extends System {
public function __construct() {
parent::__construct($this->domain);
}
public function getDomain() {
echo $this->domain;
}
}
And my code for the index.php file is:
$system = new System();
$user = new User();
$system->getDomain();
$user->getDomain();
Now, the above solution works, but it does not really what I need.
I need for the System class __construct() to be as follows:
public function __construct($domain) {
$this->domain = $domain;
}
And I want to be able to dynamically set the domain from the index.php page, like:
$system = new System('http://google.com');
So to recap everything:
I want to be able to set the domain from my constructor, like so:
public function __construct($domain) {
$this->domain = $domain;
}
instead of
public function __construct() {
$this->domain = 'http://google.com';
}
The truth is that I do not understand very well what you want to do, but I would do it this way.
class System {
private $domain;
protected function __construct($domain) {
$this->domain = $domain;
}
protected function getDomain() {
return $this->domain;
}
}
class User extends System {
public function __construct($domain) {
parent::__construct($domain);
}
}
$user = new User('http://google.com');
echo $user->getDomain();
Related
I have a string of data that will be written to a file as a log of events, so I need this string available from the time the page begins to load to the time it is completed loading, at which time the contents of the string are written to the log file.
I am able to add to this string across some classes, but not others so it has me confused. When it doesn't work I get an 'allowed memory size of ... exhausted' error.
FILE: index.php
spl_autoload_register(function($class) {
if (file_exists(dirname(__FILE__).'/classes/'.$class.'.class.php')) {
include dirname(__FILE__).'/classes/'.$class.'.class.php';
}
});
$App = new Core();
$App->Visitor->getIP(); // This will exhaust memory...why?
$App->Settings->hello(); // Works
$App->writeLog('in my index file...'); // Works
$App->viewLog();
FILE: /classes/Core.class.php
class Core {
public static $logContent;
public function __construct() {
$this->initialize();
}
private function initialize() {
self::$logContent = 'Lets start...';
$this->Visitor = new Visitor($this);
$this->Settings = new Settings($this);
$this->Cache = new Cache($this);
}
public function writeLog($action) {
self::$logContent .= $action;
}
public function viewLog() {
echo self::$logContent;
}
}
FILE: /classes/Visitor.class.php
class Visitor {
private $App;
public function __construct($App) {
$this->App = $App;
}
public function getIP() {
$this->App->writeLog('getting ip...'); // Exhausts memory
if (isset($_SERVER['REMOTE_ADDR'])) {
return $_SERVER['REMOTE_ADDR'];
} else {
return false;
}
}
}
FILE: /classes/Settings.class.php
class Settings {
private $App;
public function __construct($App) {
$this->App = $App;
}
public function hello() {
$this->App->writeLog('getting ip...');
return 'hello';
}
}
What I can't figure out is that both Visitor.class.php and Settings.class.php are setup the same way with the same constructor and yet one will work and the other won't.
So as you can see, I made a static string that everything throughout the app can add to, then later this string will be written to a file one time. Am I going about this the wrong way?
It doesn't save my changes after adding a category.
If I add a category, it is seen in the overview, but if I refresh I see the original amount.
I guess there is an error in my Singleton-design but I can't seem to find it.
class ProductService {
private $_database;
public function __construct($databaseType) {
$databaseFactory = new DatabaseFactory();
$this->_database = $databaseFactory->createDatabase($databaseType);
}
public function addCategory($category){
$this->_database->addCategory($category);
}
public function getAllCategories() {
return $this->_database->getAllCategories();
}
}
class DatabaseFactory {
public function __construct() {
}
public function createDatabase($type){
switch ($type) {
case "Memory" :
return MemoryDatabase::getInstance();
}
}
}
class MemoryDatabase {
private $categories;
private function __construct() {
$this->categories = array(
new Category("Cheese"),
);
}
public static function getInstance() {
static $inst = null;
if ($inst === null) {
$inst = new MemoryDatabase();
}
return $inst;
}
private function __clone() {}
private function __wakeup() {}
public function addCategory($category) {
array_push($this->categories, $category);
}
public function getAllCategories() {
return $this->categories;
}
}
Each request you perform in PHP is stateless.
If you want to persist data between requests, you will need to put your data in some form of persistant storage, i.e., sessions, filesystem, database, memory, etc.
Singleton pattern only ensures a single copy of an object is created, for a given request.
What is the best way to call Method heDidIt() from child class Make?
I was thinking about events but couldnt find a good non global solution.
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make();
return $this->_make;
}
private function heDidIt()
{
//Call me if the Maker did something.
}
}
class Make
{
public function doIt()
{
//hey im doing something, better tell my Controller
}
}
Just tell Make who's its boss so it can inform him:
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make($this);
return $this->_make;
}
private function heDidIt()
{
//Call me if the Maker did something.
}
public function inform($sampleParam) {
var_dump($sampleParam);
$this->heDidIt();
}
}
class Make
{
protected $control;
public function __construct(Control $control) {
$this->control = $control;
}
public function doIt()
{
//hey im doing something, better tell my Controller
$control->inform('called in Make::doIt()');
}
}
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make();
return $this->_make;
}
**protected** function heDidIt()
{
//Call me if the Maker did something.
}
}
class Make **extends Control**
{
public function doIt()
{
**$this -> heDidIt();**
//hey im doing something, better tell my Controller
}
}
Although this seems extremely pointless, so maybe providing your actual code and requirements would let us help you better.
I want to create a function in a class that is available for a set of users, but that they won't be able to access. Ex:
class Stuff_for_user {
private $errors;
/*
* private $errors gets modified by private functions
*/
public function get_errors(){ // This is for users to display errors.
return $this->errors;
}
/*something here...*/ function set_errors($str){
$this->errors = $str;
}
}
So far so good, but now I want the parent class to be able to set Stuff_for_User's errors:
class Main_mess {
public index(){
$user_available_data = new Stuff_for_user();
if($big_error)
$user_available_data->set_errors("BIG ERROR!!!");
$this->send_to_users($user_available_data);
}
}
I want only Main_mess to be able to access Stuff_for_User's set_errors() method. Is that possible?
No, that is not possible like that, since Main_mess is not a parent class of Stuff_for_users (and this is probably what you want, looking at what your code actually does). So set_errors has to be public if you want to call it from the outside.
This is not possible how you want to implement it.
Some ideas (i dont know why or how you want to do that but just ideas...):
do set_error($str,$access_key) and let $access_key be an access string only you know!
let Stuff_for_user be in Extended_Stuff_for_user which has the set_error function like:
class Extended_Stuff_for_user {
private $errors;
private $Stuff_for_user;
public function set_errors() {
/* ... */
}
public function getStuffForUser() {
return $this->Stuff_for_user;
}
}
It seems that you are looking for implementation of something called friend class in php. Well .. i'm sorry to tell you this, but it is not possible.
You should look at other possible solutions to your problem.
class SecureContainer{
protected $user = null;
protected $target = null;
public function __construct( $target, $user )
{
$this->target = $target;
$this->user = $user;
}
public function __call( $method, $arguments )
{
if ( $this->user->isAllowed(getType( $this->target ), $method))
{
return call_user_func_array(
array( $this->target, $method), $arguments );
}
}
}
Use it like this:
$something = new UnsecureSomething;
$user = new User( $uid );
$something = new SecureContainer( $something, $user );
This should let you control the access to methods.
Yes it possible but it can be dirty.
Like This.
class Stuff_for_user {
private $errors;
/*
* private $errors gets modified by private functions
*/
public function get_errors(){ // This is for users to display errors.
return $this->errors;
}
/*
This way the child classes of Main will able be to use the set_errors function;
*/
function set_errors($class,$str){
if($class instanceof Main_mess)
{
$this->errors = $str;
}
/*
AndThis way the only Main_mess will be able;
*/
function set_errors($class,$str){
if(get_class($class)=="Main_mess")
{
$this->errors = $str;
}
}
class Main_mess {
public index(){
$user_available_data = new Stuff_for_user();
if($big_error)
$user_available_data->set_errors($this,"BIG ERROR!!!");
$this->send_to_users($user_available_data);
}
}
I followed this great article http://weierophinney.net/matthew/archives/246-Using-Action-Helpers-To-Implement-Re-Usable-Widgets.html, but currently i can't get work my simplified example.
PROBLEM The preDispatch does not get loaded.
I created new module user (there is also controller UserController, i hope this wont mess up the loading).
I have added two files in user.
Bootstrap.php - under module user
class User_Bootstrap extends Zend_Application_Module_Bootstrap {
public function initResourceLoader() {
$loader = $this->getResourceLoader();
$loader->addResourceType('helper', 'helpers', 'Helper');
}
protected function _initHelpers() {
Zend_Controller_Action_HelperBroker::addHelper(
new User_Helper_HandleLogin()
);
}
New folder under /user/helpers and class HandleLogin.
class User_Helper_HandleLogin extends Zend_Controller_Action_Helper_Abstract {
protected $view;
public function preDispatch() {
echo 'called';
if (($controller = $this->getActionController()) === null) {
return;
}
$this->createProfileWidget();
}
public function createProfileWidget() {
if (!$view = $this->getView()) {
return;
}
$view->user = '<h2>HELLO WORLD</h2>';
}
public function createLoginForm() {
}
public function getView() {
if ($this->view !== null) {
return $this->view;
}
$controller = $this->getActionController();
$view = $controller->view;
if (!$view instanceof Zend_View_Abstract) {
return;
}
//$view->addScriptPath(dirname(__FILE__) .'/../views/scripts');
$this->view = $view;
return $view;
}
}
And lastly added into layout.phtml the output.
<?php echo $this->user ?>
is init() function of User_Helper_HandleLogin works? is User_Bootstrap works? :) maybe you forget resources.modules[] = in config.ini?