PHP issues with namespaces and singletons - php

Hey guys I'm having an issue that I think is because due to namespaces, I have my parent class TheParent where I do some stuff, add it to $this then extend to a child class expecting that $this will carry over, but everything inside except what is explicitly mentioned in the parents constructor seems to vanish (the $timeout = 10) I'm trying to figure out where I borked this code at, and if anyone could explain it to me why this is not working like I would think it should?
Namespace Services;
Class TheParent
{
public function __construct($timeout = 10, array $options = array())
{
$this->setAuth($options)->setTimeout($timeout);
}
// other methods that put information into $this
public function useRest()
{
require_once 'RestAggregator.php'
$this->message = REST::getInstance();
header('Content-Type: text/plain');
print_r($this); die;
}
}
Namespace Services;
Class REST Extends TheParent
{
private static $instance = NULL;
private $messages = array();
public function __construct()
{
$this->messages = self::getDataMessages();
}
public static function getInstance()
{
if(! isset(REST::$instance))
{
REST::$instance = New REST();
}
return REST::$instance;
}
protected function getDataMessages()
{
return REST::$instance->messages = array(
'foo' => '4',
'bar' => '5',
'baz' => '6',
);
}
}
This is the rest object returned, you would THINK that I would also have data from TheParent which is where things like _appKey etcetera have already been defined before being passed to REST
Services\REST Object
(
[type] =>
[messages:Services\REST:private] => Array
(
)
[groups:Services\REST:private] => Array
(
)
[_following:protected] =>
[_sent:protected] =>
[_private:protected] =>
[_received:protected] =>
[_appKey:protected] =>
[_appSecret:protected] =>
[_authToken:protected] =>
[_authSecret:protected] =>
[_authCode:protected] =>
[_redirectUri:protected] =>
[_smAuth:protected] =>
[_accessToken:protected] =>
[_tigerToken:protected] =>
[_data:protected] =>
[_timeout:protected] => 10
[_cookieJar:protected] =>
[dbh] =>
[opts] => Array
(
)
)

You are saying that class REST extends (is a child of) class Parent. But in class Parent you are referring to methods in the child class. Child classes can use parent methods but parent classes have no access to their child classes. Extending a class is a one way street.

Related

Trying to extend a class to overwrite a function PHP

