$this->a->b->c->d calling methods from a superclass in php
Ive asked a question on this link I ve problem with this tecnique I am able to call the sub classes from a class
like this
$chesterx->db->query();
I wanna do get another class from sub class
for example
i want to query execute which was come from the sql class
ROOT
|
sql <--- chesterx ---> db
i wanna use the sql class from db
the problem i cant return the chesterx class from db class
/edit/
I have some classes like news, members, categories, db and query
and i did it like the link which was on the subject top
public function __construct(){
function __construct(){
if(!$this->db){
include(ROOT."/func/class/bp.db.class.php");
$this->db = new db;
}
if(!$this->chester){
include(ROOT."/func/class/bp.chester.class.php");
$this->db = new chester;
}
}
i called the db class with this code and now i am able to call and use the db class methods well
for example
i want to use a method from db
that method is containing a value which was returning a data from the chester class's method
i wish i were clarify myself
/edit/
is there anyway to do this?
I find Ionut G. Stan's solution good for your case, but you might also want to consider the factory/singleton pattern, though it's only good if your chesterx class is a global one, and only called once
The below snippet might be a solution, although I don't really like the circular reference. Try it and use it as you see fit. And by the way, what you are calling class and subclass are actually containing and contained class.
class Database
{
public $chesterx;
public function __construct($chesterx)
{
$this->chesterx = $chesterx;
}
}
class Sql
{
public $chesterx;
public function __construct($chesterx)
{
$this->chesterx = $chesterx;
}
}
class Chesterx
{
public $db;
public $sql;
public function __construct()
{
$this->db = new Database($this);
$this->sql = new Sql($this);
}
}
Related
All my classes that connect to a database need to get values of custom columns from their respective tables. So instead of coding a function for each class, is there a way for me to implement a base class from which my classes extend and I can use that base class function to easily get and update data on my database (at least for simple data).
class Users extend BaseClass
{
private $table = "users";
private $columns = ["name", "email", "password"];
}
so from an outside function, I can access the email value like this
Users->where("name", "John")->getEmail();
or possibly
Users->where("name", "John")->get("email");
I could also use this method to update data to the database. The functions where should be universal so it should exist in BaseClass. (I know the database queries that I should use, what I want to know is how to call get after calling where and also possibly setting multiple where requirements).
Users->where("name", "John")->where("last_name", "Smith")->get("email");
I think you want something like this
abstract class BaseClass
{
private $where_clauses=[];
private $columns=[];
private $table='';
protected function setData($table,$cols){
$this->columns=$cols;
$this->table=$table;
}
public function where($key, $value){
$this->where_clauses[$key]=$value;
return $this;
}
public function get($col){
$sql='SELECT '.$col.' FROM '.$this->table.' WHERE';
$first=true;
foreach($this->where_clauses AS $key=>$val){
if(!$first) sql.=' AND ';
$first=false;
$sql.=$key.' = '.$val;
}
// RUN QUERY, Return result
}
}
Note that the where function returns a reference to $this, which is what let's you string the function calls together (not tested the code). This would also need some adapting to let you put two conditions on the same column.
On my site at the beginning of every script I include a "bootstrap" script which queries a few things from the database, does some calculations and then loads the variables into constants that I define one by one.
Some examples are:
define("SITE_ID", $site_id); // $site_id is pulled from a field in the database
define("SITE_NAME", $site_name);
// pulled from a field in the same row as the above
define("STOCK_IDS", $stock_ids);
//computed array of stock id integers from a different query.
//I perform logic on the array after the query before putting it in the definition
define("ANALYTICS_ENABLED", false);
// this is something I define myself and isnt "pulled" from a database
Now, I have many functions on the site. One example function is get_stock_info. And it references the STOCK_IDS constant.
What I want to do is have a class which has the above constants in it and the get_stock_info function.
Would the best approach to be have an empty class "site", create an instance of it and then afterwards define the static variables above one by one? Or is that not a good way and should I move all of of my logic which pulls from the database and calculates SITE_ID, STOCK_IDS, ANALYTICS_ENABLED etc into the constructor instead?
Ultimately I want the class to contain all of the above info and then I would be able to use class methods such as site::get_stock_info() and those methods will have access to the constants via self:: or this.
There's a lot more I want to do than that but that would give me enough to figure the rest out.
I think this approach isn't the best. You should consider not using constants as your values aren't constant. For your case it is better to have a class with classic getters methods.
Something like this:
class SiteInfo
{
private $siteId;
private $siteName;
private $stockIds;
private $analyticsEnabled;
public function __construct()
{
// Results from the database
$results = $query->execute();
$this->siteId = $results['siteId'];
$this->siteName = $results['siteName'];
$this->stockIds = $results['stockIds'];
$this->analyticsEnabled = $results['analyticsEnabled'];
}
public function getSiteId()
{
return $this->siteId;
}
public function getSiteName()
{
return $this->siteName;
}
public function getStockIds()
{
return $this->stockIds;
}
public function isAnalyticsEnabled()
{
return $this->analyticsEnabled;
}
}
This is my php page persona.php:
<?php
class persona {
private $name;
public function __construct($n){
$this->name=$n;
}
public function getName(){
return $this->name;
}
public function changeName($utente1,$utente2){
$temp=$utente1->name;
$utente1->name=$utente2->name;
$utente2->name=$temp;
}
}
?>
The class persona is simple and just shows the constructor and a function that change two users name if called.
This is index.php:
<?php
require_once "persona.php" ;
$utente1 = new persona("Marcello");
print "First user: <b>". $utente1->getName()."</b><br><br>";
$utente2 = new persona("Sofia");
print "Second user: <b>". $utente2->getName()."</b><br>";
changename($utente1,$utente2);
print " Test after name changes: first user". $utente1->getName()."</b> second user". $utente2->getName();
?>
What I do not understand is how to call the changeName function from here.
I can understand where the confusion arises from...I think you are unsure if you should call changename on $utente1 or $utente2. Technically you can call it from either objects because they are both instances of Persona
But for clarity (and sanity), I would recommend converting the changeName function to a static function in its declaration:
public static function changeName($utente1,$utente2){
and then in your index.php you can call it as:
Persona::changename($utente1,$utente2);
From an architecture stamp point, this will help provide a better sense that the function is tied to the class of Persona, and objects can change swap names using that class function, as opposed to making it an instance function and then having any object execute it.
In your particular case you can call it as:
$utente1->changename($utente1,$utente2);
or
$utente2->changename($utente1,$utente2);
It doesn't matter which. As the method itself doesn't work with the classes properties (but only with the method parameters), you can call it from any object that exist.
But better (best practice, and better by design) is to develop a static method, as Raidenace already said, and call it like:
Persona::changename($utente1,$utente2);
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Functionality of PHP get_class
For a small ORM-ish class-set, I have the following:
class Record {
//Implementation is simplified, details out of scope for this question.
static public function table() {
return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', get_class()))."s";
}
static public function find($conditions) {
//... db-selection calls go here.
var_dump(self::table());
}
}
class Payment extends Record {
}
class Order extends Record {
public $id = 12;
public function payments() {
$this->payments = Payment::find(array('order_id', $this->id, '='));
}
}
$order = new Order();
$order->payments();
#=> string(7) "records"
I would expect this code to print:
#=> string(8) "payments"
But, instead, it prints records. I have tried self::table(), but that gives the same result.
Edit, after some questions in the comments table() is a method that simply maps the name of the Class to the table in wich its objects live: Order lives in orders, Payment lives in payments; records does not exist!). When I call Payments::find(), I expect it to search on the table payments, not on the table records, nor on the table orders.
What am I doing wrong? How can I get the classname of the class on which ::is called, instead of the class in which is was defined?
Important part is probably the get_class(), not being able to return the proper classname.
You can use get_called_class if you're using php 5.3 or higher. It gives you the class the static method is called on, not the one where the method is actually defined.
UPDATE
You need the class name of the class on which 'find' is called. You can fetch the class name in the find method and provide it as a parameter to the table (maybe rename it to getTableForClass($class)) method. get_called_class will give you the Payment class, the table method derives the table name and returns it:
class Record {
//Implementation is simplified, details out of scope for this question.
static public function getTableForClass($class) {
return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $class))."s";
}
static public function find($conditions) {
//... db-selection calls go here.
$className = get_called_class();
$tableName = self::getTableForClass($class);
var_dump($tableName);
}
}
So basically I'm making a leap from procedural coding to OOP.
I'm trying to implement the principles of OOP but I have a nagging feeling I'm actually just writing procedural style with Objects.
So say I have a list of pipes/chairs/printers/whatever, they are all all listed as products in my single table database. I need to build a webapp that displays the whole list and items depending on their type, emphasis is on 'correct' use of OOP and its paradigm.
Is there anything wrong about just doing it like:
CLass Show
{
public function showALL(){
$prep = "SELECT * FROM myProducts";
$q = $this->db-> prepare($prep);
$q->execute();
while ($row = $q->fetch())
{
echo "bla bla bla some arranged display".$row['something']
}
}
and then simply
$sth = new show();
$sth->showAll();
I would also implement more specific display methods like:
showSpecificProduct($id)->($id would be passed trough $_GET when user say clicks on one of the links and we would have seperate product.php file that would basically just contain
include('show.class.php');
$sth = new show();
$sth->showSpecificProduct($id);
showSpecificProduct() would be doing both select query and outputing html for display.
So to cut it short, am I going about it allright or I'm just doing procedural coding with classes and objects. Also any ideas/hints etc. on resolving it if I'm doing it wrong?
As well as the model practices described by #Phil and #Drew, I would urge you to separate your business, data and view layers.
I've included a very simple version which will need to be expanded upon in your implementation, but the idea is to keep your Db selects separate from your output and almost "joining" the two together in the controller.
class ProductController
{
public $view;
public function __construct() {
$this->view = new View;
}
public function indexAction() {
$model = new DbProductRepository;
$products = $model->fetchAll();
$this->view->products = $products;
$this->view->render('index', 'product');
}
}
class View
{
protected $_variables = array();
public function __get($name) {
return isset($this->_variables['get']) ? $this->_variables['get'] : null;
}
public function __set($name, $value) {
$this->_variables[$name] = $value;
}
public function render($action, $controller) {
require_once '/path/to/views/' . $controller . '/' . $action . '.php';
}
}
// in /path/to/views/product/index.php
foreach ($this->products as $product) {
echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}
A better fit would be to implement a repository pattern. An example interface might be
interface ProductRepository
{
public function find($id);
public function fetchAll();
}
You would then create a concrete implementation of this interface
class DbProductRepository implements ProductRepsoitory
{
private $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function find($id)
{
// prepare execute SQL statement
// Fetch result
// return result
}
public function fetchAll()
{
// etc
}
}
It's generally a bad idea to echo directly from a method or function. Have your methods return the appropriate objects / arrays / whatever and consume those results.
The scenario you are describing above seems like a good candidate for MVC.
In your case, I would create a class strictly for accessing the data (doing selects of product categories or specific products) and then have a different file (your view) take the output and display it.
It could look something like this:
class Product_Model {
public function find($prodId) { ... }
public function fetchAll($category = '') { ... }
public function search($string) { ... }
}
Then somewhere else you can do:
$products = new Product_Model();
$list = $products->fetchAll(37); // get all from category 37
// in true MVC, you would have a view that you would assign the list to
// $view->list = $list;
foreach($ilst as $product) {
echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}
The basic principle of MVC is that you have model classes that are simply objects representing data from some data source (e.g. database). You might have a mapper that maps data from the database to and from your data objects. The controller would then fetch the data from your model classes, and send the information to the view, where the actual presentation is handled. Having view logic (html/javascript) in controllers is not desirable, and interacting directly with your data from the controller is the same.
first, you will want to look into class autoloading. This way you do not have to include each class you use, you just use it and the autoloader will find the right file to include for you.
http://php.net/manual/en/language.oop5.autoload.php
each class should have a single responsibility. you wouldn't have a single class that connects to the database, and changes some user data. instead you would have a database class that you would pass into the user class, and the user class would use the database class to access the database. each function should also have a single responsibility. you should never have an urge to put an "and" in a function name.
You wouldn't want one object to be aware of the properties of another object. this would cause making changes in one class to force you to make changes in another and it eventually gets difficult to make changes. properties should be for internal use by the object.
before you start writing a class, you should first think about how you would want to be able to use it (see test driven development). How would you want the code to look while using it?
$user = new User($db_object);
$user->load($id);
$user->setName($new_name);
$user->save();
Now that you know how you want to be able to use it, it's much easier to code it the right way.
research agile principles when you get a chance.
One rule of thumb is that class names should usually be nouns, because OOP is about having software objects that correspond to real conceptual objects. Class member functions are usually the verbs, that is, the actions you can do with an object.
In your example, show is a strange class name. A more typical way to do it would be to have a class called something like ProductViewer with a member function called show() or list(). Also, you could use subclasses as a way to get specialized capabilities such as custom views for particular product types.