Php inheritance superclass variables - php

I try to load an entity with some details and there is a resellerId in the entity.
Now I inherit a subclass from it, and try to access the resellerId but it's not there. How to pass the attributes to the subclasses? I really need it loaded.
Thanks!
edit:
class Crm_Entity extends Crm_Abstract {
protected $_mapper = 'Crm_Mapper_Entity';
protected $_data = array(
'customerId' => '', //done
'displayName' => '', //done
'active' => '', //done
'billingMethod' => '', //done
'debitorNumber' => null, //done
'bankAccount' => null, //done
'bankAccountTown' => null, //done
'resellerOrganisationId'=> null,
'account' => null, //done
'phonenumbers' => null, //done
'calls' => null,
'tickets' => null,
'comments' => null,
'addresses' => null,
'emailaddresses' => null, //done
'actionevents' => null
);
}
class Crm_CustomerEntity extends Crm_Entity {
//foobar not done yet
}
class Crm_Person extends Crm_CustomerEntity {
protected $_data = array(
'customerId' => null,
'firstName' => '',
'middleName' => '',
'lastName' => '',
'initials' => '',
'title' => '',
'openingWord' => ''
);
}
So I need to get the resellerId passed on to the subclass.

Ok, this is clear now.
You're storing data in associative arry. AND you're redefining this array in subclass. Of course, it won't have values form superclass that way.
Move array definition to class constructor instead. Then you should have
<?php
class Crm_Entity extends Crm_Abstract
{
protected $_mapper = 'Crm_Mapper_Entity';
protected $_data;
public function __construct()
{
parent::__construct();
$newData = array(
'customerId' => '', //done
'displayName' => '', //done
'active' => '', //done
'billingMethod' => '', //done
'debitorNumber' => null, //done
'bankAccount' => null, //done
'bankAccountTown' => null, //done
'resellerOrganisationId'=> null,
'account' => null, //done
'phonenumbers' => null, //done
'calls' => null,
'tickets' => null,
'comments' => null,
'addresses' => null,
'emailaddresses' => null, //done
'actionevents' => null
);
$this->_data = $newData;
}
}
class Crm_CustomerEntity extends Crm_Entity
{
//foobar not done yet
public function __construct()
{
parent::__construct();
}
}
class Crm_Person extends Crm_CustomerEntity
{
public function __construct()
{
parent::__construct();
$newData = array(
'customerId' => null,
'firstName' => '',
'middleName' => '',
'lastName' => '',
'initials' => '',
'title' => '',
'openingWord' => ''
);
$this->_data = array_merge($this->_data, $newData);
}
}
Of course the actual design depends - if you want those mappings before you create class you should put them in some static function instead. Something like
class Crm_Person extends Crm_CustomerEntity
{
public static function getData()
{
$data = Crm_Entity::getData()
$newData = (...)
return array_merge($data, $newData);
}
}

Your question isn't really easy to understand, but I'd check the scope of your class properties. For example:
class BaseClass {
protected $resellerId;
public function setResellerId($resellerId) {
$this->resellerId = $resellerId;
}
public function getResellerId() {
return $this->resellerId;
}
// rest of class code here
}
class ChildClass extends BaseClass {
// class contents
}
$obj = new ChildClass;
$obj->setResellerId(326);
echo $obj->getResellerId(); // should print '326' to your page
The protected keyword makes your $resellerId property available in that class, and all sub-classes. Also, public classes become available in classes extending the class in which they're defined, so I can use them in my ChildClass to access the $resellerId property, which is also available in my ChildClass.

Public or protected variable from the parent class should be accessable by children inheriting from it, private variables are not reachable. If the property is public or private and you still can not reach it, more info/ the actual code is required.

There is no resellerOrganisationId keyed value in the $_data array for an instance of Crm_Person because the entire $_data array in the Crm_Entity grand-parent class is overridden by the inheritance. All you have is the $_data array as defined in the Crm_Person class.
EDIT
class Crm_Entity {
protected $_mapper = 'Crm_Mapper_Entity';
protected $_data = array(
'customerId' => '', //done
'displayName' => '', //done
'active' => '', //done
'billingMethod' => '', //done
'debitorNumber' => null, //done
'bankAccount' => null, //done
'bankAccountTown' => null, //done
'resellerOrganisationId'=> null,
'account' => null, //done
'phonenumbers' => null, //done
'calls' => null,
'tickets' => null,
'comments' => null,
'addresses' => null,
'emailaddresses' => null, //done
'actionevents' => null
);
}
class Crm_CustomerEntity extends Crm_Entity {
//foobar not done yet
}
class Crm_Person extends Crm_CustomerEntity {
public function __construct() {
$this->_data['customerId'] = null;
$this->_data['firstName'] = '';
$this->_data['middleName'] = '';
$this->_data['lastName'] = '';
$this->_data['initials'] = '';
$this->_data['title'] = '';
$this->_data['openingWord'] = '';
}
public function getData() {
return $this->_data;
}
}
$test = new Crm_Person();
var_dump($test->getdata());

