Global variable inside multiple classes - php

Let's say I have something like this:
<?php
namespace Twitter;
class Twitter {
function __construct()
{
$config = array ('api' => 'something', 'api_url' => 'something2');
}
// some code goes here
}
class TwitterConnection {
function __construct()
{
$config = array ('api' => 'something', 'api_url' => 'something2');
}
// some code goes here
}
?>
and so on - there will be more classes that uses $config variables.
Now, the question is: how can I define config only once, and make it accessible across all classes?
Thanks

You could create a configuration object that reads from your data source (ini, db, php file ...) and populates itself. Then give it a getter so you can get the configuration properties stored within.
Something along the lines of Config::get('someProperty')
Once you have this object setup, you can pass it to the constructor of your classes so it can be used in inside.
class Twitter {
function __construct($config) {
$state = $config->get('someState');
}
}
You could also simply use it within your classes without injecting it by making it a static class (You could also just as easily create a new instance).
class Twitter {
function __construct() {
//Don't recommend this, better to inject it.
$state = Config::get('someState');
}
}
EDIT
The simplest config class that uses your hardcoded array would look something like this. Again, I suggest you move out your configuration out of your code.
class Config {
private $opts = array();
public function __construct() {
/**
* Ideally opts should be coming from some kind of easy to
* access configuration file
*
*/
$this->opts = array ('api' => 'something', 'api_url' => 'something2');
}
public function get($key) {
if (isset($this->opts[$key])) {
return $this->opts[$key];
}
return false;
}
}
class Twitter {
function __construct($config) {
echo $config->get('api');
}
}
$config = new Config();
new Twitter($config);
You could also change the class a bit so that it works without needing an instance of itself.

There are a couple of different things in play here - config data storage, and config data representation and use.
For storage, as martswite commented above, you could have a config file. You could also have config data stored in a database.
For data representation, you could have an array, like you've shown in your question, or a separate full-fledged object.
Usually, if you have objects that have a dependency on certain data in order to work, you pass (inject) that dependency into the object through its constructor. So, roughly, something like this:
class Example
{
private $dependency;
public function __construct($dependency)
{
$this->dependency = $dependency;
}
public function doSomething()
{
// do something with $this->dependency
}
}
This would be tedious to do manually if you had many objects which required the same dependency. Thankfully, there are dependency injection containers which automate a lot of the process. Where do you find these containers? A Google search should yield results. That said, Symfony seems like a popular option: http://components.symfony-project.org/dependency-injection/
All that said, there's a bit of a learning curve to understanding and using a DI container. Still, it's probably the best way to go without introducing globals into your code.
Finally, just to give you an idea of how to use it, here's some pseudo-code:
// Load config data from file/db/some other source. Use it to populate an object (most likely) or array
// Set up the DI container to automatically inject the config data into the objects which require it
// Profit

Try:
namespace Twitter;
$config = array ('api' => 'something', 'api_url' => 'something2');
class Twitter {
function __construct()
{
global $config;
}
}
class TwitterConnection {
function __construct()
{
global $config;
}
}
?>

Related

AuraPHP DI dynamic class or decision based injection

