Reputation: 31307
I have the following class:
class Apiconnect {
const URL = 'https://someurl.com/api.php';
const USERNAME = 'user';
const PASSWORD = 'pass';
/**
*
* @param <array> $postFields
* @return SimpleXMLElement
* @desc this connects but also sends and retrieves the information returned in XML
*/
public function Apiconnect($postFields)
{
$postFields["username"] = self::USERNAME;
$postFields["password"] = md5(self::PASSWORD);
$postFields["responsetype"] = 'xml';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, self::URL);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
$data = curl_exec($ch);
curl_close($ch);
$xml = new SimpleXMLElement($data);
if($xml->result == "success")
{
return $xml;
}
else
{
return $xml->message;
}
}
}
Now I would like to use this connection class on other methods on other classes that will use it.
So, I was thinking about doing a class (not sure if abstract is appropriate here), like this:
abstract class ApiSomething
{
protected $_connection;
protected $_postFields = array();
/**
* @desc - Composition.
*/
public function __construct()
{
require_once("apiconnect.php");
$this->_connection = new Apiconnect($this->_postFields);
}
public function getStuff()
{
//this is the necessary field that needs to be send.
//Containing the action that the API should perform.
$this->_postFields["action"] = "dosomething";
...
}
}
I need to use the property $_connection on getStuff() method so that the "action" is send into the API. Not sure however, how can that be accomplish.
Any help please?
Upvotes: 2
Views: 154
Reputation: 13737
You can improve your design by following these rules:
-don't do real work in the constructor (see APIConnect)
-favor composition
-inject the dependencies in the constructor
-meaningful class/interface names
-single responsibility
I would refactor this more like this:
interface APIConnection { // responsible for the connection
public function connect();
}
class FacebookConnection implements APIConnection {
public function __construct($url, $name, $pass, $params) {
// set only connection parameters here. NO WORK DONE, NO CONNECTING
}
public function connect() {
// curl stuff
}
}
class FacebookFarmer {
public function __construct(APIConnection $connection) {} // inject dependency, composition
public function harvest() {} // responsible for the actions having the connection
public function milkCows() {}
}
class FacebookFarmController { // translates what user requests to do to an action
public function __construct(FacebookFarmer $farmer) {} // injection again, composition
public function doAction($request) {
// eg $action = $request['action'];
// then $this->famer->$action() if exists
}
}
I don't know whether this is an example of something you could use because APIThis and APIThat is a bit difficult to understand. If I misunderstood please clarify your intentions.
Upvotes: 0
Reputation: 44346
First of all I think that Apiconnect
should be a singleton (you need just one authentication) and you should rename it to something like APIConnection
if you want to use it as a resource in other classes. Extending it would also be an option, but it depends on what your other class does (you other class should also be a singleton if you choose to extend). Making it abstract or not depends only if it can be used as is.
Inside your APIConnection
(I prefer naming it like this) you should have a call method doPost
or something of the sort that makes a request to the API (keep it as general as possible). In the constructor call the login API method if you want to authenticate when instantiating. When you need to call other API methods do that directly through the doPost
you just created.
Upvotes: 0
Reputation: 39
Why not extend your object instead of including something. APIConnect should be the abstract class and API something should extend it.
abstract class ApiConnect {
protected $_something;
protected $_something2;
protected $_curlResource;
function __construct($param1){
/* do curl setup here and save it to $this->_curlResource */
}
}
class ApiSomething extends ApiConnect {
protected $_paramForBase;
function __construct(){
super($this->_paramForBase);
echo "Var from base: ".parent::_something;
/* do more things with curl here, through parent::_curlResource */
}
function setParamsForCurlCall(){
/* add curl parameters with curl here, through parent::_curlResource */
}
function execCurl(){
/* do your final curl call here */
}
}
Then you can do whatever you want with your abstract class, and you can API something can have all the control logic for the base class. Granted you would only want to do this if your going to extend ApiConnect in more than one class.
Upvotes: 3