Pass the current class as parameter - php

I have a class like this:
// file /models/person.php
class Person
{
public function create_path()
{
self::log();
path_helper($this); //a global function in other php file
}
public function log()
{
echo "trying to create a path";
}
}
This is the way how Person is instanciated:
//file /tools/Builder.php
include('/models/Person.php');
class Builder
{
public function build()
{
$type = 'Person';
$temp = new $type();
$temp->create_path();
}
}
As you note in Person class, I am calling the object in question with $this reference. But this is not correct because an error is showed:
Message: Undefined variable: this
I suppose that $this reference point to other object or it is unable to work because the object is created from another script. Also, I tried to use self because there was not problem calling methods with that, but as parameter I get:
Message: Use of undefined constant self - assumed 'self'
So, can you guide me to the right direction?

I tested your code out for myself, with a few minor changes. It appears to work properly.
Changed self::log() to $this->log()
Added global function path_helper (I have no idea what this does)
PHP
function path_helper(Person $object)
{
var_dump($object);
}
class Person
{
public function create_path()
{
$this->log();
path_helper($this); //a global function in other php file
}
public function log()
{
echo "trying to create a path";
}
}
class Builder
{
public function build()
{
$type = 'Person';
$temp = new $type();
$temp->create_path();
}
}
$Build = new Builder();
$Build->build();
Result
trying to create a path
object(Person)[2]
Your code is correct and your going in the right direction.

You should call the log method like this:
$this->log();
because using self:: is reserved for static methods.
Also, try calling the path_helper function like this:
path_helper(self);
Hope I could help you. Couldn't test it, but it should work.

Related

Php overloading function issue with Class

I have a called class called ClientPolicy which is like this
class ClientPolicy {
var $serverHost="www.example.com";
var $httpPort = 80;
var $httpsPort = 443;
var $appKey;
var $secKey;
var $defaultContentCharset = "UTF-8";
}
and another class file name SyncAPIClient which looks like this
class SyncAPIClient{
function SyncAPIClient(ClientPolicy $clientPolicy) {
$this->clientPolicy = $clientPolicy;
}
function SyncAPIClient($appKey, $appSecret) {
$this->clientPolicy = new ClientPolicy();
$this->clientPolicy->appKey=$appKey;
$this->clientPolicy->secKey=$appSecret;
}
}
My questions are
1.) If you check the function in SyncAPIClient, you will notice that the ClientPolicy class was passed as a parameter before a variable, what does it really mean? What is the essence of passing a class in function parameter?
2.) I am getting an error "Cannot redeclare SyncAPIClient::SyncAPIClient()" in my script log and the reason is that SyncAPIClient function was called twice in SyncAPIClient class. How can I solve this issue? Is there any better way to write this SyncAPIClient function instead of passing it twice?
The author of this script is nowhere to be found and I am left to fix it.
1) Here the $clientPolicy variable that is passed to this function, needs be a ClientPolicy instance.
In this way, if the argument that is passed is different from an instance of ClientPolice class, an error is generated.
function SyncAPIClient(ClientPolicy $clientPolicy) {
$this->clientPolicy = $clientPolicy;
}
https://wiki.php.net/rfc/typed_properties_v2
https://laravel-news.com/php7-typed-properties
2) The error Cannot redeclare SyncAPIClient::SyncAPIClient() is caused because you are trying to declare two functions called SyncAPIClient ().
If in first SyncAPIClient() method you just want save the $clientPolicy in $this->clientPolicy, you can use the magic method __construct. Or just try changing the name of one of the functions, and the problem should be a problem.
class SyncAPIClient{
__construct(ClientPolicy $clientPolicy) {
$this->clientPolicy = $clientPolicy;
}
function SyncAPIClient($appKey, $appSecret) {
$this->clientPolicy = new ClientPolicy();
$this->clientPolicy->appKey=$appKey;
$this->clientPolicy->secKey=$appSecret;
}
}
https://www.php.net/manual/en/language.oop5.decon.php
http://www.zentut.com/php-tutorial/php-constructor-and-destructor/
Hope this helps!
I would've fix the code you have like this:
class SyncAPIClient
{
private $clientPolicy = null;
function SyncAPIClient(ClientPolicy $clientPolicy = null)
{
if($clientPolicy instanceof ClientPolicy){
$this->clientPolicy = $clientPolicy;
}else{
$this->clientPolicy = new ClientPolicy();
}
}
public function setAuthParams($appKey, $appSecret) {
$this->clientPolicy->appKey=$appKey;
$this->clientPolicy->secKey=$appSecret;
}
}
This way you can instantiate a SyncAPIClient with or without a ClientPolicy.
Without ClientPolicy:
$syncAPI = new SyncAPIClient();
$syncAPI->setAuthParams($apiKey, $apiSecret);
With ClientPolicy:
$clientPolicy = new ClientPolicy();
$clientPolicy->appKey=$appKey;
$clientPolicy->secKey=$appSecret;
$syncAPI = new SyncAPIClient($clientPolicy);
When using class and functions in combination like
Rtin::
Functions nested inside that class Rtin should have different names than that class name
So you shouldn't have function called rtin
However you can call function from outside the class with it's name
From the error you have may be due to:
function you nested in the class or the function outside the class has a duplicate outside the script itself. Like having function mentioned in included function.php file and also mentioned in the script itself so php get confused because function name is written in two php files at the same time
Example of class
class Rtin{
private $data;
private $results;
public function getResultsType(){
return ........
}
}
To call class use
$q = Rtin::getResultsType($data['name']);
In your example. Adapt it to the example I have provide and review the included files for duplicate function .