Ok, I have the parent class from a plugin I'm trying to extend:
class OsBookingHelper {
public static function get_statuses_list(){
return array( LATEPOINT_BOOKING_STATUS_APPROVED => __('Approved', 'latepoint'),
LATEPOINT_BOOKING_STATUS_PENDING => __('Pending Approval', 'latepoint'),
LATEPOINT_BOOKING_STATUS_PAYMENT_PENDING => __('Payment Pending', 'latepoint'),
LATEPOINT_BOOKING_STATUS_CANCELLED => __('Cancelled', 'latepoint'));
}
}
My code to extend follows: It's not working for some reason....
if ( ! class_exists( 'OsNuuCustomAppointmentStatusHelper' ) ) :
class OsNuuCustomAppointmentStatusHelper extends OsBookingHelper {
function __construct(){
parent::__construct();
}
public static function get_statuses_list(){
return array( LATEPOINT_BOOKING_STATUS_APPROVED => __('Approved', 'latepoint'),
LATEPOINT_BOOKING_STATUS_PENDING => __('Pending Approval', 'latepoint'),
LATEPOINT_BOOKING_STATUS_PAYMENT_PENDING => __('Payment Pending', 'latepoint'),
LATEPOINT_BOOKING_STATUS_CANCELLED => __('Cancelled', 'latepoint'),
LATEPOINT_BOOKING_STATUS_COMPLETE => __('Complete', 'latepoint'));
}
endif;
Any ideas? I'm totally at a loss with this...
Oh, before I forget. There's a parent class that is instantiated in another file that calls the file containing my code using include_once

On Silverstripe, how do I retrieve a DataList of grandchild objects including their extrafields?

I have a setup similar to that outlined below.
class A extends DataObject{
private static $many_many = array(
'Bs' => 'B'
);
public function Grandchildren(){
// return grandchildren, including their many_many_extraFields data (ExtraData)
}
}
class B extends DataObject{
private static $many_many = array(
'Cs' => 'C'
);
private static $belongs_many_many = array(
'As' => 'A'
);
private static $many_many_extraFields = array(
'As' => array(
'ExtraData' => 'Int'
)
);
}
class C extends DataObject{
private static $db = array(
'Name' => Varchar(255)
);
private static $belongs_many_many = array(
'Bs' => 'B'
);
}
I wish to retrieve all the C objects of all the B objects from a function on A (here called Grandchildren()).
Two potential solutions that I can't get to work:
1 -
public function Grandchildren(){
$grandchildren = DataList::create();
foreach($this->Bs() as $b){
$Cs = $b->Cs();
// How would I then merge these into one single DataList ($grandchildren)?
}
return $grandchildren;
}
2 -
public function Grandchildren(){
return C::get()->leftJoin('B_Cs', 'B_Cs.CID = C.ID')->where('B_Cs.AID = ' . $this->ID);
// This works but doesn't contain the needed ExtraData.
}
Many thanks in advance for any help.
Ah sorry. The answer was much simpler than I realised. Just took going through every method on the docs for DataList again.
public function Grandchildren(){
return $this->Bs()->relation('Cs');
}
Leaving question and answer here to help any of those stuck in the same situation as me (as I've been stuck with this problem many times before).

CodeIgniter: blank page when a model contains a function

i'm using codeigniter for a website project. when i include a model, it will work as long as no function is implemented (except the constructor).
this configuration works:
class Xyz_model extends CI_Model {
function __construct() {
}
}
this doesn't:
class Xyz_model extends CI_Model {
function __construct() {
}
public function get_xyz() {
return [
"xy" => ["xy"],
"yz" => ["xy"],
"zz" => ["xy","zx","zy"]
];
}
}
there is not even an database access... and i have no clue why it is not working.
You are extending the core model class, but the child's constructor is being used in placed of the parents:
parent::__construct();
Add that to your models constructor.
use this
In model
class Xyz_model extends CI_Model {
function __construct() {
}
public function get_xyz() {
$array = array(
'xy' => 'xy',
'yz' => 'xy',
'zz' => array("xy","zx","zy")
);
return $array;
}
}
In controller
$new = $this->Xyz_model->get_xyz()
print_r($new);
so output will be
Array ( [xy] => xy [yz] => xy [zz] => Array ( [0] => xy [1] => zx [2] => zy ) )

PHP parent::$property returned instead of self:$property when using parent method

I am trying to create a abstract class that has a property/array of settings and then in the child classes add additional properties to that property/array. I want methods defined in the abstract class to use the child classes property/array when the method is called from the child. I thought the code bellow should work... But it seems to still be accessing the property from the parent class.
abstract class AbstractClass {
protected static $myProp;
public function __construct() {
self::$myProp = array(
'a' => 10,
'b' => 20
);
}
protected function my_print() {
print_r( self::$myProp );
}
}
class ClassA extends AbstractClass {
protected static $myProp;
public function __construct() {
parent::__construct();
self::$myProp = array_merge( parent::$myProp,
array(
'c' => 30,
'd' => 40
)
);
$this->my_print( self::$myProp );
}
}
$myObj = new ClassA;
This should return Array ( [a] => 10 [b] => 20 [c] => 30 [d] => 40 )
Instead it returns Array ( [a] => 10 [b] => 20 )
How do I get this to work?!?
Like so:
<?php
abstract class AbstractClass {
protected static $myProp;
public function __construct() {
self::$myProp = array(
'a' => 10,
'b' => 20
);
}
protected function my_print() {
print_r( self::$myProp );
}
}
class ClassA extends AbstractClass {
public function __construct() {
parent::__construct();
self::$myProp = array_merge( parent::$myProp,
array(
'c' => 30,
'd' => 40
)
);
$this->my_print( self::$myProp );
}
}
$myObj = new ClassA;
You are overwriting the variable
Actually in parent class you did not define method my_print() to contain any arguments, plus, the method uses self::$myProp (not static::).
Also, as Ka_lin already answered you do not need to redeclare property that has been declared in parent class.
If you do (for some reason need to redeclare it like set predefined value different than parent) you can do two things:
For one, you can change my_print() to accept argument then print_r() the argument not self::$myProp:
protected function my_print($debug) {
print_r($debug);
}
Or, (in PHP as of version 5.3.0.) you can use static:: instead of self:::
protected function my_print() {
print_r(static::$myProp);
}
I would go for the second option.
Also you should ready more about self vs static (late binding) in php manual

Upsert embedded document in yiimongodbsuite

I need to perform an upsert command in yiimongodbsuite.
I tried
$model = new Murls();
$model->userid=$userid;
$model->title=$title;
$model->edits[0] = new Medithtml();
$model->edits[0]->path= $htm;
$model->edits[0]->html=$path;
$model->edits[0]->ci=$ci;
$model->update(array('_id'=>$rec->_id ),array('userid', 'title','edits' ), true );
But this shows an error.
Murls model is defined as follows
class Murls extends EMongoDocument
{
public $userid;
public $title;
public $edits;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
// This method is required!
public function getCollectionName()
{
return 'murls';
}
public function attributeLabels()
{
return array(
'html'=>'Html',
);
}
public function embeddedDocuments()
{
return array(
// property name => embedded document class name
'edits'=>'Medithtml',
);
}
public function behaviors(){
return array(
'embeddedArrays' => array(
'class' => 'ext.YiiMongoDbSuite.extra.EEmbeddedArraysBehavior',
'arrayPropertyName' => 'edits', // name of property, that will be used as an array
'arrayDocClassName' => 'Medithtml' // class name of embedded documents in array
),
);
}
}
and model Medithtml as
class Medithtml extends EMongoEmbeddedDocument{
public $html;
public $path;
public $ci;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
What I need to achieve is that a record with $title can have n number of $html , $path and $ci.
Any help will be appreciated.
What I am looking is to store data like this
array (
'_id' =>
MongoId::__set_state(array(
'$id' => '51ee1956d39c2c7e078d80da',
)),
'userid' => '12',
'title' => 'Mongo',
'edits' =>
array (
0 =>
array (
'html' => 'html>body>div:nth-child(2)>a>div>a>div',
'path' => 'ssssss',
'ci' => '1',
),
1 =>
array (
'html' => 'html>body>div:nth-child(2)>a>div:nth-child(3)>a>h2',
'path' => '/assets/img/demo/demo-avatar9604.jpg',
'ci' => '2',
),
2 =>
array (
'html' => ' html>body>div:nth-child(2)>a>div:nth-child(3)>a>center:nth-child(16)>a>h1',
'path' => '333',
'ci' => '3',
),
),
)
Only the comments array will be updated if record with a particular combination of 'title' and 'userid' exists.If it doesn not exists a new record will be inserted
You are inheriting from wrong class. To save document you must inherit from EMongoDocument not EMongoEmbeddedDocument. These classes are similar but have different purpose.
EMongoEmbeddedDocument Is for embedded documents only, it should be used only for embedded documents
EMongoDocument extends from EMongoEmbeddedDocument with methods to actually save data to db.
For array of comments, you have two options:
Use plain php array - simple less maintanable, less power, erron prone..
Use array of embedded documents - each comment is document, so can be validated, has rigid structure etc.
By default save/insert/update stores all attributes. For partial updates use combination of $attributes and set $modify to true. Warning: Passing array of attributes without $modify will store only passed attributes, discarding rest of document.
public function save($runValidation = true, $attributes = null)
...
public function insert(array $attributes = null)
...
public function update(array $attributes = null, $modify = false)
...
So in your case you can update like that:
$model->update(array('comments'), true);
Or if it's ok for you to ovverride whole document just save:
$model->save();
Note: for composite pk ovverride primaryKey():
public function primaryKey()
{
return array('title', 'userid');
}
Uh, good that stackoverflow have drafts autosave feature:)
Finally I got solution in this way:
$rec = $model->find($criteria) ;
if($rec){
foreach($rec->edits as $editarray){
$var[]=$editarray;
}
$edits_new= new Medithtml();
$edits_new['html']=$htm;
$edits_new['ci']=$ci;
$edits_new['path']=$path;
$var[]=$edits_new;
$rec->edits=$var;
$rec->userid=$userid;
$rec->title=$title;
$rec->update(array('edits' ), true);
}

Categories