I'm new to modern method of dependency injection and I'm trying to figure out how to have a method pick which class to use based on a condition. I bet I've got my design structure off but I'm also not seeing how to do this in Aura DI through the config.
This is my Aura Config
<?php
namespace Aura\Cli_Project\_Config;
use Aura\Di\Config;
use Aura\Di\Container;
class Common extends Config {
public function define(Container $di) {
// utilities
$di->set(
'App\Inventory\Utilities\EmailParser',
$di->newInstance('App\Inventory\Utilities\PlancakeParser')
);
// commands
$di->params['App\Inventory\Command\IncomingOrder'] = array(
'stdio' => $di->lazyGet('aura/cli-kernel:stdio'),
'parser' => $di->get('App\Inventory\Utilities\EmailParser')
);
}
// ...
}
And this is the class in question that needs to use different classes depending on the "source" it finds.
<?php
namespace App\Inventory\Command;
use Aura\Cli\Stdio;
use App\Inventory\Utilities\EmailParser;
use App\Inventory\Sources\Etsy;
use App\Inventory\Sources\Amazon;
use App\Inventory\Sources\Ebay;
class IncomingOrder {
public function __construct(
Stdio $stdio,
EmailParser $parser) {
$this->stdio = $stdio;
$this->parser = $parser;
}
public function process() {
// other code to parse message
// source is set by determining where it came from
$source = 'Etsy';
switch($source) {
case 'Etsy' :
// This bit seems really wrong
$sourceParser = new Etsy\OrderParser();
break;
case 'Amazon' :
$sourceParser = new Amazon\OrderParser();
break;
case 'Ebay' :
$sourceParser = new Ebay\OrderParser();
break;
default :
$sourceParser = null;
}
// Do source specific processing
}
}
Is it that I need to split my processing at the point right after the source is determined so a new class can be initialized with that source as a parameter?
The only way I can see to do this in the config is to do a lazy anonymous function to return the proper source class but this also feels against modern design principles.
Something I would like to clarify is you don't need to use set method like many of the di containers out here. You can modify the code to
<?php
namespace Aura\Cli_Project\_Config;
use Aura\Di\Config;
use Aura\Di\Container;
class Common extends Config
{
public function define(Container $di)
{
// commands
$di->params['App\Inventory\Command\IncomingOrder'] = array(
'stdio' => $di->lazyGet('aura/cli-kernel:stdio'),
'parser' => $di->lazyNew('App\Inventory\Utilities\EmailParser')
);
}
// ...
}
You can make use of set when you want to pass the same object to many other objects. Don't use newInstance for it will create the object on calling the same. You probably may need to make use of lazyNew or lazyGet functionalities.
Regarding your question about dynamic decision making. Here is my thoughts, I did have came across this question some time before. But didn't see what I did so iirc what I did was injected a factory to IncomingOrder class which can create object. The good thing about it is if your source parse needs some sort of dependency you can make use of di inside the factory.
Eg :
<?php
namespace Something;
use Aura\Di\Container;
class SourceFactory
{
public function __construct(Container $di)
{
$this->di = $di;
}
public function newInstance($source)
{
if ($di->has($source)) {
return $di->get($source);
}
// or alternatively create with new as done in switch
}
}
Hope that helps.
Thank you

how to pass data mapper between models in php