Passing an instance of a Class with methods to a function PHP

I am struggling with some PHP code here. Like the title says, I am trying to pass an instance of a Class as a parameter to a function (Note, this file is in another file and has a different scope, and thus I need to pass it as a parameter).
This is the code I have currently set up:
// requires built this page, the classes and the functions are in seperate files.
// That's why I need to pass it in as a parameter.
class ClassName {
private $name;
private $age;
public function getAge(){
return $this->age;
}
} $className = new ClassName();
// seperate file
var_dump($className); // works, but has no methods.
function randomFunc($className){
echo $className->getAge(); // call to undefined method className::getAge()
} randomFunc($className);
EDIT 2:
I have uploaded my code here:
http://sandbox.onlinephpfunctions.com/code/99954d61ca4d3f53ce549dab9f8333630633d89c
I hope you people can help me, any help would be much appreciated.
This works fine:
<?php
class ClassName {
private $name;
private $age = 19;
public function getAge(){
return $this->age;
}
}
function randomFunc($className){
echo $className->getAge(); // call to undefined method className::getAge()
}
$className = new ClassName();
randomFunc($className);
Outputs: 19
Your code also runs fine for me, it just outputs nothing since $age is empty.
What version of PHP are you running?

PDO not returning an object, but an array

With the following code, PDO won't return my $parcel as an object, but as an array. There for when i try to call my objects function, it will fail. Every example i have found has done this, in a similar way to mine. What am i doing wrong?
$statement = $this->connection->query($query);
$statement->setFetchMode(PDO::FETCH_CLASS, 'Parcel');
while ($parcel = $statement->fetch()) {
echo $parcel->hello();
}
The Parcel class, if interested.
class Parcel {
public $id;
public $parcel_number;
public $registred_at;
public $shipped_by;
public $shipped_at;
function __construct($parcel_number)
{
$this->parcel_number = $parcel_number;
}
public function hello(){
return "World";
}
}
And im using folder structures to structure the code and an Autoloader, that can probaly affect the PDO's way of calling the object.
While this is the error code
Call to a member function info() on a non-object
This error means the object is null or not instantiated properly, you might need to specify full path to your class.
For example
$statement->setFetchMode(PDO::FETCH_CLASS, 'app\model\Parcel');

Method Chaining and Class Inheritance

