Описание: Разработка и отладка приложений. Упор на 3D-графику.
-
dyvniy
- Автор темы, Администратор
-
-
dyvniy
- Автор темы, Администратор
- Возраст: 41
- Репутация: 1
- Лояльность: 1
- Сообщения: 3579
- Зарегистрирован: Ср, 10 октября 2012
- С нами: 11 лет 6 месяцев
- Профессия: Программист
- Откуда: Россия, Москва
-
ICQ
Сайт
Skype
ВКонтакте
#7 dyvniy » Пт, 19 сентября 2014, 10:19:58
Синглертон
http://lifeexample.ru/php-primeryi-skriptov/php-singleton-singlton.html- Спойлер
- Только для читателей Lifeexample возможно открыть интернет магазин на Moguta.CMS со скидкой в 15%
<<< XSS уязвимость и защита от XSS || Бесплатная CMS для интернет магазина >>>
PHP Singleton (Синглтон)
26.07.2012
PHP Singleton (Синглтон)
Здравствуйте, уважаемые читатели блога LifeExample, сегодня мы будем разбираться с очередным шаблоном программирования в PHP – Синглтоном (Singleton).
Паттерн Singleton по-настоящему полезен в крупных проектах, и на частных примерах будет не просто понять, для чего он нужен. Поэтому я предлагаю сделать нечто большее, чем просто привести код класса Singleton, как это делается в большинстве статей и материалах по теме.
Подобно тому, как мы разбирались с паттерном MVC, я хочу показать вам, как по шагам сделать маленькую систему работы с базой данных, используя в php синглтон, для подключения к ней.
Концепция шаблона Singleton
Страшное слово синглтон ассоциируемое у меня, по названию, c мелафоном из сериала «Гостья из будущего» (1984 г.), совершенно не имеет никакого сходства с машиной времени.
Singleton – это обычный php класс, в логику работы которого включена проверка на эксклюзивность его создания. Т.е. объект класса, построенный по шаблону синглтона, может быть создан лишь один раз. Все будущие попытки обратиться к его методу или свойству, создав новый объект, будут нейтрализованы логикой его работы и перенаправлены на уже имеющийся экземпляр.
Таким образом, класс, построенный по принципу синглтона, будет защищен от многочисленного создания и дублирования действий при интерпретации кода.
Представим, что у нас есть класс, инициализирующий какие либо настройки. Для инициализации он может считывать информацию из текстовых файлов и/или таблиц БД.
Также в этом классе присутствуют интерфейсы для получения тех или иных настроек. Так вот, когда в разных частях программы нам необходимо получить тот или иной параметр настроек, мы создаем новый объект и с помощью его интерфейса получаем данные.
В ходе работы системы, проведение таких операций может потребоваться очень часто, и каждый раз будет создаваться новый экземпляр класса, а соответственно будет дублироваться работа по сбору настроек из БД и файлов, что не очень лестно скажется на работе всей системы.
Как вариант можно создать глобальный объект и пользоваться только им, но ничто не защитит его от повторного создания, и пришедший в команду новый неопытный разработчик, пренебрегая соглашением об использовании глобального объекта, будет создавать дубликат столько раз, сколько ему захочется.
Решением этой проблемы как раз и занимается шаблон Singleton.
Обычный пример PHP Singleton
Давайте ознакомимся с концепцией и классическим примером реализации php синглтона. Взгляните на этот код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class someClass {
protected static $_instance;
private function __construct() {
}
public static function getInstance() {
if (self::$_instance === null) {
self::$_instance = new self;
}
return self::$_instance;
}
private function __clone() {
}
private function __wakeup() {
}
}
?>
В данном коде представлен некоторый класс, в логике работы которого, реализован паттерн – синглтон.
Первым делом объявляется защищенная статическая переменная $_instance, назначением которой является хранение в себе единственного экземпляра данного класса.
Конструктор в синглтоне защищен от публичного вызова, а следовательно исключает дублирование объектов.
Другими словами, если попытаться создать объект (PHP Singleton) класса стандартным образом:
1
obj= new someClass();
то мы получим сообщение об ошибке, в котором сказано, что конструктор доступен только изнутри класса.
1
Call to private someClass::__construct() from invalid context in…
Для того чтобы создать объект нам нужно вызвать статический метод getInstance(); таким образом:
1
someClass::getInstance();
Единственной точкой входа в класс является статическая функция getInstance() цель которой – создать первый и единственный экземпляр класса, записав его в переменную $_instance. При вызове getInstance() функция создает экземпляр класса, а следовательно задействует механизм конструктора.
Неотъемлемой частью синглтона в PHP является объявление приватных магических методов __clone() и _wakeup() , предотвращающих возможные дублирования объекта.
На этом классическое описание модели, во многих ресурсах сети заканчивается. Но остается вопрос, как пользоваться синглтоном в PHP, а главное зачем?
Пока не попробуете на практике, смысла не уловите, поэтому я настоятельно советую вам потратить еще 10 минут своего свободного времени, и посмотреть как можно на практике использовать паттерн Singleton в PHP.
PHP Singleton на примере класса для работы с БД
Если кто-то забыл, или не знает основ для работы с базами данных в php, читайте статью PHP работа с базой данных (Часть 1)
Самым подходящим примером будет маленькая система для работы с БД. Под маленькой системой я подразумеваю три файла :
index.php – точка входа в систему
class.db.php – singleton для работы с БД
class.order.php – некоторый вымышленный класс внутри которого идет работа с БД с помощью синглтона
Первым делом создадим index.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
error_reporting(E_ALL);
require 'class.db.php';
// константы для подключени к БД
define('HOST', 'localhost'); //сервер
define('USER', 'root'); //пользователь
define('PASSWORD', ''); //пароль
define('NAME_BD', 'test');//база
DB::getInstance(); // инициализация экземпляра класса дл работы с БД
//свободное использование класса
//вывод таблицы продуктов
$result=DB::query("SELECT id,product FROM `product`");
echo '<h2>Таблица продуктов:</h2> <table border="1">';
while($obj=DB::fetch_object($result)){
echo '<tr><td>'.$obj->id.'</td><td>'.$obj->product.'</td><tr>';
}
echo '</table>';
В коде index.php подключается файл class.db.php, содержащий реализацию синглтона, и производится инициализация констант для доступа к базе данных, а также инициализация объекта для работы с БД DB::getInstance();.
Примечание! Для более оптимизированной работы с синглтоном, можно внести вызов getInstance(); внутрь используемых классом публичных функций. Это поможет устранить необходимость явного определения экземпляра класса описанным выше методом DB::getInstance();
Далее следует пример работы с классом синглтона, в котором выводится содержимое таблицы product.
Чтобы это все заработало нужно создать файл class.db.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<?class DB {
protected static $_instance; //экземпляр объекта
public static function getInstance() { // получить экземпляр данного класса
if (self::$_instance === null) { // если экземпляр данного класса не создан
self::$_instance = new self; // создаем экземпляр данного класса
}
return self::$_instance; // возвращаем экземпляр данного класса
}
private function __construct() { // конструктор отрабатывает один раз при вызове DB::getInstance();
echo "<br/><em>1. Установка соединения с хостом...";
//подключаемся к БД
$this->connect = mysql_connect(HOST, USER, PASSWORD) or die("Невозможно установить соединение".mysql_error());
// выбираем таблицу
echo "<br/>2. Выбор базы...";
mysql_select_db(NAME_BD, $this->connect) or die ("Невозможно выбрать указанную базу".mysql_error());
// устанавливаем кодировку таблицы
echo "<br/>3. Устанавливаем кодировку базы: ";
$this->query('SET names "utf8"');
echo "<br/> Конструктор успешно открыл соединение с БД! и установил кодировку.</em>";
}
private function __clone() { //запрещаем клонирование объекта модификатором private
}
private function __wakeup() {//запрещаем клонирование объекта модификатором private
}
public static function query($sql) {
$obj=self::$_instance;
if(isset($obj->connect)){
$obj->count_sql++;
$start_time_sql = microtime(true);
$result=mysql_query($sql)or die("<br/><span style='color:red'>Ошибка в SQL запросе:</span> ".mysql_error());
$time_sql = microtime(true) - $start_time_sql;
echo "<br/><br/><span style='color:blue'> <span style='color:green'># Запрос номер ".$obj->count_sql.": </span>".$sql."</span> <span style='color:green'>(".round($time_sql,4)." msec )</span>";
return $result;
}
return false;
}
//возвращает запись в виде объекта
public static function fetch_object($object)
{
return @mysql_fetch_object($object);
}
//возвращает запись в виде массива
public static function fetch_array($object)
{
return @mysql_fetch_array($object);
}
//mysql_insert_id() возвращает ID,
//сгенерированный колонкой с AUTO_INCREMENT последним запросом INSERT к серверу
public static function insert_id()
{
return @mysql_insert_id();
}
}
Сей класс является рабочей реализацией паттерна singleton в php, а также наглядно демонстрирует важность единственности объекта. Для тех кто не видит важности поясню: в конструкторе данного класса производится подключение к БД, если убрать логику синглтона, то нерадивые программисты смогут организовать тысячи бессмысленных подключений к БД .
Кроме того, если углубиться в код, то можно заметить, что функционал класса ведет подсчет количеству выполненных запросов, что было бы не возможно реализовать без синглтона, не прибегая к глобальным переменным.
Раз уж заговорил о возможностях класса, расскажу и о том, что кроме количества запросов, ведется подсчет затраченного на исполнения времени, а это бывает очень полезным при отладке приложения.
Кстати, если в местах вывода заменить echo на вывод в файл, то получится наглядный лог запросов.
На этом описание класса предлагаю завершить, но если есть вопросы пишите в комментариях, отвечу.
Теперь файл index.php можно запускать. Ах да, конечно же вам понадобится импортировать дамп тестовой базы, приложенный в исходниках, или обращаться к своей БД :
Наследование Singleton в PHP
Мы уже имеем возможность обращаться к функциям синглтона, теперь попробуем сделать это в отдельном классе Order.
Многие новички делают не правильные выводы относительно данного шаблона программирования и пытаются сделать наследование дочерних классов от синглтона.
При таком подходе теряется весь смысл синглтона как механизма, защищающего дублирование объектов.
Если вы хотите наследовать некоторый класс от синглтона, то в самом синглтоне вам придется открыть публичный доступ к конструктору класса. В противном случае вы будете получать ошибку:
1
Call to private someClass::__construct() from invalid context in…
А открыв публичный доступ ломается вся защита.
Поэтому наследовать PHP Singleton, не рационально и бессмысленно, так как можно обращаться к классу синглтона из любой точки программы, инициализировав его единожды в index.php.
В следующем классе это наглядно продемонстрировано:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
//попробуем создать класс и внутри него работать с БД
class Order {
public function getOrderList(){
// $result=DB::query("INSERT `order` SET id=4,content=777");
$result=DB::query("SELECT id,content FROM `order` where id=4");
$html='<h2>Таблица заказов:</h2> <table border="1">';
while($obj=DB::fetch_object($result)){
$html.='<tr><td>'.$obj->id.'</td><td>'.$obj->content.'</td><tr>';
}
$html.='</table>';
return $html;
}
}
Создайте class.order.php и вставьте в него вышеприведенный код. В конец файла index.php допишите следующее:
1
2
3
4
5
6
7
8
require 'class.order.php';
$order = new Order();
echo $order->getOrderList();
//попробуем создать новый экземпляр DB
echo "<span style='color:red'>";
$DB2 = new DB();
Запустив приложение вы должны будете наблюдать такую картину:
Пример синглтона в php
Ошибка в конце страницы сгенерирована намеренно, для демонстрации защиты от дублирования PHP Singleton. Избавиться от ошибки можно, удалив последнюю строку:
1
$DB2 = new DB();
На этом, я предлагаю завершить наше знакомство с очередным шаблоном программирования PHP Singleton‘ом, надеюсь, материал окажется вам полезен. Подписывайтесь на RSS обновления и не пропустите следующей статьи о другом не мало известном паттерне программирования Registry.
-
dyvniy
- Автор темы, Администратор
-
-
dyvniy
- Автор темы, Администратор
- Возраст: 41
- Репутация: 1
- Лояльность: 1
- Сообщения: 3579
- Зарегистрирован: Ср, 10 октября 2012
- С нами: 11 лет 6 месяцев
- Профессия: Программист
- Откуда: Россия, Москва
-
ICQ
Сайт
Skype
ВКонтакте
#8 dyvniy » Пт, 19 сентября 2014, 10:31:15
Подключание к PayPal
http://lifeexample.ru/php-primeryi-skriptov/integ ... -paypal-prostoy-php-klass.html- Спойлер
- Интеграция PayPal, простой PHP класс
18.12.2013
Интеграция PayPal. Простой PHP класс
самой надежной в мире системой электронных оплат.
PayPal (англ. «приятель, помогающий расплатиться») — крупнейший оператор электронных денежных средств. Позволяет клиентам оплачивать счета и покупки, отправлять и принимать денежные переводы. С октября 2002 года является подразделением компании eBay. По состоянию на 2012 год PayPal работает в 193 странах (хотя не во всех предоставляется полный набор услуг), имеет более 137 млн зарегистрированных пользователей, работает с 26 национальными валютами.
Просмотрев некоторые примеры в сети, я был поражен их несостоятельностью. Представленные ниже классы для интеграции PayPal на сайт, не являются сложными, но соответствуют моему требованию о покупке товара поштучно. Код не идеален, но вы всегда можете доработать его самостоятельно.
Я решил подойти к вопросу обработки IPN разбив процессы на объекты, отвечающие за выполнение логических под-задач для того, чтобы было понятно программистам знакомым с объектно-ориентированным программирование. ( Даже если вы не знакомы, я надеюсь, что моя статья даст вам возможность увидеть преимущества и лучше понять методологию, сэкономив много времени на будущее.)
Интеграция PayPal
Для того чтобы не упустить важные детали собственной настройки ниже я собираюсь копировать вставлять свой код и изменять соответствующую информацию. Конечно, статья из-за этого увеличится и будет создаваться впечатление сборки кода, но я считаю, что в самом коде содержится необходимая информация, и заранее приношу свои извинения, поскольку вам придется скопировать несколько файлов из этой статьи, если вы их собираетесь использовать для своего проекта и вставить их в собственный проект.
Мое решение разделяет процесс на пять объектов:
payPalController – этот класс занимается обработкой логики не связанных с IPN частей PayPal процессов. Они занимается проверкой двойных транзакций, отправляемых PayPal, и проверяет факт совершения IPN транзакции именно по продукту с моего сайта. В таком случае, покупка добавляется в базу данных, а покупатель получает email.
payPalIpn – место проведения обработки IPN. Очень важно!
rmwStoreDB – с помощью этого класса транзакции добавляются в базу данных с моей стороны.
<!doctype html public '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>
<html>
<head>
<title>Some Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Generator" content="Alleycode HTML Editor">
<meta name="Description" content="Working Code">
<meta name="Keywords" content="Working Code">
</head>
<body>
<?php
require_once ("../phpPayPalController.php");
$ppc = new payPalController();
$ppc->setTesting(false);
$ppc->setLogging(false);
$ppc->processPayPalIpnPayment();
?>
</body>
Как вы видите payPalController – единственный класс, о котором нужно знать странице. Контроллер настроит остальные классы самостоятельно:
<?php
require_once("phpPayPalIpnClass.php");
require_once("phpLoggerClass.php");
require_once("phpRmwStoreDbActions.php");
require_once("phpMyMailClass.php");
class payPalController {
private $db;
private $logger;
private $testing;
function __construct() {
$this->logger = new myLogger();
$this->logger->setLogFile("logger.txt");
$this->logger->setLogging(false);
$this->db = new rmwStoreDB();
$this->db->setLogger($this->logger);
$this->testing = false;
}
function setTesting($state) {
$this->testing = $state;
$this->logger->setLogging($state);
}
function setLogging($state) { $this->logger->setLogging($state); }
function processPayPalIpnPayment() {
$processor = new payPalIpn();
$processor->setTesting($this->testing);
$processor->setLogger($this->logger);
$this->logger->log("Processing a payment.\r\n");
if (!$processor->processPost()) return;
if ($this->duplicateTransaction()) return;
if (!$this->verify()) return;
if (!$this->addOrderToDatabase()) return;
$this->sendProduct();
}
private function duplicateTransaction() {
$ret = false;
if ($this->db->itemExists("orders", "payPalTransId",
$_POST['txn_id'])) {
$this->logger->log("Transaction: " . $_POST['txn_id']
. " exists\r\n");
$ret = true;
}
else {
$this->logger->log("Transaction: " . $_POST['txn_id'] .
" does not exist\r\n");
}
return $ret;
}
private function verify() {
if (!$this->db->itemExists("products", "id", $_POST
['item_number'])) {
$this->logger->log("Item number: " . $_POST['item_number']
. " doesn't exist in database\r\n");
return false;
}
else {
$this->logger->log("Item number: " . $_POST['item_number'] .
" exists in database\r\n");
}
$this->dbPrice = $this->db->getCellValue("price",
"products", "id", $_POST['item_number']);
if ($_POST['mc_gross'] < $this->dbPrice) {
$this->logger->log("Payment received (" . $_POST
['mc_gross'] . ") less than item price. ("
. $this->dbPrice . "\r\n");
return false;
}
else {
$this->logger->log("Adequate payment received (" . $_POST
['mc_gross'] . ").\r\n");
}
if ($_POST['mc_currency'] != "USD") {
$this->logger->log("Paid in non-US funds - need to investigate.\r\n");
return false;
}
else {
$this->logger->log("US Currency received - OK.\r\n");
}
if ($_POST['receiver_email'] !=
"emailAddress@someplace.com"
&& $_POST['receiver_email'] !=
"sandboxEmailAddress@someplace.com") {
$this->logger->log("Incorrect receiver email received ("
. $_POST['receiver_email'] . ")\r\n");
return false;
}
else {
$this->logger->log("Correct email received (
" . $_POST['receiver_email'] . ")\r\n");
}
if ($_POST['payment_status'] != "Completed") {
$this->logger->log("Payment incomplete from PayPal\r\n");
return false;
}
return true;
}
private function addOrderToDatabase() {
$this->logger->log("Updating database.\r\n");
$this->db->addOrUpdateUser();
$this->db->addOrder();
return true;
}
private function sendProduct() {
$mailHandler = new myMailer();
$mailHandler->setLogger($this->logger);
if ($this->testing) {
$mailTo = 'emailAddress@someplace.com';
}
else {
$mailTo = $_POST['payer_email'];
}
if ($_POST['item_number'] == "XXXX" || $_POST
['item_number'] == "XXXY") {
if ($_POST['option_selection1'] == 'EPub') {
$this->logger->log("Sending EPub to " . $mailTo .
"\r\n");
$mailHandler->sendEbook('EPub', $mailTo);
}
else if ($_POST['option_selection1'] == 'MOBI') {
$this->logger->log("Sending MOBI to " . $mailTo . "\r\n");
$mailHandler->sendEbook('MOBI', $mailTo);
}
else {
$this->logger->log("SOMETHING WRONG - Not EPub or MOBI!\r\n");
}
}
}
}
?>
Теперь перейдем к классу payPalIpn. Как было сказано ранее, этот класс ответственен за обработку IPN и отправку корректных ответов на PayPal.
require_once("db_config.php");
require_once("phpLoggerClass.php");
class rmwStoreDB {
private $loggerC;
private $lastRowC;
function setlogger(mylogger $logFile) { $this->loggerC = $logFile; }
function tellDb($sql) {
$ret = mysql_query($sql);
if (!$ret) {
$this->loggerC->log(
"DATABASE ERROR:\r\n" . mysql_error() . "\r\n" .
"Query: " . HtmlEntities($sql));
die();
}
return $ret;
}
function itemExists($table, $column, $value) {
$rows = $this->tellDb("Select * from " . $table . " where " .
$column . " = '" . $value . "'");
$lastRowC = mysql_fetch_array($rows);
if ($lastRowC) return true;
return false;
}
function getCellValue($what, $table, $column, $theId) {
$rows = $this->tellDb("Select " . $what . " from " . $table .
" where " . $column . " = " . $theId);
$row = mysql_fetch_array($rows);
if ($row) return $row['price'];
else return 0.00;
}
function addOrUpdateUser() {
$rows = $this->tellDb("Select * from customers where email = '" .
$_POST['payer_email'] . "'");
$row = mysql_fetch_array($rows);
if (!$row) {
$this->loggerC->log("Adding user to database");
$this->addUser();
}
else {
$this->loggerC->log("User already exists in DB.\r\n");
$this->updateUser($row);
}
}
private function addUser() {
$cmd = "Insert into customers (firstName, lastName, shippingName, email, " .
"addressLine1, city, state, zipCode, country) values ('"
. $_POST['first_name'] . "', '" .
$_POST['last_name'] . "', '" .
$_POST['address_name'] . "', '" .
$_POST['payer_email'] . "', '" .
$_POST['address_street'] . "', '" .
$_POST['address_city'] . "', '" .
$_POST['address_state'] . "', '" .
$_POST['address_zip'] . "', '" .
$_POST['address_country'] . "')";
$this->tellDb($cmd);
$this->loggerC->log("Added: '" . $_POST['first_name'] .
"', '" . $_POST['last_name'] .
"', '" . $_POST['address_name'] .
"', '" . $_POST['payer_email'] .
"', '" . $_POST['address_street'] .
"', '" . $_POST['address_city'] .
"', '" . $_POST['address_state'] .
"', '" . $_POST['address_zip'] .
"', '" . $_POST['address_country'] .
"')");
}
private function updateUser(array $row) {
if ($row['firstName'] != $_POST['first_name'] ||
$row['lastName'] != $_POST['last_name'] ||
$row['shippingName'] != $_POST['address_name'] ||
$row['email'] != $_POST['payer_email'] ||
$row['addressLine1'] != $_POST['address_street'] ||
$row['city'] != $_POST['address_city'] ||
$row['state'] != $_POST['address_state'] ||
$row['zipCode'] != $_POST['address_zip'] ||
$row['country'] != $_POST['address_country']) {
$cmd = "UPDATE customers SET ";
$cmd .= "firstName = '" . $_POST['first_name'] . "', ";
$cmd .= "lastName = '" . $_POST['last_name'] . "', ";
$cmd .= "shippingName = '" . $_POST['address_name'] . "', ";
$cmd .= "addressLine1 = '" . $_POST['address_street'] . "', ";
$cmd .= "city = '" . $_POST['address_city'] . "', ";
$cmd .= "state = '" . $_POST['address_state'] . "', ";
$cmd .= "zipCode = '" . $_POST['address_zip'] . "', ";
$cmd .= "country = '" . $_POST['address_country'] . "' ";
$cmd .= "WHERE email = '" . $_POST['payer_email'] . "'";
$this->loggerC->log("\r\nChanging user with email " . $_POST['payer_email'] . "\r\n");
$old = $row['firstName'] . ", " . $row['lastName'] .
", " . $row['shippingName'] . ", " .
$row['email'] . ", " .
$row['addressLine1'] . ", " . $row['city'] .
", " .$row['state'] . ", " .
$row['zipCode'] . ", " . $row['country'] .
"\r\n\r\n";
$this->loggerC->log($old);
$this->loggerC->log($cmd . "\r\n");
$this->tellDb($cmd);
}
}
function addOrder() {
$cmd = "Select id from customers where email = '" .
$_POST['payer_email'] . "'";
$rows = $this->tellDb($cmd);
$row = mysql_fetch_array($rows);
if (!$row) {
$this->loggerC->log("HUGE PROBLEM! CUSTOMER ID NOT FOUND -" .
" ABORTING\r\n");
die();
}
$id = $row['id'];
$theDate = date('F j, Y, g:i a');
$tz = date('T');
$ppID = $_POST['txn_id'];
$grossPay = $_POST['payment_gross'];
$shipping = $_POST['shipping'];
$cmd = "Insert into orders (customer, date, timeZone, payPalTransId, " .
"grossPmt, shipping) values ('$id', '" .
"$theDate', '$tz', '$ppID', '" .
"$grossPay', '$shipping')";
$this->tellDb($cmd);
$this->loggerC->log("Inserting order into orders table:\r\n" . $cmd .
"\r\n\r\n");
$cmd = "Select id from orders where payPalTransId = '$ppID'";
$rows = $this->tellDb($cmd);
$row = mysql_fetch_array($rows);
if (!$row) {
$this->loggerC->log("HUGE PROBLEM! ORDER ID NOT FOUND -" .
" ABORTING\r\n");
die();
}
$id = $row['id'];
$itemNum = $_POST['item_number'];
$qty = $_POST['quantity'];
$info = $_POST['option_selection1'];
$cmd = "Insert into orderItems (orderNumber, item, quantity, extraInfo)" .
" values('$id', '$itemNum', '$qty'," .
" '$info')";
$this->loggerC->log(
"Inserting into order items:\r\n" . $cmd . "\r\n");
$this->tellDb($cmd);
}
}
?>
Ура! Следующие классы PHP для интеграции PayPal намного меньше предыдущих! Первый класс – почтового клиента. Понятное дело, что при его простоте можно сказать, что он должен быть более ярким и отправлять получше чем сейчас отформатированные HTML ответы на покупки. Но всему свое время.
<?php
require_once("emailPassword.php");
require_once("phpLoggerClass.php");
require_once("/path_to/swift_required.php");
class myMailer {
private $myEmail;
private $logger;
function __construct() {
$this->myEmail = "someone@somewhere.com";
}
function setLogger(myLogger &$logFile) { $this->logger = $logFile; }
function sendEbook($ebookType, $mailTo) {
$this->mailWithAttachment($fileName, $path, $mailTo, $this->myEmail, $from,
$replyTo, $subject, $msg);
}
private function mailWithAttachment($filename, $path, $mailTo, $from_mail, $from_name,
$replyto, $subject, $message) {
$transport = Swift_SmtpTransport::newInstance('mailServer.com', 465, 'ssl')
->setUsername(hiddenEmailAccount())
->setPassword(hiddenEmailPassword())
;
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance()
->setSubject($subject)
->setFrom(array($from_mail => $from_name))
->setTo(array($mailTo))
->setBody($message)
//->addPart('<p>Here is the message itself</p>', 'text/html')
->attach(Swift_Attachment::fromPath($path.$filename))
;
$this->logger->forceLog("Sending " . $filename . " to " . $mailTo .
" : ");
$result = $mailer->send($message);
$this->logger->forceLog("Result = " . $result . "\r\n");
}
}
?>
Последним идет класс логов:
<?php
class myLogger {
private $fileNameC;
private $doLoggingC;
function __construct() {
$this->fileNameC = "log.txt";
$this->doLoggingC = true;
}
function setLogFile($fileName) { $this->fileNameC = $fileName; }
function setLogging($state) { $this->doLoggingC = $state; }
function log($msg) {
if ($this->doLoggingC == true) {
file_put_contents($this->fileNameC, $msg, FILE_APPEND);
}
}
function forceLog($msg) {
file_put_contents($this->fileNameC, $msg, FILE_APPEND);
}
}
?>
Также необходимы еще два файла, если хотите, можете их скомбинировать в один, внеся представленные изменения. Они предназначены для хранения информации базы данных и информации о email. Повторюсь еще раз, очень важно, чтобы эти файлы не находились в широком доступе, поэтому рекомендую ограничить к ним доступ.
Содержание db_config.php файла следующее. За исключением того, что здесь не представлены реальные пользователи, пароли и базы данных!
$db_con = mysql_connect("localhost", "theUser", "thePassword", true) or die(mysql_error());
$db_selected = mysql_select_db("theDatabase") or die(mysql_error());
И наконец, файл с паролем email (“emailPassword.php” в представленном выше коде):
<?php
function hiddenEmailAccount() {
return "someone@somewhere.com";
}
function hiddenEmailPassword() {
return "thePassword";
}
?>
Надеюсь, представленная информация была полезной, если вы собираетесь заниматься интеграцией PayPal с помощью простого PHP класса. Спасибо за того, что прочитали мою статью и удачного вам программирования. Если вам удастся, что-то улучшить, буду рад увидеть улучшения в комментариях.
-
dyvniy
- Автор темы, Администратор
-
-
dyvniy
- Автор темы, Администратор
- Возраст: 41
- Репутация: 1
- Лояльность: 1
- Сообщения: 3579
- Зарегистрирован: Ср, 10 октября 2012
- С нами: 11 лет 6 месяцев
- Профессия: Программист
- Откуда: Россия, Москва
-
ICQ
Сайт
Skype
ВКонтакте
#10 dyvniy » Вс, 5 апреля 2015, 07:59:22
инъекция
https://www.xaker.name/forvb/showthread.php?t=13504Потенциально опасными функциями являются:
eval(),
preg_replace() (с модификатором «e»),
require_once(),
include_once(),
include(),
require(),
create_function().
PHP-инъекция становится возможной, если входные параметры принимаются и используются без проверки.
-
dyvniy
- Автор темы, Администратор
-
-
dyvniy
- Автор темы, Администратор
- Возраст: 41
- Репутация: 1
- Лояльность: 1
- Сообщения: 3579
- Зарегистрирован: Ср, 10 октября 2012
- С нами: 11 лет 6 месяцев
- Профессия: Программист
- Откуда: Россия, Москва
-
ICQ
Сайт
Skype
ВКонтакте
#12 dyvniy » Ср, 11 ноября 2015, 07:36:28
загрузка на сервер №2
http://javascript.ru/forum/dom-window/28174-zagru ... -server-sredstvami-iframe.html- Спойлер
- 10.05.2012, 12:14
lamer lamer вне форума
Профессор
Отправить личное сообщение для lamer Посмотреть профиль Найти все сообщения от lamer
Регистрация: 08.02.2012
Сообщений: 214
Загрузка файла на другой сервер средствами iframe
Здравствуйте.
Появилась необходимость загружать файлы на второй сервер принимая их на первом.
т.е. юзер загружает файл на server-1, а файл загружается на server-2
Читал что можно подобное реализовать без перезагрузки страницы методом Remote Scripting используя iframe. Но конкретных примеров с подробным описанием так и не нашел.
Может кто то встречал в инете и может кинуть линк или выложить в топе с подробным описанием ? Думаю полезно было бы не только мне.
Заранее спасибо.
Ответить с цитированием
#2 (permalink)
Старый 10.05.2012, 16:38
lamer lamer вне форума
Профессор
Отправить личное сообщение для lamer Посмотреть профиль Найти все сообщения от lamer
Регистрация: 08.02.2012
Сообщений: 214
Нашел вариант с использованием iframe, все работает и файлы на другой сервер закачивает.
index.html на первом сервере - server-1.com
Код: Выделить всё
<html>
<head>
<meta charset="utf-8">
<title>Облако тегов</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
function hideBtn(){
$('#upload').hide();
$('#res').html("Идет загрузка файла");
}
function handleResponse(mes) {
$('#upload').show();
if (mes.errors != null) {
$('#res').html("Возникли ошибки во время загрузки файла: " + mes.errors);
}
else {
$('#res').html("Файл " + mes.name + " загружен");
}
}
</script>
</head>
<body>
<form action="http://server-2.com/uploads/upload.php" method="post" target="hiddenframe" enctype="multipart/form-data" onsubmit="hideBtn();">
<input type="file" id="userfile" name="userfile" />
<input type="submit" name="upload" id="upload" value="Загрузить" />
</form>
<div id="res"></div>
<iframe id="hiddenframe" name="hiddenframe" style="width:0px; height:0px; border:0px"></iframe>
</body>
</html>
Файл upload.php на втором сервере - server-2.com
Код: Выделить всё
<?php
if(isset($_POST['upload'])){
$whitelist = array(".gif", ".jpeg", ".png");
$data = array();
$error = true;
foreach ($whitelist as $item) {
if(preg_match("/$item\$/i",$_FILES['userfile']['name'])) $error = false;
}
if(!$error) {
$folder = '.../uploads/';$uploadedFile = $folder.basename($_FILES['userfile']['name']);
if(is_uploaded_file($_FILES['userfile']['tmp_name'])){
if(move_uploaded_file($_FILES['userfile']['tmp_name'],$uploadedFile)){
$data = $_FILES['userfile'];
}
else {
$data['errors'] = "Во время загрузки файла произошла ошибка";
}
}
else {
$data['errors'] = "Файл не загружен";
}
}
else{
$data['errors'] = 'Вы загружаете запрещенный тип файла';
}
$res = '<script type="text/javascript">';
$res .= "var data = new Object;";
foreach($data as $key => $value){
$res .= 'data.'.$key.' = "'.$value.'";';
}
$res .= 'window.parent.handleResponse(data);';
$res .= "</script>";
echo $res;
}
else{
die("ERROR");
}
?>
Но проблема в том что если передавать файлы на второй сервер то статус загрузки файла так и остается висеть: Идет загрузка файла хотя файл давно загружен на сервер.
т.е. не получается без перезагрузки страницы получить ответ от второго сервера что файл загружен.
Прочел на одном ресурсе:
Цитата:
возникает проблема с Cross-Domain-Request, если вы имеете доступ к скрипту loader.php на другом сервере, то есть возможность правильно заполнить Cross-Origin заголовки и тогда все запуститься само
Читал про crossdomain.xml прописывал заголовки:
<cross-domain-policy>
<allow-access-from domain="*" to-ports="80"/>
</cross-domain-policy>
Все равно так и висит строка Идет загрузка файла
Название раздела: Программирование (под Desktop и Android)
Описание: Разработка и отладка приложений. Упор на 3D-графику.
Вернуться в «Программирование (под Desktop и Android)»
Сейчас этот раздел просматривают: 22 гостя