В JSON API для какой-то банковский счет


Я занимаюсь разработкой этого класса, и было интересно, если у кого-нибудь мысли о том, как я могу улучшить производительность.

<?php
class Something {
    private $APIUsername, $APIPassword;
    private $APIurl = 'somesite.com';

    function __construct ($APIUsername = '', $APIPassword = '') {
        try {
            if (!$APIUsername || !$APIPassword) {
                throw new Exception('You must specify a valid API username and password.');
            }

            $this->APIUsername = $APIUsername;
            $this->APIPassword = $APIPassword;
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }

    /*
    * Authenticate Account
    */
    public function authenticate ($EmailAddress, $Password) {
        try {
            $data['EmailAddress'] = $EmailAddress;
            $data['Password'] = $Password;

            $data = $this->setJSON($data);

            $result = $this->fetch('authenticate', $data);
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return $result;
    }

    /*
    * Get Contacts
    */
    public function contacts ($EmailAddress, $Password, $PIN) {
        try {
            $data['EmailAddress'] = $EmailAddress;
            $data['Password'] = $Password;
            $data['PIN'] = $PIN;

            $data = $this->setJSON($data);

            $result = $this->fetch('contacts', $data);
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return $result;
    }

    /*
    * Get Transactions
    */
    public function transactions ($EmailAddress, $Password, $PIN) {
        try {
            $data['EmailAddress'] = $EmailAddress;
            $data['Password'] = $Password;
            $data['PIN'] = $PIN;

            $data = $this->setJSON($data);

            $result = $this->fetch('transactions', $data);
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return $result;
    }

    /*
    * Validate PIN
    */
    public function validatepin ($EmailAddress, $Password, $PIN) {
        try {
            $data['EmailAddress'] = $EmailAddress;
            $data['Password'] = $Password;
            $data['PIN'] = $PIN;

            $data = $this->setJSON($data);

            $result = $this->fetch('validatepin', $data);
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return $result;
    }

    /*
    * Get Account Balance
    */
    public function balance ($EmailAddress, $Password) {
        try {
            $data['EmailAddress'] = $EmailAddress;
            $data['Password'] = $Password;

            $data = $this->setJSON($data);

            $result = $this->fetch('balance', $data);
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return $result;
    }

    /*
    * Get Account Information
    */
    public function account_information ($EmailAddress, $Password) {
        try {
            $data['EmailAddress'] = $EmailAddress;
            $data['Password'] = $Password;

            $data = $this->setJSON($data);

            $result = $this->fetch('account_information', $data);
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return $result;
    }

    /*
    * Send Money
    */
    public function send ($EmailAddress, $Password, $PIN, $DestinationID, $Amount, $Notes = '', $FundsSource = '') {
        try {
            $data['EmailAddress'] = $EmailAddress;
            $data['Password'] = $Password;
            $data['PIN'] = $PIN;
            $data['DestinationID'] = $DestinationID;
            $data['Amount'] = $Amount;
            $data['Notes'] = urlencode($Notes);
            $data['FundsSource'] = $FundsSource;

            $data = $this->setJSON($data);

            $result = $this->fetch('send', $data);
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return $result;
    }

    /*
    * Send (Sender Assumes Transaction Costs)
    */
    public function send_assume_costs ($EmailAddress, $Password, $PIN, $DestinationID, $Amount, $Description = '') {
        try {
            $data['EmailAddress'] = $EmailAddress;
            $data['Password'] = $Password;
            $data['PIN'] = $PIN;
            $data['DestinationID'] = $DestinationID;
            $data['Amount'] = $Amount;
            $data['Description'] = urlencode($Description);

            $data = $this->setJSON($data);

            $result = $this->fetch('send_assume_costs', $data);
        } catch (Exception $e) {
            $result = $e->getMessage();
        }

        return $result;
    }

    /*
    * Set JSON Data
    */
    private function setJSON ($data) {
        $a = array();

        $a['APIUsername'] = $this->APIUsername;
        $a['APIPassword'] = $this->APIPassword;

        foreach ($data as $key => $value) {
            $a[$key] = $value;
        }

        return json_encode($a);
    }

    /*
    * Helper method that talks to teh API
    */
    private function fetch($APIMethod, $data) {
        $c = curl_init($this->APIurl.$APIMethod);
        curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($c, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-Type: application/json'));
        curl_setopt($c, CURLOPT_POSTFIELDS, $data);

        $returned = curl_exec($c);
        if ($returned === false) {
            throw new Exception(curl_error($c)); return;
        }

        curl_close($c);

        if (json_decode($returned)) {
            return $returned;
        } else {
            throw new Exception('Invalid Service Request.'); return;
        }
    }
}
?>


650
6
задан 29 января 2011 в 07:01 Источник Поделиться
Комментарии
2 ответа

Некоторые вещи я заметил.

Кажется, что много/все государственные функции просто делает то же самое, настройка функций параметры в массив, называя setJSON , который просто добавляет APIusername и APIpassword а потом принести и поймать любые ошибки. Вы могли бы иметь один метод, который делает это, и только методами, которые отличаются от этой логики будет делать что-то другое.

похоже, вы можете просто использовать PHP-это компактный() функция для большинства того, что вы делаете.

Для setJSON(), вместо перебора $данные и переделать то же время, почему бы просто не добавить $данных['APIUsername'] = $этом->APIUsername; и $данных['APIPassword'] = $этом->APIPassword; а потом вернуть json_encode($данных)

Для вашего метод fetch() метод, вы могли бы избавиться от завитка требование и просто использовать потоки в PHP, используя комбинацию помощью функции stream_context_create() и функции file_get_contents().

Я думаю, что это может быть полезно взглянуть на это статьи про исключения .

Если вы на самом деле просто передавая данные с логином и паролем прилагается, вы можете просто хочу, чтобы просто использовать магию и__Call метод, который будет проверять массив допустимых методов API для вызова, а затем взять параметры, компактная, добавить имя пользователя и пароль, а затем вызов метода выборки с помощью этих данных и возвращения. Пример ниже.

<?php
class API {
protected $_api_methods = array(
'balance' => array('EmailAddress', 'Password'),
);

private $_api_username;
private $_api_password;
private $_api_url = 'someurl.com';

public function __construct($username, $password)
{
if (!$username || !$password) {
throw new APIException('You must provide API credentials');
}

$this->_api_username = $username;
$this->_api_password = $password;
}

public function __call($method_name, $arguments)
{
if (!in_array($method_name, array_keys($this->_api_methods)) {
throw new APIException("$method_name is not a valid API method");
}

$data = $this->setJSON($method_name, $arguments);
return $this->fetch($method_name, $data);
}

protected function setJSON($method_name, $data)
{
if (empty($data)) {
throw new APIException('No data provided');
}

$data = array_combine($this->_api_methods[$method_name], $data);

$data['api_username'] = $this->_api_username;
$data['api_password'] = $this->_api_password;

return json_encode($data);
}

protected function fetch($method, $data)
{
$context = stream_context_create(array(
'http' => array(
'method' => 'GET',
'timeout' => 5,
),
));

try {
$ret = file_get_contents($this->_api_url . $method, false, $context);
} catch (APIException $e) {
$ret = $e->getMessage();
}

return $ret;
}
}

class APIException extends Exception {}

2
ответ дан 30 января 2011 в 12:01 Источник Поделиться

Я думаю, что "производительность" вы имеете в виду стоимость содержания PHP сессии открытым до тех пор, как завить запрос, ждет ответа. Если речь идет о "скорости на PHP" или "время загрузки" и т. д. тогда, пожалуйста, не поймите меня неправильно, но PHP-это конная ферма, она никогда не станет хорошей скаковой лошади.

Технически нет никакого способа, чтобы ускорить удаленных вызовов API, как вы всегда нужно ждать, что. Библиотеку curl должны, как правило, выполняет очень хорошо, однако я не являюсь экспертом, когда дело доходит до PHP+завиток.

Единственное, что я замечаю, это то, что вы отключить проверку сертификат SSL. Делать это позволяет для MITM-атак, так что, возможно, это не очень хорошая идея (SSL без проверки это как презерватив с дыркой).

Что приходит в голову, что он всегда не хорошая идея, чтобы сохранить вызовов RPC с более длительный срок, так что я бы порекомендовал изменить на более фаз. Однако это лишает класса, как полная система должна быть модифицирована.

Я не могу показать вам код, но вот такая идея:


  1. Когда пользователь отправляет RPC для вашего приложения, приложение сохраняет запрос (в какой таблице базы данных) и сразу же возвращается, так что пользователь может увидеть что-то вроде "обработка" на странице.

  2. На фоне некоторых задач принимает запрос, которая хранится (в базе) и процессов в нем. Результат сохраняется (в базе данных).

  3. Затем на стороне клиента поголовно (или ждет, повторов и т. д.) до получения результата.

"Забавные" вещи о том, что это занимает даже больше времени из-за обработки фоновых заданий. Однако, как пользователь может увидеть некоторый прогресс опыт ожидания лучше.

Возможно, вы даже можете сделать это полностью асинхронный, поэтому, если пользователь переводит деньги, вы увидите некоторые "запланированные задачи" списка, так что пользователь может продолжать делать другие вещи (это, вероятно, включает в Аякс). А потом, когда результат налицо, в "запланированные задачи" мигает (или как там, ну вы поняли) таким образом, что пользователь может выглядеть в результате.

Все это вопрос дизайна: подумайте о ситуации, DOS, где 1000 пользователей нажать на кнопку "Отправить деньги" в ту же секунду (возможно, после некоторых ТВ добавить побежал). Тогда ваш веб-сервер должен держать открытым 1000 сессий, пока все 1000 запросов завиток параллельно. В API на стороне, как правило, имеют некоторые предупреждения DOS и отклонить 980 запросов завиток, потому что вы разрешается иметь только 20 запросов одновременно открывать с тем же API-ключ (это довольно часто).

Так что все равно придется сериализовать запросы. Делаю это в PHP (как в классе) - это боль в** (проблемы голода, прерывание вручную. отладка параллелизма и т. д.), но с фоновыми задачами легко: если у вас есть только, скажем, 10 параллельных процессоров хранимых запросов, там никогда не будет никаких проблем с достижением предельного запрос API.

0
ответ дан 30 января 2011 в 01:01 Источник Поделиться