2009-09-15 96 views
12

每个视图在试图让我的脚本维护,我要每个进入自己的文件,由控制器和行动组织:添加特定页面,Javascript来CakePHP中

// 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() { 
     // ??? 
    } 
} 

回答

1

我能想到的最好的办法是创建自己的custom 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源需要进入。

注意:我从来没有测试过我的扩展视图破解,但我敢打赌它会如果你真的想要这样做,你就可以工作。

28

很容易在你的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> 
+3

+1为清洁的方法和理解。 'APP.WEBROOT_DIR.DS'可以用'WWW_ROOT'常量代替。 – deizel 2009-09-15 10:10:46

+0

好的一点,在更改目录结构时也应该更少出错。改变了它。 :) – deceze 2009-09-15 11:00:55

+1

欺骗......认真......你就像是唯一的蛋糕大师,我发誓。在过去的三周里,我自己一定给你喜欢400代表。 :) – nickf 2009-09-15 12:47:29

15

像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'); 

这对我们非常有用。祝你好运!

+0

感谢你们,我正在寻找一种方法来在控制器中定义脚本。虽然我不会在.ctp中调用php代码。必须有一个更清洁的方式。 – dewwwald 2016-07-25 15:01:48

2

还挺新到这一点,但是看完这个添加以下到我的布局:

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); 
} 
+0

解释一下这段代码的作用。 – cereallarceny 2012-10-21 05:13:12

+0

非常好的片段!唯一不好的是,你不能在两个不同的控制器/操作中使用相同的js ... – 2013-08-29 13:54:13

0

有CakePHP的博客帖子的螺母和螺栓上Convention over Configuration – what's the big deal? - 它使用一个帮手指定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();

2

我只是做了页面特定的包含,但我找到了一个更好的方法来做到这一点在documentation。您可以将其加载到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'); 
0

我已经创作了插件这个确切的问题。

如果你有两个文件:

  • /app/View/Post/add.ctp
  • /app/View/Post/add.js

它将包含add.js进入页面的脚本块。

OR

  • 应用程序/查看/发表/ add.js
  • 应用程序/ Web根目录/ JS /后/ add.js

它将包括/ JS /将/ post/add.js添加到页面的脚本块中。

有几个可爱的功能在那里,它很简单,就像豆子。您甚至可以在您的.js文件中使用PHP,并使用您在该操作中设置的viewVars。最重要的是,您不需要破解视图或布局文件以使其工作,只需在布局中获取“脚本”块即可。您也可以简单地将.js写入另一个视图块。

您可以点击此处查看:https://github.com/dizyart/cakephp-viewautoload

这是在早期阶段,所以一定要发表评论和心愿!

0

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将被包括在这三个交流tions(查看,编辑,添加)。

0

有了Cake v3,你可以这样做。在特定控制器中添加所需的脚本。

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

坐落在intialize默认并呈现一次 //AppController.php 公共函数初始化(){ 父 初始化::();

$this->scripts = []; 
} 

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

现在你可以运行这个函数一次。

<?= $this->Html->script($scripts) ?>