I have read a lot in the past few days about domain objects, data mappers, and a bunch of other stuff I had no idea about.
I have decided to try and implement this in a bit of code I am writing (partly for learning purposes, and partly because I want to create a REALLY simplified framework to build a few projects quickly...with code that I can easily understand and modify).
After reading this and this, I was planning on creating a SINGLE data mapper, with a connection to the DB inside of it, and then use a factory to pass the data mapper into every domain object (well, the ones that would need it). I include some sample code below
class data_mapper {
private $dbh;
function __construct()
{
$this->dbh = new PDO(DB_STRING, DB_USER, DB_PASS);
}
public function createUser($data) ...
public function updateUser($user_id, $data) ...
public function createCategory($data) ...
}
class user {
private $data_mapper;
public $user_id;
public $data;
function __construct($dm)
{
$this->data_mapper = $dm;
}
function someFunction() {
/* some code */
$this->data_mapper->updateUser($user_id, $data);
/* some more code */
}
}
class factory {
private $data_mapper = null;
function __construct($dm)
{
$this->data_mapper = $dm;
}
public function create($name)
{
return new $name($this->data_mapper);
}
}
/* USAGE */
$dm = new data_mapper();
$factory = new factory($dm);
$user = $factory->create('user');
I am left with two questions:
A lot of recent examples I've looked at create a different data_mapper for each model. Should I be doing this? And if I do, wouldn't that make the factory much more complex (i.e. I would need to create single PDO object and pass that into each data mapper, and then pass the right data mapper into each model)?
If my above code exposes some flaw in the understanding of models, data mappers or anything else, please enlighten me (not really a question, i know)...
As far as I can tell, "data mapper" pattern implemented in modern frameworks in the form of prototype Model class, from which all application models are inherited.
In this prototype model you can implement CRUD methods and thus your models will possess it.
Speaking of passing pdo around, local scholars will tell you that you should pass PDO object as constructor parameter. But if you'll take a look at any modern framework - they are using some sort of singleton that contains a PDO instance
So, you want a REALLY simplified PHP framework. Data mappers sound like over-engineering.
Over the years i made a few KISS frameworks in PHP, this is what i did:
Use templates (aka view) such as Smarty. Great for outsourcing your webdesign.
Make a folder named pages (aka controller). Pages are called by index.php only.
Make a folder named models. Only models talk with your DB.
Make a index.php (aka router). Has a ?page=dog parameter.
Strict MCV (aka MVC) terminology is not the holy grail, the above is a nice implementation for a simple website/app/CMS.
The parts
/pages/page_dog.inc.php
A page loads the model(s) he needs, manipulates and shows it:
<?php if(!defined('YOURFRAMEWORK')){die('External access denied');}
// Page init
require './models/model_dog.inc.php';
$id = $_GET['id']; // todo fix injection attacks
$ModelDog = new ModelDog($DB);
// Page main
$ModelDog->Load($id);
echo $ModelDog->item['breed'];
For listings (a page where user selected the $id) you may not want seperate models representing each result. Make a lister class instead, much like the model but returning multiple items in one array. Its tempting to DRY and make the ListerDog class use the ModelDog but there is no readability gain just performance pain.
/index.php (aka router) calls a page (via require_once()) after auth and init ($DB):
<?php
define('YOURFRAMEWORK', 1); // disable "External access denied" error.
require_once('config.inc.php'); // todo have this hold the $config[] array.
$DB = #new mysqli( // or your derative, so you can log each query() call.
$config['db']['host'],
$config['db']['user'],
$config['db']['pasw'],
$config['db']['database']
);
if ($DB->connect_error) { die('db error: ' . mysqli_connect_errno()); }
// Load page requested by user. For now, its dog hardcoded.
require_once('./pages/page_dog.inc.php');
$DB->close;
/models/model_dog.inc.php (aka model) talks to the DB for you, processes and sanitizes data. I also use this put form processing functions.
<?php if(!defined('YOURFRAMEWORK')){die('External access denied');}
class ModelDog extends BaseModel {
private $tablename = 'dogs';
/**
* Load last (or specific) item.
* #param integer $id
* #return boolean Returns false when failed.
*/
public function Load($id=null) {
$query = "SELECT * FROM `".$this->tablename."` WHERE `id`='".$this->DB->Sanitize($id)."';";
// TODO .. $this->item =
}
public function ItemDefaults() {
return array(
'id' => 0,
'breed' => 'unknown',
'height' => 0
);
}
// TODO ..
}
/models/basemodel.inc.php extend every model class from something common like:
abstract class BaseModel
{
protected $item = array(); // Here is all the data!
protected $DB = null;
public function __construct($aQDB) {
parent::__construct();
$this->DB = $aDB;
$this->Reset();
}
public function Reset() {
$this->item = ItemDefaults();
}
public function Item() { return $item; }
// As seen in dog
abstract public function Load($id);
abstract public function ItemDefaults();
// But descendants (models) must also implement:
abstract public function Save($id = NULL);
abstract public function Delete($id);
// You may want to add Validate() and other internal things here.
}
All of the above is a bare-minimum version of what i build myself when i need another tiny framework. You gain more in proper subclassing than making more classes doing more things. A website is a simple thing in essence, until one overcomplicates it..
The gist / TLDR;
If you really want a REALLY simplified PHP framework, dont read to much. Just write code and you'll discover what it needs to make you work better.

Set a php object global for query optimization