Related

Module lang not working in Prestashop 1.7.6

Just trying to create a new simple module with translation but the saving process is not working. The table 'ps_myoptions_lang' is updating with the field id_myoptions = 0 in each lang_id and nothing is saved in 'ps_myoptions'.
modules/myoptions/controllers/admin/AdminOptionsController.php
<?php
require_once(dirname(__FILE__) . './../../classes/Option.php');
class AdminOptionsController extends AdminController
{
public function __construct(){
parent::__construct();
$this->bootstrap = true; // use Bootstrap CSS
$this->table = 'myoptions'; // SQL table name, will be prefixed with _DB_PREFIX_
$this->lang = true;
$this->identifier = 'id_myoptions'; // SQL column to be used as primary key
$this->className = 'Option'; // PHP class name
$this->allow_export = true; // allow export in CSV, XLS..
$this->_defaultOrderBy = 'a.name'; // the table alias is always `a`
$this->_defaultOrderWay = 'DESC';
$this->fields_list = [
'id_myoptions' => ['title' => 'ID','class' => 'fixed-width-xs'],
'name' => ['title' => 'Name'],
];
$this->addRowAction('edit');
$this->addRowAction('details');
$this->fields_form = [
'legend' => [
'title' => 'Pasta',
'icon' => 'icon-list-ul'
],
'input' => [
['name'=>'name','type'=>'text', 'lang' => true, 'label'=>'Name','required'=>true],
],
'submit' => [
'title' => $this->trans('Save', [], 'Admin.Actions'),
]
];
}
}
modules/myoptions/classes/Options.php
<?php
class Option extends ObjectModel
{
public $id;
public $name;
public static $definition = [
'table' => 'myoptions',
'primary' => 'id_myoptions',
'multilang' => true,
'fields' => [
'name' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isAnything', 'required'=>true],
],
];
}
modules/myoptions/myoptions.php
if (!defined('_PS_VERSION_')) {
exit;
}
class Myoptions extends Module
{
protected $config_form = false;
public function __construct()
{
$this->name = 'myoptions';
$this->tab = 'administration';
$this->version = '1.0.0';
$this->author = 'abc';
$this->need_instance = 1;
/**
* Set $this->bootstrap to true if your module is compliant with bootstrap (PrestaShop 1.6)
*/
$this->bootstrap = true;
parent::__construct();
$this->displayName = $this->l('My Options');
$this->description = $this->l('Add additional options');
$this->ps_versions_compliancy = array('min' => '1.7', 'max' => _PS_VERSION_);
}
/**
* Don't forget to create update methods if needed:
* http://doc.prestashop.com/display/PS16/Enabling+the+Auto-Update
*/
public function install()
{
Configuration::updateValue('MYOPTIONS_LIVE_MODE', false);
include(dirname(__FILE__).'/sql/install.php');
return parent::install() &&
$this->registerHook('header') &&
$this->registerHook('backOfficeHeader') &&
$this->installTabs();
}
public function uninstall()
{
Configuration::deleteByName('MYOPTIONS_LIVE_MODE');
include(dirname(__FILE__).'/sql/uninstall.php');
return parent::uninstall();
}
public function enable($force_all = false)
{
return parent::enable($force_all)
&& $this->installTabs()
;
}
public function disable($force_all = false)
{
return parent::disable($force_all)
&& $this->uninstallTabs()
;
}
/**
* Since PS 1.7.1
* #var array
*/
public $tabs = array(
array(
'name' => array(
'en' => 'Options', // Default value should be first
'fr' => 'Options',
),
'class_name' => 'AdminOptions',
'visible' => true,
'parent_class_name' => 'AdminParentThemes',
),
);
public function installTabs()
{
$moduleName = $this->name;
$this->addTab('AdminOptions', 'Options', $moduleName, 'AdminTools');
return true;
}
public function addTab($className, $tabName, $moduleName, $parentClassName)
{
$tab = new Tab();
$tab->active = 1;
$tab->class_name = $className;
$tab->name = array();
foreach (Language::getLanguages(true) as $lang) {
$tab->name[$lang['id_lang']] = $tabName;
}
$tab->id_parent = (int) Tab::getIdFromClassName($parentClassName);
$tab->module = $moduleName;
$tab->add();
return $tab;
}
}
Is there something that I'm doing wrong?
Thanks for your answer.
Prestashop 1.7.6
PHP 7.2.25
I think I found the problem :
$sqlCreate = "CREATE TABLE `" . _DB_PREFIX_ . "myoptions` (
`id_myoptions` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id_myoptions`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
$sqlCreateLang = "CREATE TABLE `" . _DB_PREFIX_ . "myoptions_lang` (
`id_myoptions` int(11) unsigned NOT NULL AUTO_INCREMENT,
`id_lang` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id_myoptions`,`id_lang`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
Db::getInstance()->execute($sqlCreate) && Db::getInstance()->execute($sqlCreateLang);
I have the same field name in both tables. I then use it only in Lang Table and it seems to work now.

