Подтвердить что ты не робот

Мобильная версия CakePHP

Я разработал полный веб-сайт с картой CakePHP, и мы хотели бы сделать очень легкую версию веб-сайта для мобильных устройств (в основном iPhone/iPad).

Есть ли способ использовать существующий веб-сайт с новым поддоменом (например, mobile.mywebsite.com), который будет отображать конкретные представления? Я бы хотел избежать копирования и упрощения текущего, чтобы соответствовать новым требованиям. Я не хочу "перерабатывать" новый веб-сайт CakePHP и делать изменения дважды каждый раз, когда мне нужно изменить действие контроллера.

4b9b3361

Ответ 1

Я сделал это, используя быстрое дополнение к beforeFilter() в моем файле app_controller.php.

function beforeFilter() {
     if ($this->RequestHandler->isMobile()) {
        $this->is_mobile = true;
        $this->set('is_mobile', true );
        $this->autoRender = false;
     }
}

Это использует CakePHP RequestHandler, чтобы определить, будет ли это мобильное устройство посещать мой сайт. Он задает свойство и переменную вида, чтобы позволить действиям просматривать настройки на основе нового макета. Также отключает autoRender, потому что мы позаботимся об этом в afterFilter.

В afterFilter() он ищет и использует файл мобильного просмотра, если таковой существует. Мобильные версии хранятся в "мобильной" папке внутри папки просмотра контроллера и называются точно такими же, как обычные немобильные версии. (т.е. add.ctp становится мобильным /add.ctp)

    function afterFilter() {
        // if in mobile mode, check for a valid view and use it
        if (isset($this->is_mobile) && $this->is_mobile) {
            $view_file = new File( VIEWS . $this->name . DS . 'mobile/' . $this->action . '.ctp' );
            $this->render($this->action, 'mobile', ($view_file->exists()?'mobile/':'').$this->action);
        }
     }

Ответ 2

Ответ Дэн работал у меня. Тем не менее, я использовал file_exists вместо конструктора файлов и добавил возможность использовать мобильные макеты. Фильтр перед тем же был, но afterFilter выглядел так:

function afterFilter() {
    // if in mobile mode, check for a valid view and use it
    if (isset($this->is_mobile) && $this->is_mobile) {
        $view_file = file_exists( VIEWS . $this->name . DS . 'mobile/' . $this->action . '.ctp' );
        $layout_file = file_exists( LAYOUTS . 'mobile/' . $this->layout . '.ctp' );

        $this->render($this->action, ($layout_file?'mobile/':'').$this->layout, ($view_file?'mobile/':'').$this->action);
    }
 }

Ответ 3

Вы можете использовать функцию темы в CakePHP 2.x для мобильного макета.

Просто выполните:

if($this->RequestHandler->isMobile())
    $this->theme = 'mobile';

Я нашел это лучше, так как вы можете легко просматривать файл на мобильном и рабочем столе.

Ответ 4

Я изменил эту технику для приложения CakePHP 2.1. Вот мой beforeFilter():

public function beforeFilter() {

if ($this->request->isMobile()){
    $this->is_mobile = true;
        $this->set('is_mobile', true );
        $this->autoRender = false;
}

}

И вот мой afterFilter():

function afterFilter() {
    // if in mobile mode, check for a valid view and use it
    if (isset($this->is_mobile) && $this->is_mobile) {
        $view_file = file_exists( 'Views' . $this->name . DS . 'mobile/' . $this->action . '.ctp' );
        $layout_file = file_exists( 'Layouts' . 'mobile/' . $this->layout . '.ctp' );
        if($view_file || $layout_file){
            $this->render($this->action, ($layout_file?'mobile/':'').$this->layout, ($view_file?'mobile/':'').$this->action);
        }
    }
 }

Это помогает учитывать устаревшие формулировки и константы в CakePHP 2.

Ответ 5

Простое решение - создать новый "мобильный" макет с соответствующими таблицами стилей и включить его в AppController:

