I just want to create function just like getFieldname() that is in magento.
For Ex:
In Magento
getId() - returns value of ID field
getName() - returns value of Name field
How can I create like that function? Kindly help me in this case..
I want to do just Like Below code,
Class Called{
$list=array();
function __construct() {
$this->list["name"]="vivek";
$this->list["id"]="1";
}
function get(){
echo $this->list[$fieldname];
}
}
$instance=new Called();
$instance->getId();
$instance->getName();
You can use the magic method __call to solved your situation
<?php
class Called
{
private $list = array('Id' => 1, 'Name' => 'Vivek Aasaithambi');
public function __call($name, $arguments) {
$field = substr($name, 3);
echo $this->list[$field];
}
}
$obj = new Called();
$obj->getId();
echo "<br/>\n";
$obj->getName();
?>
You can read more about __call in:
http://php.net/manual/en/language.oop5.overloading.php#object.call
Check the implementation of Varien_Object, the __call method is probably what you are looking for, I think. http://freegento.com/doc/de/d24/_object_8php-source.html
This will basically "capture" any non-existing method calls and if they are in the shape $this->getWhateverField, will try to access that property. With minor tweaks should work for your purposes.
See if this is what you want:
Your class should be inherited from another class (Super class) which defines your required methods.
class Super {
public function getId(){
return $this->list["id"];
}
public function getName(){
return $this->list["name"];
}
}
class Called extends Super {
var $list = array();
function __construct() {
$this->list["name"]="vivek";
$this->list["id"]="1";
}
}
$instance=new Called();
echo $instance->getId(); // 1
echo $instance->getName(); //vivek
Related
Consider this class arrangement - and in particular the magic function __invoke:
class Barman {
public function __construct() {
// .. .constructor stuff - whatever
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function __invoke($barman_id) {
echo "I have been invoked";
return $this->arr_barmen[$barman_id];
}
public function aBarFunc($param) {
return "yes it worked ," .$param;
}
}
class Foo {
public $myBar;
public function __construct() {
$this->myBar = new Bar();
}
}
I want to write syntax like this
$company = new Foo();
$company->myBar('john')->makeDrink();
Preferred result:
"vodka martini, shaken"
Actual result:
"Call to undefined method Foo::myBar()"
Invoking myBar() with the magic method should return a barman Object upon which you can call any of the barman's public methods
But now consider this (which does work)
$company = new Foo();
$myBar = $company->myBar;
$drink = $myBar('john')->makeDrink();
echo $drink;
// Result:
// I have been invoked
// vodka martini, shaken
So what's going on? I don't like that workaround - it's not sleek.
I need it to work this way:
$company->myBar('john')->makeDrink();
Please help? :-)
I believe you can just add braces around it:
$company = new Foo();
$drink = ($company->myBar)('john')->makeDrink();
echo $drink; // vodka martini, shaken
This is being caused by an ambiguity in the call you're trying to make:
$company->myBar('john')->makeDrink();
Because myBar is a property, the PHP interpreter isn't expecting it to be callable. It is parsing it as an attempt to call a method called myBar() which doesn't exist, and is thus throwing the error.
The direct way to resolve this is to clarify the ambiguity for the interpreter. You do this by adding curly braces around the property, as follows:
$company->{myBar}('john')->makeDrink();
The code is now explicit that myBar is a property and should be accessed as such, but that it contains a value that is callable and that you wish to make that call.
This whole topic is complicated (slightly) by the fact that PHP 5.x and PHP 7.x behave differently with regard to how they default to handling these kinds of ambiguity. PHP 7 changed the defaults in order to correct some internal inconsistencies within the language. The result is that in situations like this where you have an ambiguity, if you want your code to work across both PHP 5.x and 7.x, you should always use the braces to explicitly define how you want it to work, regardless of whether your code works for you without them.
There is some documentation about this change in the PHP 7.0 upgrade notes, although the examples given don't cover your exact situation.
To attain chaining you have to return the Barman object in invoke.
class Barman {
public function __construct() {
// .. .constructor stuff - whatever
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function __invoke($barman_id) {
echo "I have been invoked";
return $this->arr_barmen[$barman_id] = new Barman();
}
public function aBarFunc($param) {
return "yes it worked ," . $param;
}
}
class Foo {
public $myBar;
public function __construct() {
$this->myBar = new Bar();
}
// create a function with variable name to invoke the object
public function myBar($name) {
$mybar = $this->myBar;
return $mybar($name);
}
}
Thank you for the responses. I devised a cute workaround as follows:
class Barman {
public function __construct() {
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function getBarman($barman_id) {
return $this->arr_barmen[$barman_id];
}
public function __invoke($barman_id) {
echo "I have been invoked \n";
return $this->arr_barmen[$barman_id];
}
}
class Foo {
private $_myBar;
public function __construct() {
$this->_myBar = new Bar();
}
// The fix
public function myBar($barman_id) {
return $this->_myBar->getBarman($barman_id);
}
}
Usage:
$company = new Foo();
$drink = $company->myBar('john')->makeDrink();
echo $drink; // vodka martini, shaken
How it works?
Foo->myBar becomes private (Foo->$_myBar);
we create a public function with the name myBar inside Foo;
we create a "getBarman" fuction inside Bar which is called from Foo->myBar('john')
A few more steps - and now there's no ambiguity - Foo->myBar() IS always a function.
Cheers
M
The code sample is an simple example for what i'm working on.
I have 2 classes in php.
class Wrap {
public function wrapA($arg){
return 'A'.$arg.'A';
}
public function wrapB($arg){
return 'B'.$arg.'B';
}
}
class Child extends Wrap {
public $OUT;
public function wrapA($arg){
$this->OUT .= parent::wrapA($arg);
}
public function wrapB($arg){
$this->OUT .= parent::wrapB($arg);
}
public function __destruct(){
echo $this->OUT;
}
}
$X = new Child();
$X->wrapA(
$X->wrapB('CC')
);
The Output here is "BCCBAA". But what I try to achieve is "ABCCBA".
The "Wrap" class must be in this form.
… and if I have the following method-calls:
$X->wrapB( $X->wrapA('1') );
$X->wrapA( $X->wrapB('aa') .$X->wrapA('bbb') .$X->wrapB(
$X->wrapA('cccc') ) );
… i want to have the following output: BA1ABABaaBAbbbABAcccABA
Is there an other way?
I also want the Wrap-Class to work alone (without Child) … this is why the methods have return-value.
But in Child-Class I want to write the return-values in a variable.
THX in advance!
That's because $X->wrapB('CC') doesn't return anything and gets cast to an empty string by the time $X->wrapA() is called, thus A gets wrapped around nothing.
However, because you append BCCB to $X->OUT, by the time you call $X->wrapA(), it appends AA to that, leading to BCCBAA.
After looking at the question again, I feel that it should be solved in another way; this is something to consider:
class Wrap
{
// The wrapping itself can be declared as a static method
protected static function wrapWithChar($arg, $ch)
{
return $ch . $arg . $ch;
}
}
class Child extends Wrap
{
protected $OUT;
// we allow the internal state to be set upon construction
public function __construct($s = '')
{
$this->OUT = $s;
}
// no arguments required here, this gets applied on the internal state
public function wrapA()
{
$this->OUT = self::wrapWithChar($this->OUT, 'A');
// return instance to allow chaining
return $this;
}
public function wrapB()
{
$this->OUT = self::wrapWithChar($this->OUT, 'B');
return $this;
}
public function __toString()
{
return $this->OUT;
}
public function __destruct(){
echo $this->OUT;
}
}
// initialize with 'CC'
$X = new Child('CC');
// wrap B around it; becomes 'BCCB'
$X->wrapB();
// wrap A around that; becomes 'ABCCBA'
$X->wrapA();
// example of chaining
$Y = new Child('ZZ');
// wrap B then A around it; becomes 'ABZZBA'
$Y->wrapB()->wrapA();
Old answer
To make Child appear as something that Wrap can perform on, you could make use of the __toString() magic method (using instanceof would be more explicit, but also a bit more work):
class Child extends Wrap
{
public $OUT;
public function wrapA($arg)
{
$this->OUT = parent::wrapA($arg);
return $this;
}
public function wrapB($arg)
{
$this->OUT = parent::wrapB($arg);
return $this;
}
public function __toString()
{
return $this->OUT;
}
public function __destruct(){
echo $this->OUT;
}
}
Each wrapX() method now returns the instance itself, and __toString() gets called whenever it needs to be wrapped.
The above will generate the correct result.
I added this to my favorites as an interesting puzzle to solve.
And then found that it wasn't that complicated after I woke up and looked at the problem again.
I honestly don't think you should be using subclassing at this point since technically Child is not logically the a child of the Wrap class, it essentially seems to be a guy that wants to store the output of wrap's results.
so.. Here's my modifications that works with your original interface. Hope it's good for you ;).
It makes some very magical use of magic methods.
<?php
class Wrap {
public function wrapA($arg){
return 'A'.$arg.'A';
}
public function wrapB($arg){
return 'B'.$arg.'B';
}
}
class WrapReader{
protected $wrapper;
protected $currentResult;
public function __construct(Wrap $wrapper)
{
$this->wrapper = $wrapper;
}
public function __call($method,$argument)
{
$argument = $argument[0];
if(!method_exists($this->wrapper,$method))
throw new MethodNotFoundException('Method: '.$method.'() does not exist in class: '.get_class($this->wrapper));
$this->currentResult = $this->wrapper->$method($argument);
return $this->currentResult;
}
public function __destruct(){
echo $this;
}
public function __toString()
{
return $this->currentResult;
}
}
class MethodNotFoundException extends Exception{}
The usage:
$reader = new WrapReader(new Wrap());
echo $reader->wrapB( $reader->wrapA('1') );
echo $reader->wrapA( $reader->wrapB('aa') .$reader->wrapA('bbb') .$reader->wrapB( $reader->wrapA('cccc') ) );
echo '<br>';
Outputs BA1ABABaaBAbbbABAccccABA
Which is what you posted in your original question.
I have a similar code snippet like this
class Search
{
public function search($for, $regEx, $flag) //I would like this to be the constructor
{
// logic here
return $this;
}
}
Then I have another class that creates an object from it, later than tries to use the object.
class MyClass
{
public function start()
{
$this->search = new Search();
}
public function load()
{
$this->search($for, $regEx, $flag);
}
}
My question is, is it possible to create an object first THEN give it the parameters?
I know there are some way around this BUT I only ask because I want to use the object like this
$this->search($params);
// I have my methods chained, so I could use it in one line like
// $this->search($params)->hasResults();
if ($this->search->hasResults()) {
echo 'found stuff';
} else {
echo 'didn't find anything';
}
The way I have it set up right now, I would need to use it like this
$this->search->search($params);
if ($this->search->hasResults()) {
echo 'found stuff';
} else {
echo 'didn't find anything';
}
I have a method called search() that does the logic, and I don't want to be redundant in my naming nor do I want to change the name of the method.
I know another way to keep the visual appeal sane I could pass a variable like so
$search = $this->search->search($params);
then
$search->hasResults();
At the same time I am trying to introduce myself to new OOP concepts and learn from them. Would this require passing things by reference? or setting up some type of magic method?
While the previous anwsers show that you can, I wouldn't use it, because it breaks the concept of encapsulation. A proper way to achieve what you want is the following
class Search
{
public function __constructor($for='', $regEx='', $flag='')
{
$this->Setup($for, $regEx, $flag);
}
public function Setup($for, $regEx, $flag)
{
//assign params
//clear last result search
//chain
return $this;
}
public function search()
{
// logic here
return $this;
}
}
In this way, you can reuse the object and have the params in the constructor, without breaking encapsulation.
Yes it is possible
See the below example
<?php
class a{
public $a = 5;
public function __construct($var){
$this->a = $var;
}
}
$delta = new a(10);
echo $delta->a."\n";
$delta->__construct(15);
echo $delta->a."\n";
Output will be:
10 15
Yep, you can.
class Example {
public $any;
function __counstruct($parameters,$some_text) {
$this->any=$some_text;
return $this->any;
}
}
You can call constructor:
$obj = new Example (true,'hello');
echo $obj->any;
$obj->__construct(true,'bye-bye');
echo $obj->any;
I was able to create the visual coding I wanted by using the __call() magic method like this
public function __call($name, $params)
{
$call = ucfirst($name);
$this->$name = new $call($params);
}
from there I could use this
$this->test->search($params);
$this->test->search->hasResults();
I of course now set the search() method to the class constructor
I came to know about mixins.So my doubt is, is it possible to use mixins in php?If yes then how?
Use Trait introduced in PHP 5.4
<?php
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>
which prints Hello World!
http://php.net/manual/en/language.oop5.traits.php
This answer is obsolete as of PHP 5.4. See Jeanno's answer for how to use traits.
It really depends on what level of mixins you want from PHP. PHP handles single-inheritance, and abstract classes, which can get you most of the way.
Of course the best part of mixins is that they're interchangeable snippets added to whatever class needs them.
To get around the multiple inheritance issue, you could use include to pull in snippets of code. You'll likely have to dump in some boilerplate code to get it to work properly in some cases, but it would certainly help towards keeping your programs DRY.
Example:
class Foo
{
public function bar( $baz )
{
include('mixins/bar');
return $result;
}
}
class Fizz
{
public function bar( $baz )
{
include('mixins/bar');
return $result;
}
}
It's not as direct as being able to define a class as class Foo mixin Bar, but it should get you most of the way there. There are some drawbacks: you need to keep the same parameter names and return variable names, you'll need to pass other data that relies on context such as func_get_args_array or __FILE__.
Mixins for PHP (PHP does not implement Mixins natively, but this library will help)
First google result for "php5 mixin": http://www.sitepoint.com/forums/php-application-design-147/ruby-like-mixins-php5-332491.html
First google result for "php mixin": http://www.advogato.org/article/470.html
Short answer: yes, but not natively (yet, evidently, as #mchl notes). Check those out.
Longer answer: if you're using runkit, checkout runkit_method_copy(): "Copies a method from class to another."
I based mixins functionality on the blog entry found at jansch.nl.
class Node
{
protected $__decorator_lookup = array();
public function __construct($classes = array())
{
foreach($classes as $class)
if (class_exists($class))
{
$decorator = new $class($this);
$methods = get_class_methods($decorator);
if (is_array($methods))
foreach($methods as $method)
$this->__decorator_lookup[strtolower($method)] = $decorator;
}
else
trigger_error("Tried to inherit non-existant class", E_USER_ERROR);
}
public function __get($name)
{
switch($name)
{
default:
if ($this->__decorator_lookup[strtolower($name)])
return $this->__call($name);
}
}
public function __call($method, $args = array())
{
if(isset($this->__decorator_lookup[strtolower($method)]))
return call_user_func_array(array($this->__decorator_lookup[strtolower($method)], $method), $args);
else
trigger_error("Call to undefined method " . get_class($this) . "::$method()", E_USER_ERROR);
}
public function __clone()
{
$temp = $this->decorators;
$this->decorators = array();
foreach($temp as $decorator)
{
$new = clone($decorator);
$new->__self = $this;
$this->decorators[] = $new;
}
}
}
class Decorator
{
public $__self;
public function __construct($__self)
{
$this->__self = $__self;
}
public function &__get($key)
{
return $this->__self->$key;
}
public function __call($method, $arguments)
{
return call_user_func_array(array($this->__self, $method), $arguments);
}
public function __set($key, $value)
{
$this->__self->$key = $value;
}
}
class Pretty extends Decorator
{
public function A()
{
echo "a";
}
public function B()
{
$this->b = "b";
}
}
$a = new Node(array("Pretty"));
$a->A(); // outputs "a"
$a->B();
echo($a->b); // outputs "b"
EDIT:
As PHP clone is shallow, added __clone support.
Also, bear in mind that unset WON'T work (or at least I've not managed to make it work) within the mixin. So - doing something like unset($this->__self->someValue); won't unset the value on Node. Don't know why, as in theory it should work. Funny enough unset($this->__self->someValue); var_dump(isset($this->__self->someValue)); will produce correctly false, however accessing the value from Node scope (as Node->someValue) will still produce true. There's some strange voodoo there.
I'm trying to get data from a class in php5, where the data in the class is private and the calling function is requesting a piece of data from the class. I want to be able to gain that specific piece of data from the private variables without using a case statement.
I want to do something to the effect of:
public function get_data($field)
{
return $this->(variable with name passed in $field, i.e. name);
}
You could just use
class Muffin
{
private $_colour = 'red';
public function get_data($field)
{
return $this->$field;
}
}
Then you could do:
$a = new Muffin();
var_dump($a->get_data('_colour'));
<?php
public function get_data($field)
{
return $this->{$field};
}
?>
You may want to look at the magical __get() function too, e.g.:
<?php
class Foo
{
private $prop = 'bar';
public function __get($key)
{
return $this->{$key};
}
}
$foo = new Foo();
echo $foo->prop;
?>
I would be careful with this kind of code, as it may allow too much of the class's internal data to be exposed.