【问题标题】:CakePHP Shell Error Plugin could not be found找不到 CakePHP Shell 错误插件
【发布时间】:2016-08-15 06:09:18
【问题描述】:

我在 /app/Console/Command 中编写了一个名为 SyncVeevaShell.php 的 Shell 文件(基本上是一些控制器功能的复制/粘贴),它应该每 10 分钟通过 cronjob 运行一次,但它不起作用。当我尝试通过命令“sh cake SyncVeevaShell.php”手动运行 shell 时,我收到一条错误消息,提示找不到插件 SyncVeevaShell。我不明白为什么它会提到一个插件,因为我没有尝试使用一个。

SyncVeevaShell.php:

<?php

App::uses('AppShell', 'Console/Command');

class SyncVeevaShell extends AppShell {
public $uses = array('Asset', 'VeevaVault');

public function main()
{
    $this->autoRender = false;
    App::import('Model', 'Segment');
    $Segment = new Segment();
    App::import('Vendor', 'phpVeeva', array('file' => 'veeva' . DS . 'veeva.php'));
    $veeva = new phpVeeva();
    $veevaList = $veeva->getDocList();

    $this->remove_veeva_asset($veevaList);

    $i = 0;
    while ($i < count($veevaList))
    {
        $obj = $veevaList[$i];
        $filename = $obj->{$veeva::LIST_VALUES}[8];
        $major_ver = $obj->{$veeva::LIST_VALUES}[6];
        $minor_ver = $obj->{$veeva::LIST_VALUES}[7];

        $result = $this->Asset->VeevaVault->find('count', array(
                                        'conditions' => array(
                                            'VeevaVault.title' => $filename,
                                        )
                                    ));                         
        if ($result == 0) {

            $id = $obj->{$veeva::LIST_VALUES}[0]; //get document ID
            $info = $veeva->getInfo($id);
            $ext = $veeva->extensions[$info['format__v']];
            $size = $info['size__v'];
            $mime = $info['format__v'];
            $image = 0;
            if (strpos($mime, 'image') !== false) {
                $image = 1;
            }
            $product = $info['product__v'][0];
            $brand = $Segment->getVeevaBrand($product);
            $message_description = $info['approved_content_description__c'];
            $message_title = $info['title__v'];
            $message_expire = $info['expiration_date__vs'] . ' 12:00:00';
            $message_status = $info['status__v'];
            $url = 'https://frx.veevavault.com/api/v7.0/objects/documents/' . $id . '/file';

            $this->create_veeva_asset($id, $filename, $ext, $size, $mime, $image, $brand, $message_description, $message_title, $message_expire, $message_status, $url, $major_ver, $minor_ver);
        }
        else {

            $result = $this->Asset->VeevaVault->find('count', array(
                                        'conditions' => array(
                                            'VeevaVault.title' => $filename,
                                            'VeevaVault.major_ver' => $major_ver,
                                            'VeevaVault.minor_ver' => $minor_ver
                                        )
                                    ));
            if ($result == 0) {

                $id = $obj->{$veeva::LIST_VALUES}[0];
                $info = $veeva->getInfo($id);
                $ext = $veeva->extensions[$info['format__v']];
                $size = $info['size__v'];
                $mime = $info['format__v'];
                $image = 0;
                if (strpos($mime, 'image') !== false) {
                    $image = 1;
                }
                $product = $info['product__v'][0];
                $brand = $Segment->getVeevaBrand($product);
                $message_description = $info['approved_content_description__c'];
                $message_title = $info['title__v'];
                $message_expire = $info['expiration_date__vs'] . ' 12:00:00';
                $message_status = $info['status__v'];
                $url = 'https://frx.veevavault.com/api/v7.0/objects/documents/' . $id . '/file';

                $this->update_veeva_asset($id, $filename, $ext, $size, $mime, $image, $brand, $message_description, $message_title, $message_expire, $message_status, $url, $major_ver, $minor_ver);
            }
        }
        $i++;
    }
}

public function remove_veeva_asset($remoteVeevaList)
{
    $this->autoRender = false;
    App::import('Vendor', 'phpVeeva', array('file' => 'veeva' . DS . 'veeva.php'));
    $veeva = new phpVeeva();

    if (!empty($remoteVeevaList)) {

        $db = ConnectionManager::getDataSource('default');
        $i = 0;
        while ($i < count($remoteVeevaList))
        {
            $obj = $remoteVeevaList[$i];
            $filename = $obj->{$veeva::LIST_VALUES}[8];
            $remoteVeevaFilenames[] = $filename;
            $i++;
        }

        $localVeevaList = array();
        $query = $this->Asset->VeevaVault->find('all');
        foreach($query as $veeva) {
            $localVeevaList[] = $veeva['VeevaVault'];
        }

        if (!empty($localVeevaList)) {
            foreach($localVeevaList as $localVeeva) {
                if (in_array($localVeeva['title'], $remoteVeevaFilenames) == false) {

                    $id = $localVeeva['id'];
                    $asset_id = $localVeeva['asset_id'];

                    $sql = "DELETE FROM veeva_vaults WHERE id LIKE '" . $id . "'";
                    $db->rawQuery($sql);

                    $sql = "DELETE FROM assets WHERE id LIKE '" . $asset_id . "'";
                    $db->rawQuery($sql);
                }
            }
        }
    }
}

public function create_veeva_asset($veeva_id, $filename, $ext, $size, $mime, $image, $brand, $message_description, $message_title, $message_expire, $message_status, $url, $major_ver, $minor_ver)
{
    $this->autoRender = false;

    $uuid = String::uuid();
    $db = ConnectionManager::getDataSource('default');

    $sql = "INSERT INTO assets (id, user_id, original_name, name, ext, size, mime_type, is_image, created, modified, is_veeva, message_title, message_description, brand, status, expire_date) VALUES ('" . $uuid . "', null, '" . mysql_real_escape_string($filename) . "', '" . $uuid . "', '" . mysql_real_escape_string($ext) . "', " . mysql_real_escape_string($size) . ", '" . mysql_real_escape_string($mime) . "', " . mysql_real_escape_string($image) . ", now(), now(), 1, '" . mysql_real_escape_string($message_title) . "', '" . mysql_real_escape_string($message_description) . "', '" . mysql_real_escape_string($brand) . "', '" . mysql_real_escape_string($message_status) . "', '" . mysql_real_escape_string($message_expire) . "')";
    $db->rawQuery($sql);

    $sql = "INSERT INTO veeva_vaults (id, asset_id, veeva_id, title, description, url, created, size, major_ver, minor_ver, ext) VALUES ('" . String::uuid() . "', '" . $uuid . "', '" . $veeva_id . "', '" . mysql_real_escape_string($filename) . "', '" . mysql_real_escape_string($message_description) . "', '" . $url . "', now(), " . mysql_real_escape_string($size) . ", '" . mysql_real_escape_string($major_ver) . "', '" . mysql_real_escape_string($minor_ver) . "', '" . mysql_real_escape_string($ext) . "')";
    $db->rawQuery($sql);
}

public function update_veeva_asset($id, $filename, $ext, $size, $mime, $image, $brand, $message_description, $message_title, $message_expire, $message_status, $url, $major_ver, $minor_ver)
{
    $this->autoRender = false;

    $db = ConnectionManager::getDataSource('default');

    $sql = "UPDATE assets SET ext = '," . mysql_real_escape_string($ext) . "', size = " . mysql_real_escape_string($size) . ", mime_type = '" . mysql_real_escape_string($mime) . "', modified = now(), messages_title = '" . mysql_real_escape_string($message_title) . "', message_description = '" . mysql_real_escape_string($message_description) . "', brand = '" . mysql_real_escape_string($brand) . "', status = '" . mysql_real_escape_string($message_status) . "' WHERE original_name = '" . mysql_real_escape_string($filename) . "'";
    $db->rawQuery($sql);

    $sql = "UPDATE veeva_vaults SET veeva_id = '" . $id . "', description = '" . mysql_real_escape_string($message_description) . "', url = '" . $url . "', size = " . mysql_real_escape_string($size) . ", major_ver = " . mysql_real_escape_string($major_ver) . ", minor_ver = " . mysql_real_escape_string($minor_ver) . ", ext = " . mysql_real_escape_string($ext) . " WHERE title = '" . mysql_real_escape_string($filename) . "'";
    $db->rawQuery($sql);
}
}
?>

