Добавление Javascript для каждой страницы в CakePHP - PullRequest
12 голосов
/ 15 сентября 2009

В попытке сохранить свои скрипты удобнее, я собираюсь переместить каждый в свой собственный файл, упорядоченный по контроллеру и действию:

// scripts which only apply to /views/posts/add.ctp
/app/webroot/js/page/posts/add.js

// scripts which only apply to /view/users/index.ctp
/app/webroot/js/page/users/index.js

Это все круто, однако я бы хотел, чтобы они автоматически добавлялись контроллером, поскольку он, очевидно, знает имя и контроллера, и действия.

Я думаю, что лучшее место для этого - AppController::beforeRender(). (Да?)

Единственная проблема в том, что я не знаю, как на самом деле добавить это в переменную $scripts_for_layout. Я думал, что получение ссылки на вспомогательный объект javascript будет работать, но я не могу найти его из контроллера!

class AppController extends Controller {
    var $helpers = array("javascript", "html", "form");

    function beforeRender() {
        // ???
    }
}

Ответы [ 9 ]

28 голосов
/ 15 сентября 2009

Очень просто сделать в вашем default.ctp файле макета:

Пример для автоматического включения .css файлов на контроллер и / или контроллер / действие (поскольку у меня это было, легко адаптируется к .js файлам):

<head>
...
<?php
    if (is_file(WWW_ROOT . 'css' . DS . $this->params['controller'] . '.css')) {
        echo $html->css($this->params['controller']);
    }
    if (is_file(WWW_ROOT . 'css' . DS . $this->params['controller'] . DS . $this->params['action'] . '.css')) {
        echo $html->css($this->params['controller'] . '/' . $this->params['action']);
    }
?>
...
</head>
15 голосов
/ 15 сентября 2009

Как говорит deceze, мы делаем это с использованием макета, хотя я считаю, что наше решение немного более элегантно:)

По умолчанию .ctp:

if(isset($cssIncludes)){
    foreach($cssIncludes as $css){
        echo $html->css($css);
    }
}

if(isset($jsIncludes)){
    foreach($jsIncludes as $js){
        echo $javascript->link($js);
    }
}

Затем в наших действиях контроллера мы определяем эти массивы:

$this->set('cssIncludes',array('special')); // this will link to /css/special.css
$this->set('jsIncludes',array('jquery'));   // this will link to /js/jquery.js

Для файлов, которые необходимо загрузить в каждом представлении, мы просто добавляем ссылку «статически» в верхнюю часть макета, например:

echo $javascript->link('global');
echo $html->css('global');

Это действительно хорошо работает для нас. Удачи!

2 голосов
/ 30 апреля 2013

Мне просто нужно было сделать включение для конкретной страницы, но я нашел более удобный способ сделать это в документации Вы можете просто загрузить его в некоторый блок скрипта в вашем файле default.ctp. И в соответствующем представлении просто используйте HTML-помощник, чтобы протолкнуть скрипт:

Вы можете добавить тег сценария к определенному блоку, используя блок Опция:

echo $this->Html->script('wysiwyg', array('block' => 'scriptBottom'));

Который добавляет <script type="text/javascript" href="/js/wysiwyg.js"></script> к блоку.

В вашем макете вы можете вывести все теги скрипта, добавленные в «ScriptBottom»:

echo $this->fetch('scriptBottom');
2 голосов
/ 08 июня 2012

Вроде новичок в этом, но после прочтения этого добавил в мой макет следующее:

if ($handle = opendir(WWW_ROOT . 'js' . DS . $this->params['controller'] . DS . $this->params['action'])) 
{
    while (false !== ($entry = readdir($handle)))
        {
           $entry = str_replace(".js", "", $entry);
           echo $this->Html->script($entry);

    }
    closedir($handle);
}
1 голос
/ 15 сентября 2009

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

class myController extends AppController {
  var view = 'AppView';
  ...
}

Затем где-нибудь в вашем AppView вы захотите сделать что-то вроде:

