I have multiple classes, in this case Core and User. At this moment User is an extension of Core. In Core, I have my main functions that are required in multiple classes, for example a database connection through PDO. I use a __construct function to build the database connection, no problems with that.
However, in my User class, I want to pass values to multiple attributes through __construct. For example a Firstname, Lastname, Email, Password and a few other attributes.
When doing this, I get a warning from Netbeans that the parent constructor should be used, and a lot of vague errors, I don't ask you to fix these errors.
I would like to know if there is a way for me to use the database connection function from Core in User without making the extension. I hope it is more clear with a little bit of background information!
Below both classes, only showing the parts related to the question:
abstract class Core implements ICore {
private $_dbcon;
public function __construct($_database){
$this->_dbcon = $_database;
}
public function _connectDB(){
return $this->_dbcon;
}
class User extends Core implements IUser {
public $_username;
private $_password;
protected $_email;
protected $_adres;
protected $_phone;
protected $_contactperson;
protected $_company;
protected $_kvk;
public function __construct($_username, $_password, $_email, $_adres, $_phone, $_contactperson, $_company, $_kvk){
$this->_username = $_username;
$this->_password = $_password;
$this->_email = $_email;
$this->_adres = $_adres;
$this->_phone = $_phone;
$this->_contactperson = $_contactperson;
$this->_company = $_company;
$this->_kvk = $_kvk;
}
You have to call the parent constructor.
class User extends Core
{
public function __construct($db, $username, ...)
{
parent::__construct($db);
$this->_username = $_username;
...
}
}
But in your case I would think about a better overall design. Read about Dependency injection. In this way you'd only have one DB connection and use that connection in other classes.
class User
{
protected $db;
public function __construct(Db $db)
{
$this->db = $db;
}
}
Related
I have a class User which has private properties of a user and public interfaces. I am trying to expose those properties through OOP in order to bind their $key=>value to some sql parameters, but I can iterate over private members in order to extract the data. I have saw the var_dump() method which is usually used for debugging, so I created a public interface userInfo() that would return that object as an array. However, that just seems like a hack and not a real eloquent way of exposing or sharing data across this application. Ive read tons of articles and in class we are taught to keep members private and expose them through public interfaces. I know there is the protected member access, but is that eloquent enough? So, how would a "good", and I know that subjective, coder share this data across the application?
EDIT: Cannot use protected because nothing extends the user class
class User{
private $firstname
private $lastname
private $username
private $password
public getFirstName(){}
public getLastName(){}
public getUsername(){}
public getPassword(){}
public userInfo(){
return get_object_vars($this)
}
}
PHP has overloading / magic methods exactly for this purpose. You don't need to programmatically think of every possible value / field. Have a look at the below example:
class MyClass {
private $firstField;
private $secondField;
public function __get($property) {
if ( property_exists($this, $property) ) {
return $this->$property;
}
}
public function __set($property, $value) {
if ( property_exists($this, $property) ) {
$this->$property = $value;
}
return $this;
}
}
I read many posts and blogs about Singleton and database connection. What I understand from the singleton definition is that you can use it on any class object that is instantiated many times while staying intact.
I have a web application, and I was wondering if I could implement Singleton for database connection
Here is what I have under the DatabaseGateway class:
class DatabaseGateway
{
private $DBConnection;
private $serverName;
private $userName;
private $password;
private $databaseName;
public function __construct() {
//not done
}
public function getDBConnection() {
return $this->DBConnection;
}
public function openDBConnection() {
$this->DBConnection = new mysqli($this->serverName, $this->userName, $this->password, $this->databaseName);
}
public function closeDBConnection() {
mysqli_close($this->DBConnection);
}
The method OpenDBConnection is used when users log in in the UserGateway class. I was wondering if it is a good idea, and if it possible, to make openDBconnection into a singleton, while everyone has their own account and password.
PREAMBLE: I use F3 Framework (www.fatfreeframework.com).
Let's say I have an abstract class "Controller"
<?php
abstract class Controller
{
/* F3 */
protected $f3;
/* DATABASE SECTION */
protected $db_name;
protected $db_host;
protected $db_username;
protected $db_password;
function __construct()
{
$f3 = Base::instance();
$this->f3 = $f3;
}
protected function get_db_name()
{
return $this->db_name;
}
protected function get_db_host()
{
return $this->db_host;
}
protected function get_db_username()
{
return $this->db_username;
}
protected function get_db_password()
{
return $this->db_password;
}
protected function set_db_name($db_name)
{
$this->db_name = $db_name;
}
protected function set_db_host($db_host)
{
$this->db_host = $db_host;
}
protected function set_db_username($db_username)
{
$this->db_username = $db_username;
}
protected function set_db_password($db_password)
{
$this->db_password = $db_password;
}
} // /class Controller
And a FrontendController Class:
<?php
class FrontendController extends Controller
{
public function get_view()
{
$this->set_db_host('localhost');
}
}
His work it's manage frontend website (html, print results from database, etc etc etc).
After some day, I need the BackendController class, to manage the news of the site (for example).
1) I need to rewrite the db connections (for example) ? Or I will move them in construct of Controller?
2) In effect, from point 1, I did think to add them in __construct of subclass but ofcourse it override the __construct of abstract Class
3) Tomorrow I want create a ToolboxController Class. Let's say it's scope will be perform some task (e.g. "extract first X characters from a text", "format data according to user settings"), all code pieces that I will/can reuse in other part of app.
In this case I will need to refactor all website changing from:
Controller <= FrontendController
Controller <= BackendController
to
Controller <= ToolboxController <= FrontendController
Controller <= ToolboxController <= BackendController
where <= mean "extends" ?
It seems very very stupid question and easy, but I would understand logic process of add new functions to a born-small website to a large portal.
You do it the Wrong way. The root of your Problem is, you have no Model.
A Model is not a simple class, it as a whole abstraction layer.
Domain Object
Value Object
Database Mapper
Service
Read this good answer, to learn about it.
At the end, you Goal should be something like this this
$model = new Model();
$controller = new Controller($model);
$view = new View($model);
The View and the Controller shares the same Model, and they get it. They don't know how to obtain.
I have never used Interfaces or Abstract Classes in PHP, but have come to a point where I want to support similar but different types of the same object (in this case Network Switches) and possibly add more in the future. I communicate with them via SSH (PHPSecLib) and which the interactions are different, the actual methods would be the same.
In my particular case I believe an Abstract Class, implementing the constants, private variables, connect functions and constructor/destructors would be appropriate, leaving the extended classes ONLY to implement the functionality, where an Interface would just be a template but each extended class would still re-implement methods that are the same between them.
Am I correct in thinking that Abstract Classes are the way to go in this scenario? Do you need to place empty methods in Abstract Classes which are overridden by extended classes or can the extended class have methods that don't exist in the Abstract class?
Example:
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . '/home/devicepo/public_html/include/PHPSecLib');
include('Net/SSH2.php');
include('File/ANSI.php');
abstract class Switch
{
const STATUS_UNKNOWN = "-1";
const STATUS_OFFLINE = "0";
const STATUS_ONLINE = "1";
public $conn;
private $_server;
private $_username;
private $_password;
private $_bashshell;
public function __construct($server, $username, $password)
{
if (!$server)
die("Switch configuration not Defined");
$this->_server = $server;
$this->_username = $username;
$this->_password = $password;
}
public function connect()
{
// Establish new SSH2 Connection
$this->conn = new Net_SSH2($this->_server, 22);
if(!$this->conn->login($this->_username, $this->_password))
{
die("Failed to connect to Switch: " . $this->_server);
}
}
public function enable_port($port)
{
// Define in extended classes
}
public function disable_port($port)
{
// Define in extended classes
}
}
?>
I believe that in your case the Abstract class is the way to go. The reasons are that:
Your child classes share a big part of code with the parent class
Your child classes have a notion of similarity.
To be more specific regarding point 2, keep in mind that two classes implementing the same interface are not necessarily related. The interface represents an ability. Consider for example an airplane and a bird. Both can implement a flyable interface, but except from that they are not related in any other way. On the other hand, your child classes have a similar type. They are all switches. So your abstract class could be
abstract class BasicSwitch { // You cannot use the name switch
const STATUS_UNKNOWN = "-1";
const STATUS_OFFLINE = "0";
const STATUS_ONLINE = "1";
public $conn;
private $_server;
private $_username;
private $_password;
private $_bashshell;
public function __construct($server, $username, $password) {
if (!$server) die("Switch configuration not Defined");
$this->_server = $server;
$this->_username = $username;
$this->_password = $password;
}
public function connect() {
// Establish new SSH2 Connection
$this->conn = new Net_SSH2($this->_server, 22);
if(!$this->conn->login($this->_username, $this->_password)) {
die("Failed to connect to Switch: " . $this->_server);
}
}
abstract public function enable_port($port);
abstract public function disable_port($port);
}
and a concrete implementation could be
class CiscoSwitch extends BasicSwitch {
public function __construct($server, $username, $password) {
parent::__construct($server, $username, $password);
}
public function enable_port($port) {
echo 'Port is enabled';
}
public function disable_port($port) {
echo 'Port is disabled';
}
}
The most important think to keep in mind here is that CiscoSwitch is also a type of BasicSwitch. This means that a CiscoSwitch can be used anywhere a BasicSwitch is expected. So consider that you have a Rack with many switches and you want to enable the same port an all switches in the rack. Here is your Rack class:
class Rack {
protected $switches;
public function addSwitch(BasicSwitch $switch) {
$this->switches[] = $switch;
}
public function enable_ports($port) {
foreach($this->switches as $switch) {
$switch->enable_port($port);
}
}
}
If you type hint on the Abstract class (BasicSwitch) and not on the implementation you can be sure that any switch inside the rack can enable and disable its ports. You really don't care which switch it is. You just know that it can do the job.
This is what code on an interface and not on implementation is all about. This way your code is open for extension but closed for modification. You can create as many switch types as you want but you will be sure that the Rack class will continue to work.
Probably a silly question, I have many classes in PHP with this template:
class SomeTable {
private $db;
private $prefix;
private $tbl_name;
function __construct($db, $tbl_name) {
$this->db = $db;
$this->prefix = $db->tblPrefix();
$this->tbl_name = $tbl_name;
$this->install();
}
private function install() {
$sql = "CREATE TABLE IF NOT EXISTS...";
$this->db->query($sql, null);
}
// query functions
...
}
I have one of these classes to represent each table in the database.
The 3 private variables at the top must be available in each class,
and they are set in the constructor.
The constructor is the same for every class.
The install() function is different for every class because it is
used to create the database table. (I like to keep it here because
I can keep looking back at it while I'm writing/editing queries).
Do I then create an abstract class with the 3 variables, constructor, empty install() function and implement it in each class? Will it work the same for me?
I'm sorry if it's a dumb question, I've really never used classes/inheritance before in PHP.
Do I then create an abstract class with the 3 variables, constructor,
empty install() function and implement it in each class? Will it work
the same for me?
Yes. The 3 variables will have to be protected now though, instead of private, since they need to be access from child classes. Something like this:
abstract class DBTable{
protected $db;
protected $prefix;
protected $tbl_name;
function __construct($db, $tbl_name) {
$this->db = $db;
$this->prefix = $db->tblPrefix();
$this->tbl_name = $tbl_name;
}
abstract function install();
}
class SomeTable extends DBTable {
private function install() {
$sql = "CREATE TABLE IF NOT EXISTS...";
$this->db->query($sql, null);
}
}
If you extend a class you will inherit any public or protected methods that exist in the parent class. So if you have a class like so:
class Database {
public function get_database(){
return 'blah';
}
}
And then you extend the class like so:
class Blah extends Database {
...
}
Now, the Blah class will inherit the method get_database() so both Database::get_database() and Blah::get_database() will return the same thing. You can also use the parent:: special name to target the extended class. Note: private methods are only available in the class in which they are instantiated and are not inherited.
I should also note that you can override methods by using the same method name in the child class. So if you write a get_database() method within the Blah class, it will take precedence over the parent's method of the same name.