class KD_DB extends PDO {
protected static $dbOne = '';
protected static $dbTwo = '';
public function setVariable ($alias,$content){
switch($alias){
case'one': self::$dbOne = $content; break;
case'two': self::$dbTwo = $content; break;
}
}
}
Is there a way to create these dynamically?
Something like this to create the protected static variables
public function setVariable ($alias,$content){
self::${$alias} = $content;
}
It did not work, but I suspect it is because I need it to be static to make it to work with a third class that extends this one...
If you only have the two variables, it may be easier (with more appropriate names) to set them using a static function for each one, something like...
class KD_DB {
public static $dbOne = '';
public static $dbTwo = '';
public static function setOne ($content){
self::$dbOne = $content;
}
}
KD_DB::setOne("value for one");
var_dump(KD_DB::$dbOne);
(code with minor changes to show the process)
But if you wanted a more open ended method, I would go for an associative array as the static variables and then use the 1 method (like you currently are) to set the value in the array...
class KD_DB {
public static $data = [];
public static function setVariable ($alias,$content){
self::$data[$alias] = $content;
}
}
KD_DB::setVariable("three", "value for three");
var_dump(KD_DB::$data);
this method can have issues if you mistype a variable reference which should be found during testing though, but does offer flexibility.
Related
Got a stucking situation which produces unnecessary IDE warnings and may lead to cleaning-up used code.
I think the best solution is to add some PHPDoc at the right place, but couldn't find the right place yet because of some constraints, as explained in the below examples.
IDE: PhpStorm
Result:
<?php
/*
* Generic result class, widely used, so can't touch it ¯\_(ツ)_/¯
*/
class Result {
public $data;
public function __construct() {
return $this;
}
public function setData($data) {
$this->data = $data;
return $this;
}
}
Customer:
<?php
class Customer {
public string $name = '';
public string $email = '';
public function __construct() {
$this->name = 'John Smith';
$this->email = 'test#example.com';
}
public function getCustomer(): Result {
return (new Result())->setData(new self());
}
public function reverseName(): string { // ❌ Unused element: 'reverseName'
$parts = explode(' ', $this->name);
return implode(' ', array_reverse($parts));
}
}
Controller:
<?php
require_once 'vendor/autoload.php';
$john = (new Customer())->getCustomer();
// ℹ️ $john->data is an instance of the Customer class.
// How should I tell to the IDE this ^ ❓
$reversedName = $john->data->reverseName(); // ❌ Cannot find declaration to go when trying to navigate to the method
exit($reversedName);
Tried many and many options, but the only one which works is by adding a PHPDoc to Result's $data property. Can't touch it because it's widely used in the project...
LE:: The Customer class has a lot of methods similar to reverseName(), so assigning the data property to a new variable is also difficult to write: /** #var Customer $john */ $john = (new Customer())->getCustomer()->data;
You could try to use another PhpStorm feature called advanced metadata.
Firstly you need to configure metadata in the next way
namespace PHPSTORM_META {
override(\App\Result::getData(0), map(['' => '#']));
}
then add getter to your Result class
public function getData()
{
return $this->data;
}
and use this getter in the next way
$john->getData(Customer::class)->reverseName();
The main idea is to use class name as an argument of the getter method and PhpStorm will know what class object this getter will return.
I'm using a Form class for getting the values of a form in static way. Everything is great. But I want to do it dynamically. I want a form class that will do the job for different forms. In display() method I'm getting value of name, email, password, phone etc. I want that when there are more or less value or in another form the Form class do the job for me dynamically. How can i do that?
//This is Register.php
public function display()
{
Form::setname($_POST['name']);
Form::email($_POST['email']);
Form::password($_POST['pass']);
Form::repassword($_POST['rpass']);
Form::phone($_POST['phone']);
list($name,$b,$c,$d,$e)=Form::getall();
}
<?php
//This is Form.php
class Form
{
private $name;
private $email;
private $pass;
private $rpass;
private $phone;
public static function setname($name)
{
$this->name=$name; // Using $this when not in object context
}
public static function email($email)
{
$this->email=$email;
}
public static function password($pass)
{
$this->pass=$pass;
}
public static function repassword($rpass)
{
$this->rpass=$rpass;
}
public static function phone($phone)
{
$this->phone=$phone;
}
public static function getall()
{
$a=$this->name;
$b=$this->email;
$c=$this->pass;
$d=$this->rpass;
$e=$this->phone;
return [$a,$b,$c,$d,$e];
}
}
There are a few things you have to do to get this right. First, avoid statics. Conceptually each form should be represented by it's own object. Second, use magic methods provided by PHP. Those are very powerful and if used properly can allow for some crazy good designs. Third, use array notation with a single name for all your input elements within a single form, for example, for the name of your form elements: use something like: User[email] instead of just email and User[name] instead of just name and so on and so forth.
Keeping these in mind, the form class could be as follows:
class Form{
private $variables = array();
public function __get($name){
$returnValue = null;
if(isset($this->variables[$name])){
$returnValue = $this->variables[$name];
}
return $returnValue;
}
public function __set($name, $value){
$this->variables[$name] = $value;
}
public function getAll(){
return $this->variables;
}
}
This should be enough for the functionality that you require. In addition, you can add a convenience function that I have found very useful. This could be named as a setAttrubites or setAll function. It would be like this:
public function setAll($allData){
foreach($allData as $key => $data){
$this->variables[$key] = $data;
}
}
This will allow you to set all variables in one swoop using a command like this:
$form = new Form();
$form->setAll($_POST['User']);
In order to make this possible, as I mentioned before, all your input elements should be grouped in an array. So the input elements would be like this:
<input type="text" name="User[name]" />
<input type="text" name="User[email]" />
Hope you get the drift...
You can try to add an array of new variables to the class, much like
$dynamic_form_elements = array();
public static function dynamic_element($element, $value) {
$this->dynamic_form_elements[$element] = $value;
}
After that, simply put the $dynamic_form_elements variable to your list for returning in the getAll() method.
return [$a,$b,$c,$d,$e,$dynamic_form_elements];
It's working fine I just needed a setvalue and getvalue method in Form calss .And call it each time for a specific field in display() method.Is it good or there are any better way?
class Form{
private $value;
public function setvalue($value)
{
$this->value=$value;
}
public function getvalue()
{
$a=$this->value;
return $a;
}
}
public function display()
{
$newform=new Form();
$newform->setvalue($_POST['name']);
$name=$newform->getvalue();
$newform->setvalue($_POST['email']);
$b=$newform->getvalue();
$newform->setvalue($_POST['pass']);
$c=$newform->getvalue();
$newform->setvalue($_POST['rpass']);
$d=$newform->getvalue();
$newform->setvalue($_POST['phone']);
$e=$newform->getvalue();
}
I am in the process of re educating myself in the programming of OOP
in PHP.
I have been under the erroneous assumption that all variables not static inside a class def
had to be proceeded with $this->. I finally stumbled over myself with a variable naming collision
and am now relearning, somewhat, the way of php OOP.
My present question is:
Can you mark a method property set with $this-> as public, private, or protected?
I have done;
class _DEMO
{
private $this->someVar = 'whatever';
}
and I get a syntax error.
then:
class _DEMO
{
public function __construct($_ip)
{
$this->ip = $_ip; // <<< how can I set access on this property?
}
}
As of now I don't know how to use properties with access levels set
other than to declare static properties.
OK, so I tried
class _DEMO
{
public $_someVar = 'so and so';
}
$_a = new _DEMO()
print $_a->someVar // NADA
So, I take it that the variable can be declared this way but not initialized?
on second thought, OOPs! I saw the problem with variable reference $_testy and $this->testy, should be $this->_testy
class _DEMO
{
private static $_doTell = 'Well??...';
private $_testy = "So What? ";
public function __construct($_ip)
{
$this->_testy .= " right Now?";
$this->ip = $_ip;
$this->soWhat = 'Boo!...';
}
public function getVar($_var, $_addon)
{
$this->setVar($_var, $_addon);
switch($_var)
{
case 'soWhat':
return $this->soWhat;
break;
case 'ip':
return $this->ip;
break;
case 'doTell':
return self::$_doTell;
break;
default:
break;
}
}
private function setVar($_var, $_input)
{
switch($_var)
{
case 'soWhat':
$this->soWhat .= $_input;
break;
case 'ip':
$this->ip .= $_input;
break;
case 'doTell':
self::$_doTell .= $_input;
break;
default:
break;
}
}
}
$_test = new _DEMO('Hello??...');
print "Test result 1: ".$_test->ip;
print "<br>Test result 2: ".$_test->getVar('doTell', ' So, how old are you??');
print "<br>Test result 3: \$_test::\$_doTell; Fatal error: Cannot access private property _DEMO::$_doTell";
print "<br>Test result 4: ".$_test->testy; // <<<< prints " right Now?" without errors about trying to
//access private members
Properties are declared at the start of the class like:
public $property1;
private $property2;
protected $property3;
Then,
1. all properties can be accessed from any method of the same class like $this->property.
2. $property1 can be accessed from all methods in ANY class.
3. $property2 can be accessed from all methods in the SAME class.
4. $property3 can be accessed from all methods in the SAME class and classes which EXTEND THE SAME class.
E.g. You can access a private property from a public method:
class A {
private $property;
public function getProperty() {
return $this->property
}
Then, in a controller, you could do:
$obj = new A;
$property = $obj->getProperty();
but not:
$obj = new A;
$property = $obj->property;
Sure, you can:
class MySampleClass {
/**
* #var string
*/
private $aStringVariable;
/**
* #param string $anIP
*/
protected function __construct( $anIP ) {
$this->aStringVariable = $anIP;
}
}
// How to use the class
$myClassObject = new MySampleClass( '192.168.0.1' );
You might wish to download the eval-version of PHPStorm, a PHP IDE. The IDE might help, since it points out errors while you type and PHPStorm provides auto-completion.
Additionally, have a look in the PHP Wiki of StackOverflow. The Wiki provides valuable information.
Here is a simple example of using property.
class HelloProperty{
private $mySimpleProperty;
public function setSimpleProperty($mySimpleProperty){
$this->mySimpleProperty = $mySimpleProperty;
}
public function getSimpleProperty(){
return $this->mySimpleProperty;
}
}
$obj = new HelloProperty();
$obj->setSimpleProperty('Hello Property');
echo $obj->getSimpleProperty();
:)
Supposed there is a function in a \AW\Blog\Model\post.php.there is a function in it.
public function PreNext($type){
$id = $this->_data['post_id'];
$blog = Mage::getResourceModel('blog/post_collection');
$blog->getSelect()->where('post_id>?',$id);
return $blog->getFirstItem();
}
why it write $this->_data['post_id']; could i write it with another.
what are the four lines meaning which in the function within magento.? many thanks.
the post.php
class AW_Blog_Model_Post extends Mage_Core_Model_Abstract{
const NOROUTE_PAGE_ID = 'no-route';
protected function _construct(){
$this->_init('blog/post');
}
public function load($id, $field=null){
return $post = parent::load($id, $field);
}
public function noRoutePage(){
$this->setData($this->load(self::NOROUTE_PAGE_ID, $this->getIdFieldName()));
return $this;
}
public function getShortContent(){
$content = $this->getData('short_content');
if(Mage::getStoreConfig(AW_Blog_Helper_Config::XML_BLOG_PARSE_CMS)){
$processor = Mage::getModel('core/email_template_filter');
$content = $processor->filter($content);
}
return $content;
}
public function getPostContent(){
$content = $this->getData('post_content');
if(Mage::getStoreConfig(AW_Blog_Helper_Config::XML_BLOG_PARSE_CMS)){
$processor = Mage::getModel('core/email_template_filter');
$content = $processor->filter($content);
}
return $content;
}
public function loadByIdentifier($v) {
return $this->load($v, 'identifier');
}
}
This is code of a custom extension, so only people having this extension can know, what this post.php file contains, and whether you can get the value using other ways than $this->_data['post_id'].
If the extension uses standard Magento Getters/Setters, maybe $this->getPostId() may work, too.
The rest loads a collection of records having a post_id greater than $this->_data['post_id'], but returns only the first record found.
Update
The class you posted extends
Mage_Core_Model_Abstract
which in turn extends
Varien_Object
in a standard Magento OOB.
The Varien_Object class defines the standard getters/setters I was talking about, so yes, you can also use $this->getPostId() to get the value.
To understand how these getters/setters work, I'd recommend to check the Varien_Object and read about PHPs magic methods, like __call(), __get() and __set().
OK. here is what I'm trying to do:
class Image{
public $_image;
public $_extension;
public $_mime;
public $_size;
public $_location;
public $_description;
public function __construct($image, $location){
$this->_image = $image;
$this->_location = $location;
$this->_extension = getExtension();
$this->_mime = getMime();
$this->_size = getSize();
}
private functions fallow.....
}
But I keep getting an internal server error when I try to run it. When I comment out the method calls it works. So the question is can I call methods from inside the constructor or am I doing something wrong with the methods.
Do your functions getExtension, getMime and getSize exist? Are they methods on this class? If they are methods, they need to be called with $this->... as in
$this->_extension = $this->getExtension();
If they are not methods, and are functions, you need to make sure the files that contain/define them are loaded before you run the constructor.
Well ..this fragment of code will work as expected:
class Foo
{
protected $secret = null;
public function __construct( $data )
{
$this->secret = $this->makeSecret($data);
}
public function makeSecret( $data )
{
return md5( $data );
}
}
$bar = new Foo( 'lorem ipsum' );
That is not a problem.
But you should know, that is considered to be a bad practice - to do computation/work in the constructor. It makes that class practically untestable. Instead, if you need to perform some computation before "releasing" the object to the rest of the code, you should use a factory. Something along the lines of :
class ImageFactory
{
public function build($image, $location)
{
$instance = new Image($image, $location);
$instance->prepare();
return $instance;
}
}
The class would need some changes:
class Image
{
protected $_image; // you were leaking abstraction
protected $_extension;
protected $_mime;
protected $_size;
protected $_location;
protected $_description;
public function __construct($image, $location)
{
$this->_image = $image;
$this->_location = $location;
}
public function prepare()
{
$this->_extension = $this->getExtension();
$this->_mime = $this->getMime();
$this->_size = $this->getSize();
}
private functions fallow.....
}
Now when you need to create new object you do:
$factory = new ImageFactory;
$image = $factory->build( $file, '/uploads/' );
Of course the instance of ImageFactory can be reusable, and if all your images use the same $location, then you would pass that variable to factory at the initialization. And the factory would be able to "remember it" and pass to all the images it creates:
$factory = new ImageFactory('/uploads/');
$img1 = $factory->build( $file );
$img2 = $factory->build( $something_else );
This is actually how one should deal with creating multiple objects, which all need access to same DB connection instance.
Yes, you can call methods from within the constructor. Remember that the __construct() magic method was implemented in PHP 5. Prior to that, you created a function named the same as your class which acted as your constructor so depending on your PHP version, that could be a problem.
Additionally, the function calls you are making, are they in the class or external? If they are inside the class you need to call them this way:
$this->_extension = $this->getExtension();
You didnt specified what error you are expiriencing clearly. But try calling you class methods even inside the class using this keyword, otherwise it would not work:
public function __construct($image, $location)
{
$this->_image = $image;
$this->_location = $location;
$this->_extension = $this->getExtension();
$this->_mime = $this->getMime();
$this->_size = $this->getSize();
}
Would be a better idea to post your code for the methods you wrote. There could be something wrong within them as well. Possibly forgetting to return a result or something...