定时任务:

*/10 * * * * cd /var/www/SalesGuru/content/app/Console/Command; /usr/bin/php -q SyncVeevaShell.php > /dev/null ;

错误信息:

Error: Plugin SyncVeevaShell could not be found.
#0 /var/www/SalesGuru/content/lib/Cake/Core/App.php(364): CakePlugin::path('SyncVeevaShell')
#1 /var/www/SalesGuru/content/lib/Cake/Core/App.php(225): App::pluginPath('SyncVeevaShell')
#2 /var/www/SalesGuru/content/lib/Cake/Core/App.php(542): App::path('Console/Command', 'SyncVeevaShell')
#3 [internal function]: App::load('PhpShell')
#4 [internal function]: spl_autoload_call('PhpShell')
#5 /var/www/SalesGuru/content/lib/Cake/Console/ShellDispatcher.php(241): class_exists('PhpShell')
#6 /var/www/SalesGuru/content/lib/Cake/Console/ShellDispatcher.php(191): ShellDispatcher->_getShell('SyncVeevaShell....')
#7 /var/www/SalesGuru/content/lib/Cake/Console/ShellDispatcher.php(69): ShellDispatcher->dispatch()
#8 /var/www/SalesGuru/content/app/Console/cake.php(33): ShellDispatcher::run(Array)
#9 {main}