I have a problem in optimizing my PHP script. For example:
A MySQL Table:
option_name || option_value
=====================================================
base_url || http://mysite.com/myproject
theme_name || default
language || en
MyScript.php file:
class options {
private $options = null;
public function get($optionName) {
if(!isset($this->options))
self::get_data();
return $this->options[$optionName];
}
protected function get_Data() {
// ...
// DO A MYSQL QUERY AND SAVE IT TO $this->options
// ...
}
}
The data which this class returns is constant. So there is no need to run a MySQL query every time I need to access for example base_url value. What is the best way to create an object and use it global?
$OPTIONS = new options;
function load_option($optName) {
global $OPTIONS;
return $OPTIONS->get($optName);
}
Something like this function maybe? Someone told this is The Worst Possible Way.
I need help. Thanks!
Your problem here, is that you do not understand what SOLID and DI principles are. You should implement classes that serve each singular responsibility, then inject their instances on demand.
In your case, it would look like this,
class Config
{
protected $pdo;
protected $cache;
public function __construct($pdo)
{
$this->pdo = $pdo;
}
public function read($key)
{
// Read a value by its key from a table
// Here should be a SELECT query
// You can also prevent reading the same thing twice
// by storing it in a cache
}
public function write(array $data)
{
foreach ($data as $key => $value) {
// Here should be INSERT statement
}
}
public function delete($key)
{
// Here comes a DELETE statement
}
}
Each time you need to read a configuration value, you would simply inject an instance of Config to a class that needs it.
class Foo
{
protected $config;
public function __construct(Config $config)
{
$this->config = $config;
}
public function doSomethingDependingOnConfig()
{
if ($this->config->read('lang') === 'en') {
// do something
}
}
}
And you would use it like,
$pdo = new PDO(...);
$config = new Config($pdo);
// Test
echo $config->read('lang'); //en
// So,
$foo = new Foo($config);
$foo->doSomethingDependingOnConfig();
Actually, I don't think that's the worst possible way.
Many config settings don't need to be stored in a database. Some even can't be (like the address and credentials of the database).
So is it obvious that some hard coded config is convenient. And if you would investigate existing PHP applications, you'll see that most of them will have some globally configurable options.
The disadvantage of a global variable, is that its very strict and hard to change it's usage. Soon you'll find yourself using this global thoughout your application.
But you already countered that by wrapping access to it in a function, so you can easily change the options later, without having to change your entire application. You've hidden the way the options are stored by making this wrapper function. If you'd like, you could still fetch them from the database, or start storing them in a file, because all you need to change is this function. So this is quite a good solution, actually.
One thing you could do to improve this code:
Maybe you could wrap it in a Config singleton class. The advantage of that, is that you can actually store the config in that class as well, getting rid of the global variable, and therefor, getting rid of accidental access to that global. You will force yourself to always use the function/class access to the options.

OOP PHP - Get vars from one class and into a class within another file

I have a situation where I'm creating a controller file that echo's json output to be used client-side with ajax:
echo json_encode($response);
The main class in another file, among other things, grabs all the setting vars from the CMS.
Now, the controller file has a class that generates the request from the API, but the setting vars in the class (username, id, count, etc.) are hard coded because I can't figure out how exactly to get them from the main class in the other file. With the settings hard coded, the controller file creates and echos the json output as expected. It just needs the dynamic vars from the main class.
Please excuse my lack of knowledge and usage of OOP. I've been trying it with a structure like this, where again, just trying to get the username and other vars from the main class into another class within separate file.
** EDIT ** Rethinking this a bit based on the comment by #Dave Just as it makes better sense. So if I move the api_request function into mainClass and return the response, I can get the variables I need and the request still works. So that would lead me to ask - how can I still echo the $response from the api_request function in a separate file? That separate file with the json is what I'm using for my ajax script.
class mainClass {
public $username;
function __construct() {
...
}
public function api_settings( $username ) {
...
}
}
$main_class = new mainClass;
$main_class->api_settings();
// OR
$main_class->username;
api-call.php
class apiCall extends mainClass {
public $username;
function __construct() {
parent::__construct;
...
}
public function api_request() {
...
$return = $api_auth->request(
'GET',
$api_auth->url( '/cms-plug' ),
array(
//where I need to be able to grab the $username from the main class
'username' => 'joebob'
)
);
echo json_encode($response);
}
}
$api_class = new apiCall;
Since you asked me to point out this,
There are so many flaws in your architecture
First,
When you do it like,
class apiCall extends mainClass {
you break the Single Responsibility Principle and Liskov Substitution principle at the same time
Second,
A controller should never echo anything
MVC itself looks like
$modelLayer = new ModelLayer();
$view = new View($modelLayer);
$controller = new Controller($modelLayer);
$controller->indexAction($request);
echo $view->render();
You actually implementing something that is close to Model-View-Presenter, not MVC
Third
Since your class starts from api.. then there's no need to include that name in methods.
Fourth,
You don't have to tightly couple json_encode() with generation logic. That method should only return an array, then you'd json_encode() that array. Benefits? 1) Separation of Concerns 2) You can event convert that array to YAML or XML, not only JSON
And also, you should avoid inheritance in your case. Write singular class that deals with ApiCalls. So, it would look like as,
final class ApiCall
{
/**
* I'd use a name that makes sense
*
* #param string $username
* #return array on success, FALSE on failure
*/
public function fetchByUsername($username)
{
$return = $api_auth->request(
'GET',
$api_auth->url( '/cms-plug' ),
array('username' => $username)
);
if ($response !== false){
return $response;
} else {
return false;
}
}
}
And you would use it like,
if (isset($_GET['username'])){
$api = new ApiCall();
$result = $api->fetchByUsername($_GET['username']);
if ($result !== false){
// Respond as JSON
die(json_encode($result));
} else {
die('Wrong username');
}
}
You can access properties from the current object with this. This also works for inherited properties from parent classes.
api-call.php
class apiCall extends mainClass {
//public $username; // you don't have to decalre $username again, it gets already inherited from mainClass since its public there
function __construct() {
parent::__construct;
...
}
public function api_request() {
...
$return = $api_auth->request(
'GET',
$api_auth->url( '/cms-plug' ),
array(
//where I need to be able to grab the $username from the main class
'username' => this->username // vars of the current object and inherited vars are available with "this"
)
);
echo json_encode($response);
}
}
$api_class = new apiCall;