function __construct(&$controller, $register){
  parent::__construct($controller,$register);
  $this->addScript('<script type="text/javascript" src="/path/to/js/' . $this->controller . '/' . $this->action . '.js"></script>');
}

Но я бы сделал шаг назад и сначала подумал бы о нескольких вещах.

Насколько велики ваши сценарии в среднем? Являются ли издержки вызова внешнего скрипта (до того, как скрипт кэшируется клиентом) лучше, чем добавление нескольких сотен байтов в ваш основной поток вывода (просто вставив скрипт на страницу, встроенный)?

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

Еще один способ решения этой проблемы - сделать все это в javascript. Просто разберись с ленивой схемой загрузки. Таким образом, ваше приложение просто загружает очень маленький файл loader.js, и этот скрипт выясняет, какие другие источники javascript нужно извлечь.

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

0 голосов
/ 25 июля 2016

С Cake v3 вы можете сделать это следующим образом. Добавьте нужные скрипты в конкретный контроллер.

//YourController.php
public function beforeRender (Event $event)
{
    array_push($this->scripts, 'Admin/gallery');
    parent::beforeRender($event);
}

Установить значение по умолчанию в intialize и сделать один раз //AppController.php публичная функция initialize () { Родитель :: Initialize ();

    $this->scripts = [];
}

public function beforeRender (Event $event)
{
    /* Define scripts in beforeRender of Child */
    $this->set('scripts', $this->scripts);
    /*-----------------------------------------*/
}

Теперь вы можете запустить эту функцию один раз.

<?= $this->Html->script($scripts) ?>
0 голосов
/ 30 августа 2013

LI работал немного (очень мало) над фрагментом W1ckd и облегчал разделение одного и того же js для различных действий:

if ( is_dir(WWW_ROOT . 'js' . DS . $this->params['controller'] ) && ( $handle = opendir( WWW_ROOT . 'js' . DS . $this->params['controller'] ) ) )
{
    while ( false !== ( $entry = readdir( $handle ) ) )
    {
        if ( in_array( $this->params['action'], explode( '.', $entry ) ) ) {
            $entry = str_replace( ".js", "", $entry );
            echo $this->Html->script( $this->params['controller'].DS.$entry );
        }

    }
    closedir( $handle );
}

Таким образом, вы можете получить что-то вроде:

Webroot / JS / Контроллер / view.edit.add.js

И этот js будет включен в эти три действия (просмотр, редактирование, добавление).

0 голосов
/ 24 августа 2013

Я создал плагин для этой проблемы.

Если у вас есть два файла:

  • / приложение / View / Post / add.ctp
  • / приложение / View / Post / add.js

будет включать add.js в блок скрипта страницы.

OR

  • Приложение / View / Post / add.js
  • приложение / Webroot / JS / пост / add.js

будет включать /js/post/add.js в блок скриптов страницы.

Там есть несколько симпатичных функций, и это просто, как бобы. Вы даже можете использовать PHP внутри своих файлов .js и использовать viewVars, которые вы установили в действии. Более того, вам не нужно взламывать файлы вида или макета, чтобы он работал, просто извлеките блок «скрипт» в макете. Вы также можете просто записать .js в другой блок просмотра.

Вы можете проверить это здесь: https://github.com/dizyart/cakephp-viewautoload

Это на ранних стадиях, поэтому обязательно комментируйте и список желаний!

0 голосов
/ 02 января 2013

Существует сообщение о блоге CakePHP на Соглашение о конфигурации - в чем дело? - в котором используется помощник для указания файлов Javascript:

<?php

class JsManagerHelper extends AppHelper {

    var $helpers = array('Javascript');

    //where's our jQuery path relevant to CakePHP's JS dir?
    var $_jqueryPath = 'jquery';

    //where do we keep our page/view relevant scripts?
    var $_pageScriptPath = 'page_specific';

    function myJs() {
    return $this->Javascript->link($this->_jqueryPath . '/' .
                                    $this->_pageScriptPath .'/' .
                                    $this->params['controller'] . '_' .
                                    $this->params['action'], false);
    }

}

?>

И тогда у вас просто есть $jsManager->myJs(); в вашем представлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...