public $components = array('RequestHandler');
public function beforeRender() {
    parent::beforeRender();
    if ($this->RequestHandler->isMobile()) {
        $this->layout = 'mobile';
    }
}

Это важно сделать в beforeRender(), если вы измените $this->layout в своих методах контроллеров.

Ответ 6

CakePHP v2.2.1 Решение (+ Cookies для сохранения мобильного/рабочего стола/другого макета)

Это решение основано на ответах @Dan Berlyoung, @deewilcox и @Chris K.

Части этих ответов не работали (для меня) в CakePHP 2.2.1.

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

/app/Controller/AppController.php

class AppController extends Controller {

  public $components = array('Cookie');
  public $is_mobile = false;
  public $layouts = array('desktop', 'mobile');

  // executed before every action in the controller
  function beforeFilter() 
  {
    // Using "rijndael" encryption because the default "cipher" type of encryption fails to decrypt when PHP has the Suhosin patch installed. 
    // See: http://cakephp.lighthouseapp.com/projects/42648/tickets/471-securitycipher-function-cannot-decrypt
    $this->Cookie->type('rijndael');

    // When using "rijndael" encryption the "key" value must be longer than 32 bytes.
    $this->Cookie->key = 'qSI242342432qs*&[email protected][email protected]*(XSL#$%)[email protected][email protected]#HKis~#^'; // When using rijndael encryption this value must be longer than 32 bytes.

    // Flag whether the layout is being "forced" i.e overwritten/controlled by the user (true or false)
    $forceLayout = $this->Cookie->read('Options.forceLayout');

    // Identify the layout the user wishes to "force" (mobile or desktop)
    $forcedLayout = $this->Cookie->read('Options.forcedLayout');

    // Check URL paramaters for ?forcedLayout=desktop or ?forcedLayout=mobile and persist this decision in a COOKIE
    if( isset($this->params->query['forcedLayout']) && in_array($this->params->query['forcedLayout'], $this->layouts) )
    {
        $forceLayout = true;
        $forcedLayout = $this->params->query['forcedLayout'];
        $this->Cookie->write('Options.forceLayout', $forceLayout);
        $this->Cookie->write('Options.forcedLayout', $forcedLayout);
    }

    // We use CakePHP built in "mobile" User-Agent detection (a pretty basic list of UA see: /lib/Cake/Network/CakeRequest.php)
    // Note: For more robust detection consider using "Mobile Detect" (https://github.com/serbanghita/Mobile-Detect) or WURL (http://wurfl.sourceforge.net/)
    if( ( $forceLayout && $forcedLayout == 'mobile' ) || ( !$forceLayout && $this->request->is('mobile') ) )  {
        $this->is_mobile = true;
        $this->autoRender = false; // take care of rendering in the afterFilter()
    }

    $this->set('is_mobile', $this->is_mobile);
  }

  // executed after all controller logic, including the view render.
  function afterFilter() {

    // if in mobile mode, check for a vaild layout and/or view and use it
    if( $this->is_mobile ) {
        $has_mobile_view_file = file_exists( ROOT . DS . APP_DIR . DS . 'View' . DS . $this->name . DS . 'mobile' . DS . $this->action . '.ctp' );
        $has_mobile_layout_file = file_exists( ROOT . DS . APP_DIR . DS . 'View' . DS . 'Layouts' . DS . 'mobile' . DS . $this->layout . '.ctp' );

        $view_file = ( $has_mobile_view_file ? 'mobile' . DS : '' ) . $this->action;
        $layout_file = ( $has_mobile_layout_file ? 'mobile' . DS : '' ) . $this->layout;

        $this->render( $view_file, $layout_file );
    }
  }
}

/app/View/Elements/default_footer.ctp