I think I have more or less managed to get a grasp on OOP/Inheritance, and the basics of method chaining I think I understood as well. However I am still confused about how to actually use some of it.
I wanted to do something that I've seen when working with Magento before:
In Magento, I've seen some sort of "selector-function" used in method chaining. It's a little hard to put into words, but it was something along the lines of:
$categoryName = Mage::getModel('catalog/category')->load($categoryId)->getName();
It's the load($categoryId) part that interests me, as in, a function that selects some instance of something and allows me to run a function on that specific instance.
Now, I am writing a module that allows me to configure certain promotions on our website. Seeing as we'll have many different promotions and I want them to be easily configurable and modifiable, I wanted to do something similar.
So, if I wanted to be able to do something like this:
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo $prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo $prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
How would the class definition for that have to look like?
This may be much more simple or much more complicated than I anticipate. In either case, thanks a lot!
Edit:
So I did some testing around with the info deceze gave me, but I'm still confused.
Bad naming and putting 2 classes in 1 file aside, here's what I did:
class file:
class Promotion {
private $__arr = array();
public function addPromo($name) {
$this->__arr[$name] = new Promo();
}
public function getPromo($name) {
$this->__arr[$name];
}
}
class Promo {
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $name;
}
}
and the run file:
require_once 'class.php';
error_reporting(E_ALL);
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo 'X: '.$prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo "\n";
echo 'N: '.$prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
This gives me Fatal error: Call to a member function setName() on a non-object in /var/www/test/index.php on line 11.
But why? Shouldn't getPromo() give me back the object?
Thanks again..
Thanks to the great guys here, it works now. In case anyone were to pass by here with the same or a similar question, here's the final, working code:
Classes:
class Promotion {
private $__arr = array();
public function addPromo($name) {
$this->__arr[$name] = new Promo();
}
public function getPromo($name) {
return $this->__arr[$name];
}
}
class Promo {
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
Test file:
require_once 'class.php';
error_reporting(E_ALL);
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo 'X: '.$prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo "\n";
echo 'N: '.$prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
Method chaining is really simple, all it does is use one particular element of PHP's syntax:
When a function returns an object, you can directly continue with -> after that function.
The longhand version can be:
$bar = $foo->bar();
$baz = $bar->baz();
echo $baz;
$foo->bar() returns an object ($bar) which has a method baz(), and that method returns some value ($baz). This can be written in shorthand like so:
echo $foo->bar()->baz();
$foo->bar() still returns an object which has a method baz(), so you can directly call it without assigning it to an intermediate variable. Maybe this makes it more obvious:
echo ( $foo->bar() )->baz();
You're calling the baz() method on whatever $foo->bar() returns.
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
As such, in your above case, all you need to do is to return an object which has the method setName from getPromo. I would assume getPromo is supposed to return some object of, say, the Promo class. If the Promo class has a method setName, you're all set.
If you want to chain methods you just need to always return the object like this
class Chain {
public function firstChain() {
//do something
return $this;
}
public function secondChain() {
//do some stuff
return $this;
}
}
Than when you have an instance of the class you do like this:
$obj = new Chain();
$obj->fistChain()->secondChain();

PHP - runkit redefine method

all my websites share a common starter, that deals with urls, file locations, etc.. There are 3 cases that need to be handled - is directory, file exists and file does not exist. Each application has unique code for each case. I decided to tinker with runkit a bit and I am trying to unify the code. Each case will be handled by a function, that could be redefined via runkit.
Consider this code:
class start {
function __construct() {
$this->options = array();
}
public function process() {
// some code here
$this->file_not_exists();
}
public function file_not_exists() {
$this->options['page'] = 222;
}
public function redefine($what, $code) {
runkit_method_redefine(get_class($this), $what, '', $code, RUNKIT_ACC_PUBLIC);
}
}
$start = new start();
$start->redefine('file_not_exists', '$this->options["page"] = 333;')
// page is now 333
This part works as intended. But when I try to change the code so the redefined method calls user function it works. But, for the love of god, I cant figure out how to pass the $this to the function.
Redefine method looks like this:
public function redefine($what, $code) {
runkit_method_redefine(get_class($this), $what, '', 'call_user_func('.$code.'(), '.$this.');', RUNKIT_ACC_PUBLIC)
}
This doesn't work, no matter what I try (call_user_func_array as well). I just cant figure it out. For the record:
public function redefine($what, $code) {
my_user_function($this);
}
Does work.
Any help is appreciated.
Note that this is just an experiment and I would like to know how to do this :)
Edit:
I get:
Catchable fatal error: Object of class starter could not be converted to string in blablallala\rewrite_starter2.php on line 153
{... removed as not necessary ...}
==== EDIT =====
[For the new problem, what you need is this]
<?
class start {
function __construct() {
$this->options = array();
}
public function process() {
// some code here
$this->file_not_exists();
}
public function file_not_exists() {
$this->options['page'] = 222;
}
public function redefine($what, $code) {
runkit_method_redefine(get_class($this),
$what,
'',
'call_user_func(array($this,' .$code. '),$this);',
RUNKIT_ACC_PUBLIC);
}
public function my_func($someobj)
{
print_r($someobj);
}
}
$start = new start();
$start->redefine('file_not_exists', 'my_func');
$start->process();
?>
The documentation on the call_user_func function says that the first argument is 'callable'. So to call the class method dynamically, you should pass the array($obj, 'func_name').

Categories