Call an object reference over different methods through ajax in Codeigniter - php

I am trying to call different methods within same controller written using Codeigniter through separate AJAX calls and create an object of a Third Library in one of those calls and later access the same object (also autoloaded SESSION library) in second method while making second AJAX Call:
Javascript has 2 separate AJAX Calls:
$.post('http://mysite.com/UserController/controllerA',{Param1:x,Param2:y});
$.post('http://mysite.com/UserController/controllerB');
And the controller looks like:
require_once 'FILEPATH/Thirdlibrary.php';
class UserController extends CI_Controller {
protected $service;
public controllerA{
$varA = $this->input->post('Param1');
$varB = $this->input->post('Param2');
$this->service = new ThirdLibray($varA,$varB);
$this->service->startCall();//Thirdlibrary has method startCall() and stopCall
}
public controllerB{
//I want to refer to the same object $this->service here
$this->service->stopCall();
}
Now I know that PHP re-initializes the objects each time its loaded/visited, how could I make this work.How to ovecome such error:
Call to a member function stopCall() on a non-object
(Querying here after making all the efforts searching and coding)

store the object into session and use it.
require_once 'FILEPATH/Thirdlibrary.php';
class UserController extends CI_Controller {
protected $service;
public controllerA{
$varA = $this->input->post('Param1');
$varB = $this->input->post('Param2');
if($this->session->userdata('lib_service'))
{
$this->service =$this->session->userdata('lib_service');
}
else
{
$this->service = new ThirdLibray($varA,$varB);
}
$this->service->startCall();//Thirdlibrary has method startCall() and stopCall
$this->session->set_userdata('lib_service',$this->service); // Why i am saving the object here?, startCall may update some object properties, so that-also will be saved. Otherwise you can have this line in the else part above, after object creation.
}
public controllerB{
//I want to refer to the same object $this->service here
if($this->session->userdata('lib_service'))
{
$this->service =$this->session->userdata('lib_service');
$this->service->stopCall();
// Here after stop if you don't want the object, you can clear from session.
}
}

You can try with Singleton pattern for php. This is the basic code for implement it for your situation but I'm not sure it will work for you. Let's try:
First create a wrraped class for your third party library: ThirdlibraryWrapped.php that you can see more about singleton Best practice on PHP singleton classes
class ThirdLibraryWrapped{
public ThirdLibray thirdLibrary;
public static function Instance($param1=null,$param2 = null)
{
static $inst = null;
if ($inst === null) {
$inst = new ThirdlibraryWrapped($param1,$param2);
}
return $inst;
}
private function __construct($param1,$param2)
{
if($param1!=null && $param2 != null)
thirdLibrary = new ThirdLibrary($param1,$param2);
else
//default constructor of thirdLibrary
thirdLibrary = new ThirdLibrary();
}}
For your controller code:
require_once 'FILEPATH/ThirdlibraryWrapped.php';
class UserController extends CI_Controller {
protected $service;
public controllerA{
$varA = $this->input->post('Param1');
$varB = $this->input->post('Param2');
$this->service = ThirdlibraryWrapped::Instance($varA,$varB);
$this->service->thirdLibrary->startCall();//Thirdlibrary has method startCall() and stopCall
}
public controllerB{
//I want to refer to the same object $this->service here
$this->service = ThirdlibraryWrapped::Instance();
$this->service->thirdLibrary->stopCall();
}}

Related

PHP MVC: How to use private Model object stored inside View from outside class

I am new in learning MVC, I want to use private Model object stored inside View from outside class, like below example:
class Model{
private $data
}
class View{
private $model
public function __construct($model) {
$this->model = $model;
}
}
// outside
$m = New Model;
$v = New View($m);
echo $v->m->data; // How to get it
i know setter/getter method, but it can can much more bigger MVC code.please help.
You would probably want to access the view from within the controller like this:
class Controller
{
public function __construct($model, $view)
{
$this->model = $model;
$this->view = $view;
}
public function show()
{
return $this->view->render($this->model->getData());
}
}
$controller = new Controller();
$controller->show();
You want the controller to receive all of the dependencies that it has ideally in the constructor. That way it doesn't need to search for them. This is inversion of control or DI (dependency injection).

Calling an external class only once?

I have a class that using an external package to do something
class MyClass
{
public function doSomething($data){
$external = new External();
$external->doSomething($data);
}
}
This class is called from another class, for example:
class MasterClass
{
public function go(){
$data = 'whatever';
$data2 = 'whatever2';
$myClass = new MyClass();
$myClass->doSomething($data);
$myClass->doSomething($data2);
....
}
}
So in my MasterClass I am calling the doSomething function multiple times. WHich creates a new External class multiple times - which is not really necessary.
How can I get around this issue and only create the external class once?
class MyClass
{
protected $external;
public function doSomething($data){
if(!$this->external){
$this->external = new External();
}
$this->external->doSomething($data);
}
}
But read about dependency injection in php.
Move the new External() call into the constructor and store it as a property, then reference that property in the doSomething() method instead of constructing a new instance every time.
Alternatively, if you don't want to always construct a new External whenever you construct a MyClass, you could move the construction into a Lazy Load static method called something like getExternal() in External class.
The first time that method is called it would need to store a new instance of External as a property, but on subsequent calls (when the property is already set) return the same instance. This type of pattern is called Singleton Pattern in Object-Oriented Design Patterns.
You could refer to this link to know more about singleton pattern and how it is implemented.
Pass External class in constructor.
class MyClass
{
private $external;
public function __construct(External $external)
{
$this->external = $external;
}
public function doSomething($data)
{
$this->external->doSomething($data);
}
class MasterClass
{
public function go() {
$data = 'whatever';
$data2 = 'whatever2';
$external = new External();
$myClass = new MyClass($external);
$myClass->doSomething($data);
$myClass->doSomething($data2);
....
}
}

PHP Object Oriented array not being printed

Alright so I got 2 problems on my hands at the moment and those are
I want to call the function from the parent object but I am getting a lot of errors saying "Fatal error: Cannot instantiate abstract class Person"
If I call the getUserItems directly it will not do anything. There wont be anything echoed or such.
<?php
abstract class Person {
abstract function getUserItems();
}
class inventory extends Person {
protected $storage = array();
protected $item_id;
public function itemAdd($itemname) {
$storage[$this->item_id+1] = $itemname;
}
public function getUserItems() {
foreach($this->storage as $itemName=>$item_id) {
echo $itemName." ".$item_id."<br/>";
}
}
}
$user = new Person();
$user->getUserItems();
/*$user = new inventory();
$user->itemAdd("Item 1");
$user->itemAdd("Item 2");
$user->getUserItems();*/
?>
In OOP - abstract class may not be instantiated.
An abstract class is a class with both implementation and interface (pure virtual methods) that will be inherited. Interfaces generally do not have any implementation but only pure virtual functions.
So you cannot instantiate (new Person()). You must extend this abstract class and implement it's abtract functions (same way you did in inventory).
Regarding the echoing problem - inside your itemAdd function you didn't use the object's $storage member (you just used a local $storage variable). You should use it as the object's memebr, using $this->storage:
public function itemAdd($itemname) {
$this->storage[$this->item_id+1] = $itemname;
}
Note that I'm not so sure how you managed the $this->item_id member because you didn't set/changed it in the code.
If you only want to add new items to the storage member you could use:
$this->storage[] = $itemname;
This will make sure every new item will be added to the $storage array.
ad1)
Person is abstract class so you can not create object of that class.
ad2)
You must use $this
so not:
$storage[$this->item_id+1]
but
$this->storage[++$this->item_id]
Here I fixed another bug which was $this->item_id+1
Abstract class can not access directly but access from other class.
abstract class Person {
abstract function getUserItems();
}
class inventory extends Person {
protected $storage = array();
protected $item_id=2;
public function itemAdd($itemname) {
$storage[$this->item_id+1] = $itemname;
}
public function getUserItems() {
foreach($this->storage as $itemName=>$item_id) {
echo $itemName." ".$item_id."<br/>";
}
}
}
$user = new inventory();
$user->getUserItems();
$user = new inventory();
$user->itemAdd("Item 1");
$user->itemAdd("Item 2");
$user->getUserItems();

PHP hangs on a loop and never makes Request

I have a RESTful API that I need to inteact with using CURL. I have created a wrapper class that has a static function with the CURL code.
class ApiInvoke
{
public static function execute($username, $password, $endpoint, $data = array(), $options = array())
{
//Rest of the CURL code goes here.....
}
}
I the created a class where I call the static APIInvokve class method to actually execute the API call. Below is the consumer class for ApiInvoke class above.
require "api_invoke.php"
class FlowgearConnect
{
//Properties go gere
public function getResults($model, $workflow, $data)
{
$endpoint = $this->getEndpoint($model, $workflow);
$results = array();
if(!is_null($endpoint)){
$results = ApiInvoke::execute('username', 'password', $endpoint, $data array('timeout' => 30));
}
return $results;
}
//....
}
Then I have a ParentClass class that create an instance of FlowgearConnect object which is made avalable to sub-classes. However, all subclasses are are processed inside the same parent class.
class ParentClass
{
private $Flowgear;
public function init()
{
$this->Flowgear = new FlowGearConnect(); //Assuming it has been required somewhere
}
}
Then we may have ChildClassA and ChildClassB which extends ParentClass. By vartue of the child classes extending the parent class they have access to the instance of $this->Flowgear object already because below is how the FlowgearConnect class is used:
class ChildClassA
{
public function getResults()
{
$results = $this->Flowgear->getResults('child_a', 'latestEvents', array());
}
}
ChildClassB has the very same function or rather exact except it might be responsible for getting a list of orders for example.
How these child classes are processed inside the parent class is depicted below:
//A function inside the ParentClass to process ChildClassA and ChildClassB
public function processModules()
{
$modules = $request->getModules();
foreach($modules as $module){
require_once "modules/' . $module;
$Module = new $module();
$Module ->getResults();
}
}
Something along these lines is not right.... Basically the extending class creates an instance of a class that is used by child classes. Somewhere somehow something is not right here and I guess it has everything to do with the facy that I am not using singgleton. I could if I new how to where CURL is concerned.
Stupid of me to ever thought I could never be able to create just one instance of a curl object thanks to Rayhan’s Http Client class (http://raynux.com/blog/2009/06/13/http-client-class-for-php-development/).
Basically what I wanted was to create a CURL SINGLETON class such that I do not have instances of the same object created over and over again.
Below is a skeleton of how I went about to achieve this:
class Flowgear
{
static private $_instance;
//Rest properties here...
public function __cosntsruct()
{ $this->_token = $this->_username .':'. $this->_passoword; }
public function execute()
{
//Call a class that handles the actual API invocation passing all relevant data
}
static public function &getInstance()
{
if(self::$_instance == null){
self::$_instance = new self;
}
return self::$_instance;
}
}
Then I simply get a single instance of the class by calling Flowgear::getInstance();

PHP - Calling instance method from static method

I am having trouble calling a specific method from another class in my app. I have a class, Rest, that determines various settings, etc. about a particular request received by the server and creates a Rest object with the properties of the request. The Rest class may then call any given method in a separate class to fulfill the request. The problem is that the other class needs to call methods in the Rest class to send a response, etc.
How can this be possible? Here's a blueprint of my current setup:
class Rest {
public $controller = null;
public $method = null;
public $accept = null;
public function __construct() {
// Determine the type of request, etc. and set properties
$this->controller = "Users";
$this->method = "index";
$this->accept = "json";
// Load the requested controller
$obj = new $this->controller;
call_user_func(array($obj, $this->method));
}
public function send_response($response) {
if ( $this->accept == "json" ) {
echo json_encode($response);
}
}
}
The controller class:
class Users {
public static function index() {
// Do stuff
Rest::send_response($response_data);
}
}
This results in receiving a fatal error in the send_response method: Using $this when not in object context
What's the better way to do this without sacrificing the current workflow.
You can create a Rest instance in User:
public static function index() {
// Do stuff
$rest = new Rest;
$rest::send_response($response_data);
}
You could also change Rest to be a singleton and call an instance of it, but beware of this antipattern.
You need to create an instance first.
class Users {
public static function index() {
// Do stuff
$rest = new Rest();
$rest->send_response($response_data);
}
}
You don't call send_response() in an object context, as the error message says.
Either you create an instance and call everything on that instance (IMHO the right way), or you do everything statically, including the constructor (you may want to have a intialization method instead) and the properties.

Categories