<ul>
    <?php
        $paramsQuery = $this->params->query;
        if(!is_array($paramsQuery))
        {
            $paramsQuery = array();
        }
        $paramsQuery['url'] = ( isset($paramsQuery['url']) ) ? $paramsQuery['url'] : '';
        $url = $paramsQuery['url'];
        unset($paramsQuery['url']);
        $params = $paramsQuery;

        $mobile_url = '/' . $url . '?' . http_build_query( array_merge( $params, array( 'forcedLayout' => 'mobile' ) ) );
        $desktop_url = '/' . $url . '?' . http_build_query( array_merge( $params, array( 'forcedLayout' => 'desktop' ) ) );
    ?>

    <?php if($is_mobile): ?>
        <li><?= $this->Html->link('Desktop Site', $desktop_url, array('target' => '', 'class' => '')) ?></li>
    <?php else: ?>
        <li><?= $this->Html->link('Mobile Site', $mobile_url, array('target' => '', 'class' => '')) ?></li>
    <?php endif; ?>
</ul>

/app/View/Layouts/default.ctp

<h1>Desktop Site Layout</h1>
<?= $this->fetch('content') ?>

/app/View/Layouts/mobile/default.ctp

<h1>Mobile Site Layout</h1>
<?= $this->fetch('content') ?>

/app/View/Pages/home.ctp

<h2>Home - on Desktop</h2>
<?= $this->element('default_footer') ?>

/app/View/Pages/mobile/home.ctp

<h2>Home - on Mobile</h2>
<?= $this->element('default_footer') ?>

Использование

Используйте ссылки default_footer для изменения макета - или эти прямые URL-адреса
http://example.com/pages/home?forcedLayout=desktop
http://example.com/pages/home?forcedLayout=mobile

Сессия COOKIE сохраняет выбранный вами вариант... например. попробуйте установить на "мобильный", а затем наведите URL-адрес без параметра forcedLayout=.
http://example.com/pages/home

Связи default_footer сохраняют существующие параметры (кроме "фрагмента" #gohere)
http://example.com/pages/home/a/b/c:d?this=that&foo=bar#gohere

Сайт для рабочего сайта:
http://example.com/pages/home/a/b/c:d?this=that&foo=bar&forcedLayout=desktop

Для более надежного распознавания User-Agent, рассмотрите возможность использования Mobile Detect PHP Library... вы могли бы нацелиться на планшеты и даже конкретные разрабатывать версии ОС... О, какая забава! ^ _ ^

Ответ 7

Решение, с которым я пошел, было легкой модификацией, основанной на нескольких ответах здесь, для CakePHP 2.5.5. Обработка выполняется в beforeRender (обратите внимание, что beforeRender запускается только на действия контроллера, которые фактически отображают страницу, так что это экономит накладные расходы, а не beforeFilter/afterFilter для частных методов):

$mobile = $this->request->is('mobile');
$this->set('mobile',$mobile);
//Check if an alternate mobile view and/or layout exists for this request.
if($mobile){
    if(file_exists(APP.'View'.DS.$this->name.DS.'mobile'.DS.$this->view.'.ctp')){
        //Render this action on its mobile view.
        $this->view = 'mobile'.DS.$this->view;
    }
    if(file_exists(APP.'View'.DS.'Layouts'.DS.'mobile'.DS.$this->layout.'.ctp' )){
        //Render this action on its mobile layout.
        $this->layout = 'mobile'.DS.$this->layout;
    }
}

Переменная $mobile может использоваться на любом представлении, если у вас есть небольшие настройки, иначе вы можете поменять любое представление с помощью View/{controller}/mobile/same_file_name.ctp или макета с помощью View/Layouts/mobile/same_file_name.ctp, чтобы иметь отдельную структуру страницы.

Обратите внимание, что это использует формат $this- > view и $this- > , а затем изменяет их, вместо использования $this- > action и $this- > render (view, layout), потому что ваше представление не всегда (например, перерыв с помощью $this- > action), и это решение предотвращает необходимость беспокоиться о том, когда $this- > render() будет принудительно, и позволит ему произойти естественным образом.

Ответ 8

Да, вы можете использовать весь свой домен и контроллеры, посмотрите Tera-WURLF

И даже лучше, вам не нужен субдомен для мобильной версии.