草庐IT

php - 我正在开发一个 php 购物 list 函数/api

coder 2024-04-16 原文

返回一组购物 list 对象,或者是购物者的,或者是具有“建议的”标志='Y'的 list

当我手动将 token 添加到 $_GET 时,我返回一个空白数组。 [{},{}] 但是如果我 var_dump($shopper_list) 我得到两个不同的用户列表..它应该只有一个,因为一次登录应该等于一个 token :

[{},{}]
array(2) {
  [0]=>
  object(UserShoppingList)#4 (14) {
    ["sign_in_token":protected]=>
    NULL
    ["Shopper":protected]=>
    NULL
    ["ID":protected]=>
    string(1) "4"
    ["SHOPPING_LIST_NAME":protected]=>
    string(18) "kj's shopping list"
    ["SUGGESTION":protected]=>
    string(1) "N"
    ["SEQUENCE":protected]=>
    NULL
    ["ShoppingListItem":protected]=>
    NULL
    ["api_url":protected]=>
    NULL
    ["table":"Base":private]=>
    string(23) "jfw_shopping_list_names"
    ["procedure":"Base":private]=>
    NULL
    ["procedure_args":"Base":private]=>
    NULL
    ["keys":"Base":private]=>
    array(1) {
      ["ID"]=>
      NULL
    }
    ["alias_db_to_php":"Base":private]=>
    array(0) {
    }
    ["alias_php_to_db":"Base":private]=>
    array(0) {
    }
  }
  [1]=>
  object(UserShoppingList)#5 (14) {
    ["sign_in_token":protected]=>
    NULL
    ["Shopper":protected]=>
    NULL
    ["ID":protected]=>
    string(1) "2"
    ["SHOPPING_LIST_NAME":protected]=>
    string(20) "bonner shopping list"
    ["SUGGESTION":protected]=>
    string(1) "N"
    ["SEQUENCE":protected]=>
    NULL
    ["ShoppingListItem":protected]=>
    NULL
    ["api_url":protected]=>
    NULL
    ["table":"Base":private]=>
    string(23) "jfw_shopping_list_names"
    ["procedure":"Base":private]=>
    NULL
    ["procedure_args":"Base":private]=>
    NULL
    ["keys":"Base":private]=>
    array(1) {
      ["ID"]=>
      NULL
    }
    ["alias_db_to_php":"Base":private]=>
    array(0) {
    }
    ["alias_php_to_db":"Base":private]=>
    array(0) {
    }
  }
}

我的 php 页面 (get_shopping_lists.php) 如下所示:

/*
    This script is used to return a JSON array of ShoppingList objects.
    Those objects can be limited to either only "suggested" ShoppingList names,
    or to all of the lists for a single Shopper.  So, either the shopper_id or
    the boolean "suggested_only" should be set.
*/
if(!isset($_GET['token']) && !isset($_GET['suggested_only'])) {
    die('Must pass-in either a \'token\' or \'suggested_only\' flag');
}

if(isset($_GET['token'])) {
    $shopper = new Shopper($_GET['token'])
    or die('Could not instantiate a new Shopper from the \'token\' passed-in');

    $shopper_lists = $shopper->get_lists(true);
    echo json_encode($shopper_lists);
}

if(isset($_GET['suggested_only']) && $_GET['suggested_only'] == 'true') {

}

我希望返回一个购物列表对象数组,或者是一个购物者(您将 token 传递给 Shopper 类的“get_lists”函数),或者是具有“建议的列表”的列表” flag = 'Y' 如果您要传递另一个参数以表示您只需要建议的列表。这些选项中的每一个都会以不同的方式调用框架中的各个部分。

购物者类别:

// Most objects in this framework are populated by calling the constructor, but
// this one has a variety of entry points. They don't do any sanity checking
// with eachother, so you can have $user->create and $user->register refer to
// completely different rows.
class Shopper extends Base {

    protected $shopper_id;
    protected $email;
    protected $user_name;
    protected $temp_token;
    protected $sign_in_token;

    protected $UserShoppingList;

    function __construct($email = null) {
        // For testing use only. Declined to wrap in this_is_dev because I
        // foresee using it somewhere in the code, pushing live, and being 
//        parent::__construct('jfw_shoppers', array('SHOPPER_ID' => $shopper_id));

        // Allow them to pass an e-mail address or the token
        if (strpos($email, '@') === false) {
            $this->sign_in_token = $email;
        } else {
            $this->email = $email;
        }
    }

    // todo: need a new function to do the actual activation.
    public function activate($temp_token) {
        global $db;

        $this->set_temp_token($temp_token);

        $vars = array();
        $vars[] = array(':i_temp_token', $this->get_temp_token());

        // Returns a Y or N
        return $db->get_function_as_proc('custom.japi_shopper_identity.Activate_User(:i_temp_token)', $vars) == 'Y';
    }

