2010-10-15 60 views
2

我有下面的类:PHP的设计问题

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; 
    } 
} 
} 

现在我想使用此连接类上,将使用其他类的其他方法。

所以,我想这样做一个类(不知道抽象为宜这里),像这样:

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"; 
    ... 
    } 

} 

我需要使用上getStuff()方法的属性$ _connection从而使“行动”发送到API。但不知道,那怎么能成就呢。

请帮忙吗?

+0

您错误地使用了md5。 – rook 2010-10-15 17:11:53

+0

@Rook - 如果我这样做,这个API似乎只能工作。但是你有什么建议? – MEM 2010-10-15 17:58:00

+0

那么,https是最适合正在使用的交通工具。像这样使用md5的真正问题是,现在md5散列是你的密码,所以如果有人得到md5散列,那么他们可以立即登录。密码存储在数据库中很可能是这样的,然后可以使用SQL注入来立即访问,从而破坏散列密码的目的。 – rook 2010-10-15 18:01:02

回答

3

为什么不扩展你的对象而不是包含某些东西。 APIConnect应该是抽象类,API应该扩展它。

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 */ 
    } 
} 

然后,你可以做任何你想要与你的抽象类,你可以API东西可以拥有所有的基类的控制逻辑。当然,如果你想在不止一个类中扩展ApiConnect,你只需要这样做。

+0

也许抽象的用法是我的一部分的一个小姐带领。 :(非常高兴我不需要在这个应用程序中抽象卷曲用法 - 这将是我将做的唯一卷曲用法。连接/检索/发送不需要抽象发送方法或其他东西。因此,我认为抽象是一个错过的领导。:( – MEM 2010-10-15 18:01:31

0

首先我认为Apiconnect应该是一个singleton(你只需要一次认证),如果你想把它用作其他类的资源,你应该把它重命名为APIConnection。扩展它也是一个选项,但它取决于你的其他类所做的工作(如果你选择扩展,其他类也应该是单例)。只要它可以按原样使用,就使其变为抽象或不抽象。你应该有一个调用方法doPost或者向API发出请求的东西(保持尽可能通用)。在你的APIConnection(我更喜欢这样命名)的时候,你应该有一个调用方法doPost。如果您想在实例化时进行身份验证,则在构造函数中调用登录API方法。当您需要调用其他API方法时,请直接通过您刚创建的doPost进行调用。

+0

)据我所知,好的抽象似乎是失去了方程。关于我应该尽可能保持doPost的事实,我不确定如果我能做到这一点,因为API期望通过curl使用一些数组来处理和返回XML。所以,我相信这只是他们需要的方式... – MEM 2010-10-15 18:19:52

0

您可以按以下规则改进设计:

- 不要做实际工作在构造函数(见APIConnect)
-favor组成
-inject在构造函数依赖
-meaningful类/接口名
-single责任

我会重构这个更像是这样的:

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 
    } 
} 

我不知道这是否是您可以使用的示例,因为APIThis和APIThat有点难以理解。如果我误解了,请澄清你的意图。

+0

接口是否是好的如果我们还需要连接其他的API,那么在这种情况下,所有的API都将在这个应用程序的整个生命周期中被需要。这个附加信息是否有用?我不确定实现之间有什么区别一个扩展类的接口,不用担心,我会阅读它,但我没有了解注射和它与组成的关系,然而,我有一个问题,在您的示例中,FarmController如何使用连接? – MEM 2010-10-15 18:12:35

+0

它与您的示例中使用的方式相同。因为我没有真正理解我是如何认为它需要它。您可以将界面视为责任。在这种情况下,它说“我负责创建连接”。不同的班级可以以不同的方式实施责任,而不需要客户关心如何。 – koen 2010-10-15 18:20:27