Статистика

Участников проекта 105
Опубликовано статей 78
Отчет по карме. Топ 20

Новости блога

1 29.11.2013  Сегодня самым активным участникам newblog'а был выплачен доход с sape.
7 02.11.2012  Ура! Свешилось, нашему сайту дали тИЦ 10. Спасибо всем кто принимает участие в развитии нашего блога.
8 21.08.2012  Интеграция с sape.ru. Теперь каждый автор статей на newblog автоматически зарабатывает на рекламе.
Все новости

Топ 5 категорий

Программирование 46
Операционные системы 9
Базы данных 4
Туризм 2
Заметки 2

Последние 5 заметок (90)

gullyar - Закладки gullyar
gullyar - Ваша первая закладка
osadchaya - Закладки osadchaya
Ira0231188 - Закладки Ira0231188
Ira0231188 - Закладки Ira0231188

Ссылки

www.freedev.asia

cloud cms php

21.08.2012 07:57 | Просмотров: 3339 | Доход: 45.37 руб. | Комментариев: 1
[Программирование] 
Рейтинг: 5/1

Появилась идея сделать cms в облаке. Скорее даже не cms, а набор универсальных модулей, которые работают в облаке и отрисовывают весь интерфейс на стороне клиента. Чем такой подход может быть интересен?

    - Разработчику не требуется php, java или любая другая технология, достаточно даже статического сайта!
    - При увеличении нагрузки, основная масса прийдется на облако и не потребует масштабируемости со стороны разработчика!
    - Так как cms будет предоставляться модульно, то все стили оформления могут быть с сайта разработчика, никаких шаблонов!
    - Полная настройка под ключ, при этом для установки модуля в сайт, достаточно всего 1 строчки кода.
    - Модули cms должны уметь взаимодействовать между собой.
 
Транспорт script ajax, кросдоменные запросы.

Изначально я думал взять за основу iframe, но очень быстро от него отказался, так как не получилось бы применять пользовательские стили оформления. Транспорт должен быть динамичным и не требовать перезагрузки страницы. Лушче всего на эту роль подходит ajax и позволяет строить интерактивные пользовательские интерфейсы с фоновым обменом браузера с веб сервером. Это то что нужно. Но увы XMLHttpRequest не позволяет делать кроссдоменные запросы, а от фреймов я уже отказался. Остается пойти по стопам google analytics и использовать script или img для транспорта. Остановил свой выбор на script. Он решает сразу 2 задачи, предоставляет транспорт и позволяет применять пользовательские стили.

Кодирую, бью на пакеты и собираю.

При создании тега script, браузер автоматически делает кросдоменный GET запрос к серверу указанному в src. Все бы ничего, да только GET имеет ограничение на передаваемые данные. Поэтому данные нужно разбивать, а потом собирать на сервере. Каждый пакет маркируется и когда на сервер приходит пакет с маркером "end", происходит сборка данных. На серверной стороне реализовано что-то наподобие пула, который генерирует нужный js в зависимости от запроса. Благодаря этому несложно заставить взаимодействовать модули между собой. urlencode не дает все что необходимо, хочется передавать в запросах любые символы, в том числе и "+". Поэтому простой Base64 не подходит. Его следует немного изменить, а именно заменить символы "+" и "=" на символы "_" и "-".

Реализация со стороны разработчика.

Со стороны разработчика все просто, ему достаточно указать:

<script id="inew" src="http://newblog.kz/lab/pool.php"></script>

 

И после этого он получает полноценный, динамичный модуль у себя на сайте. Например новости, чат, обратную связь и любой другой стандартный блок любой cms.

Реализация со стороны сервера.

На стороне сервера потребуется файл pool.php, который будет обрабатывать и распределять запросы между классами, в качестве примера пакеты буду писать в файл на стороне сервера(не есть хорошо), жду предложений как лучше(в базу в в таблицу memory?)..

<?php
$server="http://newblog.kz/lab/";  //Адрес скрипта на сервере
$len=900;                                         //Длина блока при передачи данных
$modules=array('news');

foreach($modules as $module)
    include("cloud/".$module.".php");