    public function create($password) {
        global $db;

        if (!$this->get_email() || !$this->get_username()) {
            return false;
        }

        $vars = array();
        $vars[] = array(':email', $this->get_email());
        $vars[] = array(':username', $this->get_username());
        $vars[] = array(':password', $password);

        $id = $db->get_function_as_proc('custom.japi_shopper_identity.create_user(:email, :username,  :password)', $vars);
        $this->set_id($id);

        // If it failed, it'll puke on the procedure. If we've come this far, we
        // know it worked.
        return true;
    }

    public function get_email() {
        return $this->email;
    }

    private function get_id() {
        if (isset($this->shopper_id)) {
            return $this->shopper_id;

        // If this object has an e-mail address or the user sent one
        } else if ($this->get_email())  {
            global $db;

            $vars = array();
            $vars[] = array(':i_email_id', $this->get_email());

            // FUNCTION get_id_by_email(i_email_id IN jfw_shoppers.email%TYPE)
            $id = array_pop(array_pop($db->get_function('custom.japi_shopper_identity.get_id_by_email(:i_email_id)', $vars)));

            $this->set_id($id);
            $this->shopper_id = $id;
            return $this->shopper_id;

        // Can also get from token
        } else if ($this->get_sign_in_token())  {
            // todo: call get_id_by_token
            return false;
        }
    }


    // todo: test
    public function get_lists($clobber = false) {
        global $pd;
//        $pd->print_object($this, 'User - has token?');
//        $pd->print_object($this->get_sign_in_token(), 'Token');

        if ($this->UserShoppingList != null && !$clobber) {
            return $this->UserShoppingList;

        } else if ($this->get_sign_in_token()) {
            global $db;
            $pd->print_object($this, 'User - has token?');
            $pd->print_object(strtolower($this->get_sign_in_token()), 'token?');

            $vars = array();
            $vars[] = array(':i_sign_in_token', strtolower($this->get_sign_in_token()));

            $pd->print_object($this->get_sign_in_token(), 'About to seek lists using token');
            $rows = $db->get_function('custom.japi_shopper_identity.get_lists_for_shopper(:i_sign_in_token)', $vars);
            $pd->print_object($rows, 'Rows returned by get_lists using token '.$this->get_sign_in_token());

            // Turn the rows into objects
            $this->UserShoppingList = array_to_objects($rows, 'UserShoppingList');

            return $this->UserShoppingList;
        } else {
            return false;
        }
    }

    public function get_sign_in_token() {
        if ($this->sign_in_token != null) {
            return $this->sign_in_token;
        } else {
            return false;
        }
    }

    public function get_temp_token() {
        if ($this->temp_token != null) {
            return $this->temp_token;
        } else {
            return false;
        }
    }

    public function get_username() {
        return $this->user_name;
    }

    public function json($obj = null, $return_json = false) {
        if ($obj == null) {
            $obj = $this;
        }
        return parent::json($obj, $return_json);
    }

    // Most objects in this framework are populated by calling the constructor,
    // but the only way to populate this one is to call this function with good 
    // credentials.
    public function login($password) {
        global $db;

        if (!$this->get_email()) {
            return false;
        }

        // Log them in now that we know who they are. 
        $vars = array();
        $vars[] = array(':i_email_id', $this->get_email());
        $vars[] = array(':i_password', $password);

        // This also exists, but is not yet in use:
        // $token = $db->get_function_as_proc('custom.japi_shopper_identity.login_by_username(:i_username, :i_password)', $vars);
        $token = $db->get_function_as_proc('custom.japi_shopper_identity.Login_by_Email(:i_email_id, :i_password)', $vars);
        // todo: what if it's bad credentials?

        if ($token == null) {
            return false;

        } else {
            $this->set_sign_in_token($token);
            return $this->get_sign_in_token();
        }
    }

    public function password_reset($tmp_token, $password) {
        global $db;

        if (strlen($password) < 8) {
            return false;
        }

        $vars = array();
        $vars[] = array(':temp_token', $tmp_token);
        $vars[] = array(':new_password', $password);

        return $db->get_function_as_proc('custom.japi_shopper_identity.password_reset(:temp_token, :new_password)', $vars) == 'Y';
    }

    public function request_activation() {
        global $db;

        $vars = array();
        $vars[] = array(':i_shopper_id', $this->get_id());

        // Returns a temp token
        $temp_token = $db->get_function_as_proc('custom.japi_shopper_identity.activate_user_request(:i_shopper_id)', $vars);

        if ($temp_token == null) {
            return false;
        } else {
            $this->send_activation_email();
            return $temp_token;
        }
    }

    public function request_password_reset() {
        global $db, $pd;

        if (!$this->get_id()) {
            return false;
        }

        $vars = array();
        $vars[] = array(':shopper_id', $this->get_id());

        $temp_token = $db->get_function_as_proc('custom.japi_shopper_identity.password_reset_request(:shopper_id)', $vars);
        if ($temp_token == null) {
            return false;
        } else {
            $this->set_temp_token($temp_token);
            $pd->print_object('About to send the e-mail');
            $this->send_password_email();
            $pd->print_object('Sent the email');
            return $this->get_temp_token();
        }
    }


