|
|
|
| Всем доброго времени суток!
Очень тяжело самому обучаться программированию в том плане, что некому подсказать как лучше и указать где неправильно. Поэтому такая банальная тема...
Имеет ли такой класс право на жизнь? Часто ли в реальных условиях случается так, что нужно несколько разных соединенний к БД? Вообще, бывают ли такие случаи?
Что сделал правильно, а что неправильно? Подскажите, пожалуйста.
Заранее большое спасибо.
<?php
class MySQL {
/**
* Contains all instances of the MySQL class
*
* @staticvar array
*/
private static $instances = array();
/**
* Specify the connection parameters
* NOTE: This is an associative array so the indexes are already specfied as:
* - 'hostname';
* - 'username';
* - 'password';
* Make sure you pass all the required parameters using the predifined indexes
*
* @var array
*/
private $config = array(
'hostname' => '',
'username' => '',
'password' => ''
);
/**
* The Resource ID of the current connection
*
* @var resource
*/
private $connection;
/**
* The constructor method is private which prevents from direct initialization of an instance
*
* @param array $config
*/
private function __construct($config) {
$this->config = $config;
}
/**
* The getInstance() method used for setting an instance of MySQL class
*
* It checks whether MySQL::$instances array is empty or has any previously set instances in it.
* If no instance was set previously, it initiates new instance and pushes it to MySQL::$instances
* array. Otherwise, it checks if the connection parameters of the instance being initiated match
* the connection parameters of some other instance in MySQL::$instances array. If this is the case
* it returns that instance without initiating the new one with the same connection parameters.
* If not, it initiates new instance and pushes it to the MySQL::$instances array.
*
* @param array $config
* @return MySQL instance
*/
public static function getInstance($config) {
# if there was no instance set previously, initiate the new one and push it to the array
if (empty(self::$instances)) {
$newInstance = new MySQL($config);
self::$instances[] = $newInstance;
return $newInstance;
# otherwise check for a match
} else {
foreach (self::$instances as $instance) {
if ($instance->config == $config) {
return $instance;
# if no match found initiate the new one and push it to the array
} else {
$newInstance = new MySQL($config);
self::$instances[] = $newInstance;
return $newInstance;
}
}
}
}
/**
* The open() method creates a connection to Database
*
* @return resource $this->connection ID
*/
public function open() {
$this->connection = mysql_connect(
$this->config['hostname'],
$this->config['username'],
$this->config['password']
);
if (!$this->connection) {
throw new MySQLException( mysql_error(),
'An error occurred while connecting to Database'
);
}
mysql_query("SET NAMES 'cp1251'");
return $this->connection;
}
/**
* The opened() method checks if the connection was properly created
*
* @return boolean
*/
public function opened() {
if (is_resource($this->connection)) {
return TRUE;
} else {
return FALSE;
}
}
public function getMySQLInstances() {
print_r(self::$instances);
}
/**
* The close() method closes connection of the current instance
* Nullifies the connection ID and unsets the instance from MySQL::$instances array
*/
public function close() {
mysql_close($this->connection);
$this->connection = NULL;
foreach (self::$instances as $index => $instance) {
if ($instance->config == $this->config) {
unset(self::$instances[$index]);
}
}
}
}
?>
|
Проверить в действии можно так:
<?php
$connection = MySQL::getInstance(array(
'hostname' => 'localhost',
'username' => 'root',
'password' => ''
));
$connection->open();
if ($connection->opened()) {
echo '<pre>';
$connection->getMySQLInstances();
echo '</pre>';
}
$connection->close();
echo '<pre>';
$connection->getMySQLInstances();
echo '</pre>';
$connection2 = MySQL::getInstance(array(
'hostname' => 'localhost',
'username' => 'root',
'password' => ''
));
$connection2->open();
if ($connection2->opened()) {
echo '<pre>';
$connection2->getMySQLInstances();
echo '</pre>';
}
$connection3 = MySQL::getInstance(array(
'hostname' => '127.0.0.1',
'username' => 'root',
'password' => ''
));
$connection3->open();
if ($connection3->opened()) {
echo '<pre>';
$connection3->getMySQLInstances();
echo '</pre>';
}
?>
|
| |
|
|
|
|
|
|
|
для: newProgrammer
(29.03.2009 в 22:05)
| | Сделал сам? :-) Вот эти строчки заставляют усомниться, или ты всегда пишешь комменты к своих скриптах на английском? :-))
The getInstance() method used for setting an instance of MySQL class
*
* It checks whether MySQL::$instances array is empty or has any previously set instances in it.
* If no instance was set previously, it initiates new instance and pushes it to MySQL::$instances
* array. Otherwise, it checks if the connection parameters of the instance being initiated match
* the connection parameters of some other instance in MySQL::$instances array. If this is the case
* it returns that instance without initiating the new one with the same connection parameters.
* If not, it initiates new instance and pushes it to the MySQL::$instances array.
*
|
| |
|
|
|
|
|
|
|
для: Mefisto84
(30.03.2009 в 04:33)
| | Ну да сам... просто на английском писать комменты для меня удобнее! На русском пишу только для форумов и то если их мало, а для себя только на английском. В данном случае, писал как обычно для себя, получилось много, а переводить было как-то влом. Надеюсь это не будет препятствием для того, чтобы мне помогли.
PS Только, пожалуйста, давайте по теме, для меня PHP важнее, чем английский :))
PPS Если что переведу... :) | |
|
|
|
|
|
|
|
для: newProgrammer
(29.03.2009 в 22:05)
| | Шаблон синглетон изучаем?
Несколько соединений с разными базами в рамках одного скрипта - крайне редко встречающаяся задача. Так что данный класс больше эксперимент ради эксперимента.
Такие правильные, вроде, но ненужные классы очень скучно разбирать.
Попробуйте писать вещи, которые сами будете на 100% использовать. Тогда и обсуждение и разбор будут гораздо информативнее и полезнее. | |
|
|
|
|
|
|
|
для: Axxil
(30.03.2009 в 15:48)
| | Спасибо, Axxil.
Это я и хотел узнать. Значит несколько соединений в рамках одного скрипта используются редко. Теперь я понимаю, что в ближайшее время мне-то уж точно такой класс не пригодится.
Singleton и другие паттерны изучаю. По OOP есть несколько классных книжек. Читаю, пишу, но большая часть, действительно, получается эксперимент ради эксперимента.
Теперь прежде чем писать буду спрашивать, чтобы не создавать бесполезные классы. | |
|
|
|
|
|
|
|
для: Axxil
(30.03.2009 в 15:48)
| | В проеутах своих почти постоянно работаю одновременно с четырьмя базами - это не странно | |
|
|
|
|
|
|
|
для: mihdan
(11.12.2009 в 18:04)
| | Это сверхпрофессионализм — работать сразу с 4-мя БД. Вероятно, проект больно хорошо устроен. лол) | |
|
|
|
|
|
|
|
для: Fractured#
(11.12.2009 в 18:17)
| | Зря смеётесь, таблицы сайтов хранятся на одном сервере, католог, подключаемый к ним для раскрутки - на другом сервере. Слепить воедино нельзя очень по многим причинам. Одна из них - дисковое пространство под каталог - миллионы организаций и столько же мегобайт, занимаемых ими. | |
|
|
|
|
|
|
|
для: Fractured#
(11.12.2009 в 18:17)
| | Банальный пример: браузерные игры с чатом.
Чат почти всегда будет находится в отдельнйо базе (конечно я говорю про более-менее развитую игру, а не игру в которую играют одновремено всего 100 человек) | |
|
|
|
|
|
|
|
для: newProgrammer
(29.03.2009 в 22:05)
| | Всё так чистенько, аккуратненько, бесполезненько, и вдруг, как обухом по башке
mysql_query("SET NAMES 'cp1251'");
|
Ы... | |
|
|
|
|
|
|
|
для: Trianon
(12.12.2009 в 13:48)
| | а что в этой строке не так? | |
|
|
|
|
|
|
|
для: slo_nik
(12.12.2009 в 15:16)
| | присутствие | |
|
|
|
|
|
|
|
для: slo_nik
(12.12.2009 в 15:16)
| | Откуда класс знает, какая у меня кодировка на сайте? | |
|
|
|
|
|
|
|
для: Trianon
(12.12.2009 в 15:31)
| | да, действительно...
получается, что в классе надо задавать кодировку? | |
|
|
|
|
|
|
|
для: Slo_Nik
(12.12.2009 в 15:40)
| | Мне всегда любопытно...
А для чего вообще столько индусского кода возни? Ведь это все решается тремя строчкми. Вот сейчас еще пару методов добавится - кодировку устанавливать... | |
|
|
|
|
|
|
|
для: Николай2357
(12.12.2009 в 15:59)
| | Обертка для MySQL-функций может быть полезна:
1. Для безболезненного перехода на другую базу данных
2. Для генерации исключений и логгирования ошибок. Ошибки SQL-запосов никак не фигурируют в среде PHP, поэтому их обработка всегда лежит на плечах программиста. Чтобы этот пласт автоматизировать по любому придется писать обертку или в виде собственного набора фукнций или в виде класса.
PS Вообще подход имеет право на существование и, как правило, оправдывает себя в дальнейшем, не смотря на то, что стандартные функции (известные всем программистам и легко сопровождаемые) заменяются на нестандартные. | |
|
|
|
|
|
|
|
для: cheops
(12.12.2009 в 16:18)
| | Обертка для MySQL-функций может быть полезна:
Я знаю для чего делается обертка для mysql_query() . Для диагностики ошибок очень удобно.
Я интересуюсь другим, а именно организацией соединения
Безболезненный переход на другую бд - аргумент притянутый за уши. Потому что
1. Это происходит крайне редко.
2. Это решается проще и эфективнее - сменой файла коннекта.
3. А вот то, что сей код будет неоправданно тормозить и кушать ресурс - очевидно.
Это похоже на то, что на ночь рядом ставить два стакана. Пустой и полный. Полный - вдруг захочется пить. А пустой - вдруг не захочется. | |
|
|
|
|
|
|
|
для: Николай2357
(12.12.2009 в 16:58)
| | На этот случай лучше ставить стакан и горшок. | |
|
|
|
|
|
|
|
для: Николай2357
(12.12.2009 в 16:58)
| | Я тут давеча познакомился с альтернативным интерпретатором PHP — quercus. Ох и мощная штука. Со встроенной поддержкой юникода. Впечатлился настолько, что решил подогнать под него текущий, разрабаываемый мной, проект (на ZF, кстати говоря) и выложить на google app engine. Готовлю статью на эту тему. | |
|
|
|
|
|
|
|
для: Slo_Nik
(12.12.2009 в 15:40)
| | >да, действительно...
>получается, что в классе надо задавать кодировку?
Хорошо бы предусмотреть такую необязательную возможность. Возможно, вы потом сами перейдете на UTF-8 и класс должен предоставлять такую возможность. Хорошо также если бы он по умолчанию использовал cp1251 с которой вы вероятно хотите иметь дело большую часть времени. | |
|
|
|
|
|
|
|
для: cheops
(12.12.2009 в 16:20)
| | Вероятно, хотеть иметь дело большую часть времени следует именно с utf-8. Нет?
Я понимаю, что личные желания - дело тонкое... но надо же что-то делать, Аркадий! работать над собой! | |
|
|
|
|
|
|
|
для: Trianon
(12.12.2009 в 16:29)
| | Личные желания обычно выходят на первый план, когда работа ведется в одиночку или над небольшим количеством проектов. В противном случае помимо личных желаний могут быть объективные трудности с поддержкой старой кодировки (получаемая выгода может не окупить расходы на такой переход). Не везде и не всегда все зависит от личных желаний, а работа над собой не означает работа над инфраструктурой. Влияй работа над собой на инфраструктуру, мы бы за счет нашего ВВП, давно бы ВВП других стран обогнали :))) | |
|
|
|
|
|
|
|
для: cheops
(12.12.2009 в 16:40)
| | Я ж не говорю, что надо взять и переломать все старое на новое.
Я лишь о том, что хотеть следует в хорошем, годном направлении. | |
|
|
|
|
|
|
|
для: Trianon
(12.12.2009 в 16:44)
| | Скорее всего повсеместный переход на UTF-8 продлится ещё несколько лет...
Достоинства UTF-8 можно перечислять очень долго, это и безболезненный многоязыковой сайт и беззаморочный AJAX. Однако имеются и недостатки, которые подзатормаживают такой переход: чуть потяжелее однобайтовой кодировки, отстутствие поддержки на уровне ядра PHP (хотя в ядре строковые функции такие разношерстные, что и плевать) и отсуствие регистронезависимого сопоставления в MySQL. | |
|
|
|
|
|
|
|
для: cheops
(12.12.2009 в 16:50)
| | >отсуствие регистронезависимого сопоставления в MySQL.
Точно отсутствует? | |
|
|
|
|
|
|
|
для: Trianon
(12.12.2009 в 16:55)
| | Собственно глубоко не копал, но пошарив вокруг, что-то не нащупал готового решения (вот так чтобы был готовый _ci без гвоздей). Если у вас есть готовое решение или направление, куда копать поделитесь, плиз? | |
|
|
|
|
|
|
|
для: cheops
(12.12.2009 в 23:35)
| | Я тоже копал а) давно и б) неглубоко.
Но вроде как, из того что помню, наличие/отсутствие подходящих сопоставлений UTF-8 определяется полнотой установки сервера SQL (вроде соответствующие xml-файлы описывают сопоставления)
Так что и _cs и _ci достижимы.
Более точно http://dev.mysql.com/doc/refman/5.0/en/adding-collation-unicode-uca.html | |
|
|
|
|
|
|
|
для: Trianon
(13.12.2009 в 00:00)
| | Хм... любопытно с 5.0.45 даже без перекомпиляции добавить можно... только я так понимаю по ссылке предлагается кодировку для своих нужд самому создать (т.е. скажем русский вариант utf8_russian_ci)... Это бы ещё и хостера уговорить создать такую кодировку. Хм... однако для своих серверов и для одного-двух языков - это пожалуй выход. | |
|
|
|
|
|
|
|
для: cheops
(13.12.2009 в 12:15)
| | B при этом гуглояндекс-поиск по utf8_general_ci выдает изрядное количество результатов, говорящих о том, что какие-то (хуже ли лучше ли) таблицы сопоставлений таки на сервере есть. :) | |
|
|
|
|
|
|
|
для: cheops
(12.12.2009 в 16:20)
| | да вот уже припёрло перейти на utf-8, как раз из - за попытки внедрить ajax :):):):) | |
|
|
|
|
|
|
|
для: Slo_Nik
(12.12.2009 в 16:58)
| | Переходить лучше раньше, чем позже, особенно, если коммерческим кодом обрасти не успели :))) | |
|
|
|
|
|
|
|
для: cheops
(12.12.2009 в 23:36)
| | >коммерческим кодом обрасти не успели
что Вы имели ввиду? | |
|
|
|
|
|
|
|
для: Slo_Nik
(13.12.2009 в 07:34)
| | Если у вас нет на сопровождении множество сайтов и систем, заточенных именно под cp1251, вывод из эксплуатации которых либо заставил бы вас отказаться от сопровождения сайта или потребовал бы от вас сразу огромного объема кодирования в сжатые сроки.
PS Т.е. если у вас много сайтов, построенных по единой схеме и использующие одинаковые блоки. | |
|
|
|
|
|
|
|
для: cheops
(13.12.2009 в 12:11)
| | спасибо за разъяснения. | |
|
|
|