2

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?

4
  • @Rook - this API seems to only work if I do like this. But what do you suggest? Commented Oct 15, 2010 at 17:58
  • Well, https is the best for transport which is being used. The real problem with using md5 like this is that now the md5 hash is your password so if someone gets the md5 hash then they can login immediately. There is a good chance the password is stored in the database like this, and then SQL Injection can be used to get immediate access, thus defeating the purpose of hashing passwords. Commented Oct 15, 2010 at 18:01
  • @Rook thanks Rook. And the solution will pass by? I'm asking this, because on API documentation they say: In order to login DO like this. So I've done, cause I'm not that smart on programming matters. If, however, on my side of things, I can do it better, why not? - Your explanation seems to be givin me some clues, I realise that, however, I'm not able to follow them yet... :s Commented Oct 15, 2010 at 18:23
  • i'm not sure what you are asking it seems obvious. A md5 hash is just a string and that has to be compared somewhere. md5 isn't an encryption algorithm its a message digest function. On your end you can't really do anything, except for email them and tell them them to ask SO for a real solution :) Commented Oct 15, 2010 at 18:26

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Probably the abstract usage was a miss lead from my part. :( To be honnest I will not need to abstract the curl usage on this application - that will be the only curl usage that I will make. Connection/Retrieve/Send no need to abstract send methods, or other things. Not even in the farest futures so, I believe that abstract was a miss lead. :(
0

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.

1 Comment

Well abstract seems to be out of equation as far as I can see. About the fact that I should keep the doPost as general as possible, I'm not sure if I can do this, because, the API expects to have, with the curl, some array to play with and return the XML. So, I believe it's just the way they need perhaps...
0

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.

2 Comments

Will the interface be of a good use if we need to connect other API's as well? On this case, however, all 1 API will be required for all life long of this application. Is this additional information of some use? I'm not sure what is the difference between implementing an interface of extending a class, worry not, I will read about it. I didn't know about injection and it's relations with composition, I have however, one question, how does , on your example, FarmController uses the connection?
It's used the same way as in your example. Since I didn't really understood how I just assumed it needed it. You can regard the interface as a responsability. In this case it says "I'm responsible to create a connection". Different classes can implement the responsibility in a different way without the client class caring how.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.