    private function send_activation_email() {
        if (!$this->get_email() || !$this->get_temp_token())  {
            return false;
        }


        $fancy = '
<div style="text-align: center;"><img src="logo.jpg" /></div>
<h2>Welcome to com!</h2>
<p>To complete your registration, <a href="todo: ">click here</a> or copy and paste the URL into your browser:</p>

URL?token='.$this->get_temp_token().'

Thanks!
';

        $plain = 'Welcome to com!

To complete your registration, please activate your account by going to the URL below:

URL?token='.$this->get_temp_token().'

Thanks!
';

        // todo: subject could probably be better
        return email_customer($this->get_email(), 'Welcome to com!', $fancy, $plain);
    }


    private function send_password_email() {
        global $pd;
        $pd->print_object('In send_password_email');
        $pd->print_object($this->get_email(), 'E-mail');
        $pd->print_object($this->get_temp_token(), 'Token');

        if (!$this->get_email() || !$this->get_temp_token())  {
            return false;
        }

        $pd->print_object($this->get_email(), 'Have all the data I need');


        $fancy = '
<div style="text-align: center;"><img src="logo.jpg" /></div>
<h2>Welcome to com!</h2>
<p>To reset your password, <a href="todo: ">click here</a> or copy and paste the URL into your browser:</p>

<p>URL?token='.$this->get_temp_token().'</p>

<p>Thanks!</p>
';
        $plain = 'Welcome to com!

To reset your password by going to the URL below:

URL?token='.$this->get_temp_token().'

Thanks!
';
        $pd->print_object('About to actually e-mail');


        return email_customer($this->get_email(), "Reset your com password", $fancy, $plain);
    }

    public function set_email($email) {
        return $this->email = $email;
    }

    public function set_id($email) {
        return $this->shopper_id;
    }

    public function set_sign_in_token($token) {
        return $this->sign_in_token = $token;
    }

    public function set_temp_token($token) {
        return $this->temp_token = $token;
    }

    public function set_username($username) {
        return $this->user_name = $username;
    }
}

我对如何引用购物者列表以及如果他们没有列表而不是选择建议的列表感到有点困惑。

我的 (oracle11g) 数据库中有一些测试列表:

     ID SHOPPING_LIST_NAME                                 S SEQUENCE
------- -------------------------------------------------- - --------
      3 793d7384fa4fa247d6fae07db104147d0a2dad6e           N
      1 test amnaik shopping list                          N
      4 kj's shopping list                                 N
      5 kj's shopping list from 1384201636                 N
      6 kj's shopping list from 1384201659                 N
      7 kj's shopping list from 1384202055                 N
      8 kj's shopping list from 1384202089                 N
      2 bonner shopping list                               N

8 rows selected.



SHOPPING_LIST_ID SHOPPER_ID ITM_CD    QUANTITY CHANGE_DA CHANGE_US A O
---------------- ---------- --------- -------- --------- --------- - -
               1          2 ABI85MT06        4 28-OCT-13 CUSTOM    N N
               1          1 STZ28AC1         3 11-NOV-13 CUSTOM    Y N
               1          1 ABI85MT06        3 11-NOV-13 CUSTOM    Y N
               1          1 XYZ              1                     Y N
               2          1 XYZ              1                     Y N
               4         67 MND44SA01        1                     Y N
               4         67 MND44SA02        1                     Y N
               2         67 MND44SA02        1                     Y N
               1          1 ABCDEF           1                     Y N

9 rows selected.

像往常一样,我们将不胜感激任何帮助或建议。谢谢。

最佳答案

基于那个 Shopper 类,您更新的 get_lists 函数正在调用一个 db 方法:

$rows = $db->get_function('custom.japi_shopper_identity.get_lists_for_shopper(:i_sign_in_token)', $vars);

此方法返回一个数组,我必须假设它是来自 oracle 数据库的查询结果。在将其转换为一组对象并将其返回到 get_shopping_lists.php 后,您需要检查以确保此值不为 false,因为这是 get_lists() 方法调用中的最终 else 条件。如果是,则输出某种类型的错误消息(如果这是您的消费者所期望的,则可能是 JSON 格式)。

至于你想添加的新东西

  • 如果他们没有,则自动创建一个列表
  • 获取建议列表

对于第一个,在获取行之后,您将检查以确保 $rows 不为空,然后调用一个方法来创建列表(大概也是某种类型的 customer.japi_shopper... oracle 上的函数边。

对于第二个,您将使用 if/else 分支逻辑(如果 $suggested == true,获取这些结果;否则,执行您已经在执行的操作...)

关于php - 我正在开发一个 php 购物 list 函数/api,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20059662/

有关php - 我正在开发一个 php 购物 list 函数/api的更多相关文章

  1. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  2. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  3. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  4. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  5. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  6. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  7. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  8. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  9. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  10. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

随机推荐