Instantiate object defined as property in a PHP class as needed (lazy loading)

For the sake of simplicity, assume I have 2 classes, User and UserStatus, used in a Web application.
<?php
// library code:
class UserStatus {
protected $_status = NULL;
private function fetchDataFromDB() {
// regular DB stuff
$this->_status = ...
// result will be something like 'online', 'away', etc.
}
public function getIcon() {
global $icon_array;
if (is_null($this->_status)) {
$this->fetchDataFromDB()
}
return $icon_array[$this->_status];
}
}
class User {
protected $user_id;
public $user_name;
protected $status;
public function __construct() {}
public static function getAll() {
// some DB stuff
return $users;
}
}
// and now, in index.php:
$users = User::getAll();
// echoes the icon to use to reflect the current user status
foreach ($users as $user) {
echo <img src="$user->status->getIcon()"/>;
}
?>
In most of the HTTP request the status object will not be used so I'm looking for a way to only instantiate it as needed (call it lazy loading). How should I intercept the status->method() call and create that object on-the-fly?
An important note is that I need $user_id available in the UserStatus class, otherwise the fetchDataFromDB() method won't know to which user it should fetch the data. How should this be done?
I've looked at some interesting stuff on this matter like Fabien Potencier's What is Dependency Injection? and Pimple - a PHP 5.3 dependency injection container and also some articles about the Proxy Pattern but to implement them it looks like I have to mess a lot with the current code. Is there a simpler way?
Maybe im missing something but it seems the easiest solution in this instance would be to have your getter for Status simply create the object if it doesnt exist...
public function getStatus()
{
if(!isset($this->status))
{
// or however you creat this object..
$this->status = new UserStatus($this->user_id);
}
return $this->status;
}
public function __get($property)
{
$method = 'get'.ucfirst($property); // getStatus
if(method_exists($this, $method))
{
return $this->$method();
}
}
By using the __get magic method anytime you do $user->status it will call $user->getStatus(). Ofcourse you could also always just access it like: $user->getStatus()->getIcon() as well.
However you decide to set up accessing your properties i would recommend doing it in a consistent way across your entire model.
You could put the status class in a different file and then leverage php's autoloading mechnism:
http://php.net/manual/de/language.oop5.autoload.php
to not load that file until you access it.
There are rumors that auto loading (or actually just any kind of conditional loading) is troublesome for byte code caches and optimizers though unfortunately I don't know too much about the impact.
P.S.: The manual does not say rhis explicity at this point: You can also use spl_autoload_register() instead of just defining the magic __autoload function. This is slightly more powerful.

Categories