Variables in Trait

I have created a trait in Laravel.
In myconstruct I am calling a setting('value') - This is provided by the qcod/laravel-app-settings package.
But inside my methods when I reference $this->token or $this->org_id it returns NULL
I know the values are set, as they're showing in the config and are also set correctly in the Database.
My PHP code is :
<?php
namespace App\Traits;
use Illuminate\Support\Facades\Log;
trait PropertyBaseTrait
{
private $org_id;
private $token;
private $is_set;
public function __construct()
{
$this->org_id = setting('propertybase_org');
$this->token = setting('propertybase_token');
}
public function base_url($method)
{
return 'https://pb-integrations-api-staging.herokuapp.com/api/v1/'.$method.'/'.$this->org_id.'';
}
public function post_lead($data)
{
$lead_data = array(
'first_name' => '',
'last_name' => '',
'email' => '',
'phone1' => '',
'phone2' => '',
'phone3' => '',
'address' => '',
'city' => '',
'state' => '',
'zip_code' => '',
'country_name' => '',
'landing_page' => '',
'search_term' => '',
'referral_source' => ''
);
$object_type = 'lead';
$action_type = 'create';
dd($this->token);
$endpoint = $this->base_url('messages');
$this->post_data( $endpoint, $object_type, $action_type, json_encode($data));
}
The problem is that you have construct in your trait and maybe in your class where you are using this trait.
possible scenario:
class MyClass {
use MyTraitWithConstructor;
public function __construct(){
...
}
}
In this case trait constructor doesn't work.
What You can do?
You can rename trait construcor like this:
class MyClass {
use PropertyBaseTrait {
PropertyBaseTrait::__construct as private __prConstruct;
}
public function __construct(){
$this->__prConstruct();
...
}
}
Avoid writing constructor in traits. That's what I can say.
Instead, you can make them as normal method, then just call it in your class constructor.
Trait
trait Bar
{
public function init()
{
$this->org_id = setting('propertybase_org');
$this->token = setting('propertybase_token');
}
}
Class
class Foo
{
use Bar;
public function __construct()
{
$this->init();
}
}

Create a custom resource webservice PrestaShop

I create a module for PrestaShop 1.6 where I create a table as following in mymodule/mymodule.php:
class Mymodule extends Module {
// Some code
public function installDb() {
return Db::getInstance()->execute("
CREATE TABLE IF NOT EXISTS `" . _DB_PREFIX_ . "mytable`(
`id_mdm` INT NOT NULL AUTO_INCREMENT,
`id_category` INT NOT NULL,
`service` INT NOT NULL,
`title` VARCHAR(300) NOT NULL default '',
`title_font_size` VARCHAR(128) NOT NULL default '',
`title_color` VARCHAR(128) NOT NULL default '',
`background_color` VARCHAR(128) NOT NULL default '',
`border_style` VARCHAR(128) NOT NULL default '',
`position` INT NOT NULL,
`count` INT NOT NULL,
PRIMARY KEY (`id_mdm`), UNIQUE (`id_category`)) ENGINE = InnoDB;");
}
// Some code
}
It works fine, my table is created. Then I override webservice in mymodule/override/classes/webservice/WebserviceRequest.php:
class WebserviceRequest extends WebserviceRequestCore {
public static function getResources() {
$resources = parent::getResources();
$resources['myresource'] = array(
'description' => '',
'class' => 'myresource'
);
ksort($resources);
return $resources;
}
}
I create a new class called myresource in mymodule/override/classes/Myresource.php:
class MyresourceCore extends ObjectModel {
public $id;
public $id_mdm;
public $id_category;
public $service;
public $title;
public $title_font_size;
public $title_color;
public $background_color;
public $border_style;
public $position;
public $count;
public static $definition = array(
'table' => 'mytable',
'primary' => 'id_mdm',
'fields' => array(
'id_category' => array('type' => self::TYPE_INT),
'service' => array('type' => self::TYPE_INT),
'title' => array('type' => self::TYPE_STRING),
'title_font_size' => array('type' => self::TYPE_STRING),
'title_color' => array('type' => self::TYPE_STRING),
'background_color' => array('type' => self::TYPE_STRING),
'border_style' => array('type' => self::TYPE_STRING),
'position' => array('type' => self::TYPE_INT),
'count' => array('type' => self::TYPE_INT)
)
);
protected $webserviceParameters = array();
}
In the Back office I generate a key for myresource, but when I test in my browser http://mydomain/api/myresource?ws_key=mykey, there is the following error:
Fatal error: Class 'myresource' not found in /path/mydomain/classes/webservice/WebserviceRequest.php on line 502
I don't know why PrestaShop doesn't detect it. Thank you in advance for your assistance.
In Prestashop 1.7, you can use this hook: addWebserviceResources
Example:
include_once dirname(__FILE__) . '/classes/Sample.php';
class myAPISample extends Module {
// ...
public function install() {
return parent::install() && $this->registerHook('addWebserviceResources');
}
// ...
public function hookAddWebserviceResources($params) {
return [ 'samples' => ['description' => 'My sample', 'class' => 'Sample' ] ];
}
//...
}
See also (in french) : https://www.h-hennes.fr/blog/2018/06/25/prestashop-ajouter-un-objet-dans-lapi/
If you check the PHP error logs, you will notice an error of the type Class not found. In this case it's class "MyResource" not found.
In order to solve this, you need to include your Model class in the constructor of the override method like this
class WebserviceRequest extends WebserviceRequestCore {
public function __construct()
{
include_once(_PS_MODULE_DIR_ . 'myresource' . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'MyResource.php');
}
public static function getResources()
{
$resources = parent::getResources();
$resources['myresource'] = array(
'description' => '',
'class' => 'myresource'
);
ksort($resources);
return $resources;
}
}
And you need to place the Model Class in /mymodule/classes/MyResource.php
Placing the Model Class in mymodule/override/classes/Myresource.php is not correct cause there is no Myresource class to override. This will give you an error when uninstalling the module - you will not be able to uninstall it
Finally I found an alternative solution without using the native PrestaShop webservice. I created a directory called webservice in mymodule/webservice/mymodule.php. This file will be used to post data to PrestaShop's website. Here is how I did it:
<?php
$currentDirectory = str_replace('modules/mymodule/webservice/', '',
dirname($_SERVER['SCRIPT_FILENAME']) . "/");
$sep = DIRECTORY_SEPARATOR;
require_once $currentDirectory . 'config' . $sep . 'config.inc.php';
require_once $currentDirectory . 'init.php';
$hostnameIp = $_SERVER['REMOTE_ADDR'];
if ($hostnameIp == 'AUTHORIZED_IP') {
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Some code
http_response_code(200);
} else {
http_response_code(405);
}
} else {
http_response_code(403);
}
Then I just need to execute a POST request to myresource at the following url: http://mydomain/modules/mymodule/webservice/mymodule.php.
Be careful to do some validation for security, like IP address. If the validation is successful, then your do some treatment to insert or update data to mysql tables.

Yii Fixtures Issue?

I seem to be having a problem with fixtures in Yii. The problem seems to be the following,
public $fixtures=array('projects'=>'Project');
The model Project exists and I have the fixtures in a file name tbl_project.php in the fixtures folder of tests and my table name is called tbl_project. Inside the fixtures file is the following.
return array(
'project1' => array(
'name' => 'Test Project 1',
'description' => 'This is test project 1',
'create_time' => '',
'create_user_id' => '',
'update_time' => '',
'update_user_id' => '',
),
'project2' => array(
'name' => 'Test Project 2',
'description' => 'This is test project 2',
'create_time' => '',
'create_user_id' => '',
'update_time' => '',
'update_user_id' => '',
),
'project3' => array(
'name' => 'Test Project 3',
'description' => 'This is test project 3',
'create_time' => '',
'create_user_id' => '',
'update_time' => '',
'update_user_id' => '',
),
);
This is actually from the book "Agile Web Application Development with Yii". When I run the test case I get the following with no test result information.
PHPUnit 3.6.10 by Sebastian Bergmann.
Configuration read from ETC/protected/tests/phpunit.xml
If I remove the fixtures array from the top I get the following.
Time: 0 seconds, Memory: 9.25Mb
There was 1 error:
1) ProjectTest::testRead
Exception: Unknown method 'projects' for class 'ProjectTest'.
Which obviously makes sense. I dont know what Im doing wrong.
Make sure the test class looks like this
class ProjectTest extends CDbTestCase{
protected $fixtures = array(
'projects' => 'Project',
);
public function testRead(){
$receivedProject = $this->projects('Project1');
$this->assertTrue($receivedProject instanceof Project);
$this->assertEquals($receivedProject->name,'test 1');
}
...`
Check the fixture configuration in protected/config/test.php ... Should look like ...
...
'components'=>array(
'fixture'=>array(
'class'=>'system.test.CDbFixtureManager',
),
'db'=>array(
'connectionString' =>'mysql:host=localhost;dbname=your_db_name',
'emulatePrepare' => true,
'username' => 'username',
'password' => 'passwd',
'charset' => 'utf8',
),
....
Ultimately check the permissions on the fixture file making sure it can be read
Also be sure you are calling parents setUp() method in your own setUp()
class SomeTest extends CDbTestCase {
public $fixtures = array(
'somes' => 'Some',
);
protected function setUp() {
parent::setUp();
// your code....
}
// your tests .......................
}
Is your test class deriven from CDbTestCase instead of CTestCase?
your Test Class should look something like this:
class ProjectTest extends CDbTestCase{
protected $fixtures = array(
'projects' => 'Project',
);
public function testRead(){
$receivedProject = $this->projects('Project1');
$this->assertTrue($receivedProject instanceof Project);
$this->assertEquals($receivedProject->name,'test 1');
}
class ProjectTest extends CDbTestCase
{
public function testCreate()
{
//CREATE a new Project
$newProject=new Project;
$newProjectName = 'Test Project Creation';
$newProject->setAttributes(array(
'name' => $newProjectName,
'description' => 'This is a test for new project creation',
'createTime' => '2009-09-09 00:00:00',
'createUser' => '1',
'updateTime' => '2009-09-09 00:00:00',
'updateUser' => '1',
)
);
$this->assertTrue($newProject->save(false));
//READ back the newly created Project to ensure the creation worked
$retrievedProject=Project::model()->findByPk($newProject->id);
$this->assertTrue($retrievedProject instanceof Project);
$this->assertEquals($newProjectName,$retrievedProject->name);
}
public function testRead()
{
$retrievedProject = $this->projects('project1');
$this->assertTrue($retrievedProject instanceof Project);
$this->assertEquals('Test Project 1',$retrievedProject->name);
}
public function testUpdate()
{
$project = $this->projects('project2');
$updatedProjectName = 'Updated Test Project 2';
$project->name = $updatedProjectName;
$this->assertTrue($project->save(false));
//read back the record again to ensure the update worked
$updatedProject=Project::model()->findByPk($project->id);
$this->assertTrue($updatedProject instanceof Project);
$this->assertEquals($updatedProjectName,$updatedProject->name);
}
public function testDelete()
{
$project = $this->projects('project2');
$savedProjectId = $project->id;
$this->assertTrue($project->delete());
$deletedProject=Project::model()->findByPk($savedProjectId);
$this->assertEquals(NULL,$deletedProject);
}
public function testGetUserOptions()
{
$project = $this->projects('project1');
$options = $project->userOptions;
$this->assertTrue(is_array($options));
$this->assertTrue(count($options) > 0);
}
public $fixtures=array(
'projects'=>'Project',
'users'=>'User',
'projUsrAssign'=>':tbl_project_user_assignment',
);
}
make sure that setup come with its parent
<i>public function setUp() {
parent::setUp();
}</i>

How to retrieve the model name within the table class in symfony 1.4?

I am inside a ModelTable and I need the Model name. For example: in case of EventTable I need to know the model it instantiates - Event.
Internally the following function already instantiates an correct Model:
class EventTable extends Doctrine_Table
{
public function findBySomething($something)
{
// Will return a Event
return $this->createQuery('s')->fetchOne();
}
}
What I would like to be able to do:
class EventTable extends Doctrine_Table
{
public function findBySomething($something)
{
$modelName = $this->getModelName();
echo "I will create a ".$modelName; // Will display Event
return $this->createQuery('s')->fetchOne();
}
}
How do I retrieve the model name from inside a table?
You have an array of options available for each Table (Doctrine/Table.php):
protected $_options = array(
'name' => null,
'tableName' => null,
'sequenceName' => null,
'inheritanceMap' => array(),
'enumMap' => array(),
'type' => null,
'charset' => null,
'collate' => null,
'treeImpl' => null,
'treeOptions' => array(),
'indexes' => array(),
'parents' => array(),
'joinedParents' => array(),
'queryParts' => array(),
'versioning' => null,
'subclasses' => array(),
);
So you can retrieve the model name using:
$this->getOption('name');

Categories