我对 CakePHP 相当陌生,对 Shell 和 cronjobs 完全陌生。

【问题讨论】:

  • 你应该总是提到你正在使用的确切的 cakephp 版本。并使用 $this->loadModel() 代替那些手动创建模型。
  • 哇,该代码是 FUGLY 和 SQL 可注入的。您说代码是从控制器中获取的?恭喜,您的应用程序是可利用的。 90% 的代码也应该在模型中。阅读 CakePHP 书中关于 MVC 的章节并遵循最佳实践:胖模型,瘦控制器。这将允许您共享代码,而不是违反 DRY 并复制相同的代码。为什么你根本不使用 CakePHP 模型?最后,mysql_real_escape_string 在 5.5 中已弃用。
  • 您的 SyncVeevaShell 函数之外的其他要点应该在模型文件中 - 而不是直接在您的非模型类中。 +1,因为即使代码是......问题也很清楚=)(我认为有些人使用反对票来表达他们对您正在做的事情的不喜欢,而不是“这是一个难以理解/不好的问题) .
  • 是的,这个网站很糟糕,我从另一家公司继承了它并遵循他们的编码方法,因为我是 Cake 的新手。在已经完成大量开发之后,我意识到它有多糟糕。当/如果我有时间我会做一些代码重构。感谢您的建议。

标签: php cakephp cron


【解决方案1】:

有一个完全相同的用例in the book

在你的情况下:

*/10 * * * * cd /var/www/SalesGuru/content/app && Console/cake SyncVeeva > /dev/null

  • 导航到您的 APP 目录
  • 致电Console/cake [ShellName without suffix] [optional command name]

The official documentation 应该始终是您获取信息的第一站。然后谷歌,然后是这样的论坛。

请注意,您应该能够使用 -q (--quit) 参数而不是使用 &gt; /dev/null 来使 shell 静音。

【讨论】:

  • 谢谢。作为记录,我没有编写 cron 作业,它是另一个开发人员。但在我认为它是正确的之前,我应该用文档检查它。非常感谢。
【解决方案2】:

我的具体情况很简单,但我仍然设法花时间试图弄明白。

我在APP/Console/Command 下创建了一个脚本并试图从命令行运行它,但它一直给我找不到插件错误。

原来我忘了在文件名中包含 Shell 部分。例如,如果您的脚本名为ClearCache,则实际文件名应为ClearCacheShell.php

希望这可以节省其他人几分钟的时间,因为这篇文章是第一个出现在搜索结果中的帖子。

【讨论】:

    【解决方案3】:

    应该是sh cake SyncVeeva

    将脚本作为 shell 运行时不需要包含“Shell.php”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多