if(isset($_GET['data'])){
    //Прием пакетов и запись в файл
    if(!empty($_GET['uid'])){
        $fh = fopen("cache/".$_GET['uid'], "a+");
        flock($fh, 2);
        fwrite($fh, $_GET['data']);
        flock($fh, 3);
        fclose($fh);
    }
//Пришел последний пакет
  if(!empty($_GET['end'])){
      $content=file("cache/".$_GET['uid']);
      if(isset($content)){
          if(!empty($content)&&($content!=0)){
              $content=$content[0];
              $content=str_replace('-', '+', $content);
              $content=str_replace('_', '=', $content);
              $content=base64_decode($content);
             
              foreach($modules as $module){
                  $class=ucwords($module);
                  $class::pool($_GET['id'],$content);
              }
          }
      }
  }   
}else{

//Первоначальная загрузка
echo '
server="'.$server.'";
len='.$len.';
var head = document.getElementsByTagName("head").item(0);
var hscript = document.createElement("script");
hscript.setAttribute("src", server+"lib.js");
head.appendChild(hscript);

hscript.onload=function(){';
    foreach($modules as $module){
        $class=ucwords($module);
        $class::run();
    }
echo '}';
}
?>

Java script библиотека которая будет подгружаться в самом начале:

function celement(uid,id,end,dl,i,data){
    s = document.createElement("script");         
    s.src = server+"pool.php?id="+id+"&uid="+uid+"&end="+end+"&size="+dl+"&data="+data.substr(i,len);
    document.body.appendChild(s);
    if(end==0){
        s.onload=function(){
            i=i+len;
            if(i<(dl-len)){
                celement(uid,id,0,dl,i,data);
            }else{
                celement(uid,id,1,dl,i,data);
            }
        };
    }
    //document.body.removeChild(s);
}

function send(id,data){
    uid=(((1+Math.random())*0x10000)|0).toString(16).substring(1);
    //data=encodeURIComponent(data);
    data=Base64.encode(data);
    //alert(data);

    dl=data.length;
    if(dl>len){
        celement(uid,id,0,dl,0,data);
    }else{
        celement(uid,id,1,dl,0,data);
    }
  return s;
}

var Base64 = {
   _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/_",
    encode : function (input) {
      var output = "";
      var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
      var i = 0
      input = Base64._utf8_encode(input);
         while (i < input.length) {
       chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);
       enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;
       if( isNaN(chr2) ) {
           enc3 = enc4 = 64;
        }else if( isNaN(chr3) ){
          enc4 = 64;
        }
       output = output +
        this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
        this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
     }
      return output;
    },
    _utf8_encode : function (string) {
      string = string.replace(/\r\n/g,"\n");
      var utftext = "";
      for (var n = 0; n < string.length; n++) {
        var c = string.charCodeAt(n);
       if( c < 128 ){
          utftext += String.fromCharCode(c);
        }else if( (c > 127) && (c < 2048) ){
          utftext += String.fromCharCode((c >> 6) | 192);
          utftext += String.fromCharCode((c & 63) | 128);
        }else {
          utftext += String.fromCharCode((c >> 12) | 224);
          utftext += String.fromCharCode(((c >> 6) & 63) | 128);
          utftext += String.fromCharCode((c & 63) | 128);
        }
     }
      return utftext;
    }
 }

d = document.createElement("div");
d.id = "idata";
document.getElementById("inew").parentNode.insertBefore( d, document.getElementById("inew").nextSibling );

 

Готово, теперь мы можем подключить свой класс. Пусть это будет простое текстовое поле со ссылкой "click" по нажатию которой сообщение будет передаваться на сервер и браузер будет получать ответ без перезагрузки страницы:

<?php
class News{
    //Стартовый интерфейс
    public static function run() {
        echo '
        ibody = document.createElement("div");
        ibody.id = "ibody";
        document.getElementById("inew").parentNode.insertBefore(ibody,document.getElementById("inew"));
        content="<input id=\"input\"></input><a href=\"#\" onclick=\"send(\'idata\',document.getElementById(\'input\').value)\">click</a>";
        document.getElementById("ibody").innerHTML=content;
        ';
    }

    //Обработчик событий
    public static function pool($id,$data) {
        echo '
        function load(){
        document.getElementById("'.$id.'").innerHTML="send to server:'.$data.'";
        }
        load();';
    }
   
}
?>

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


© GM
| Комментировать статью |
  • пыщь +6 (25.08.2012 14:46)
    3 кусок, 15 строка, засирается тегами script если не раскомментировать, а в примере нет, почему?
    | Ответить |