问题为。点击产品页面的。 Add to Favorites链接。 但是 aaa.com/customer/productfavorite 点进去会员页面却是空的,但星星的图标的数量有添加。 系统也没有报错。换浏览器操作也一样。
您的是最新版本吗?
http://fecshop.appfront.fancyecommerce.com/raglan-sleeves-letter-printed-crew-neck-sweatshirt-53386451-77774122
我在演示网站测试了一下,是可以的,如图:
您追踪下代码看看,是什么原因导致的?
用的是最新版的。1.4.1.0 查看mongodb数据中是,添加成功了。有记录。但是无法显示。 不知道id=0是什么意思。 我的会员ID是2
@myred08 #2楼 你自己追踪一下代码,不显示,在于2个部分:
1.添加到收藏失败,或者添加到收藏的数据有问题,你看一下添加的产品和执行收藏的用户的id是否正确
2如果第一步骤点击收藏,保存到数据库的数据没有问题,那么,.账户中心的收藏列表,可能 显示收藏功能有问题,去这里排查一下
顺藤摸瓜,查看一下具体的问题所在,官网demo是没有问题的,您自己调试一下,找找是什么原因导致的。
/app/appfront/modules/Customer/block/productfavorite/Index.php
第34行改为 $user_id = (int)$identity->id;
把user_id类型强制转成int发现。就可以显示了。 不知道是不是我mongodb没有升级数据库的原因? 另外是windows 环境下的BUG。
类型导致的bug
恩。linux可能没有关系吧。 windows是有BUG。
你的 $identity->id,为什么是字符串类型,这个是数据库customer表的id,是int类型。
$identity->id
不应该是string的,你是第一个提这个错误的
你是不是改代码改错了?我在demo输出了一下,是int类型,而不是字符串,这个不是bug,应该是你自己改了哪里东西导致的。
@myred08 #7楼 和window应该没有关系的,window可能出现大小写问题,但是不会出现类型搞错的问题。
#8楼 和mysql表没关系。 favorite表是在mongodb里面。 你用什么软件查看 mongodb表结构? 我现在是用一个插件看不到结构。 另外我是根据 http://www.fecshop.com/topic/527 安装的系统。
\vendor\fancyecommerce\fecshop\services\product\Favorite.php
protected function actionList($filter) { echo("改前:"); var_dump($filter);
你可以输出看一下变量
另外这个/app/appfront/modules/Customer/block/productfavorite/Index.php文件,user_id是string类型的。
public function getLastData() { $this->initFavoriteParam(); $identity = Yii::$app->user->identity; $user_id = $identity->id; var_dump($user_id);
mysql表格结构没有错误是int类型的,另外我也是刚研究。没有改东西呢。
你输出一下: Yii::$app->user->identity
var_dump( Yii::$app->user->identity)
你是提这个问题的第一个人,其他人没有遇到过。
对于appfront user组件的配置
@fecshop/app/appfront/config/appfront.php
'user' => [ 'class' => 'fecshop\yii\web\User', 'identityClass' => 'fecshop\models\mysqldb\Customer', // 是否cookie 登录。 /* * @var boolean whether to enable cookie-based login. Defaults to false. * Note that this property will be ignored if [[enableSession]] is false. * 设置为true的好处为,当浏览器关掉在打开,可以自动登录。 */ 'enableAutoLogin' => true, /* * authTimeout => 56666, * 这里请不要设置authTimeout,为了让customer账户session * 和cart的session保持一致,设置超时时间请统一在session组件 * 中设置超时时间。 */ //'authTimeout' => 56666, ],
fecshop\yii\web\User 继承于 yii\web\User
Yii::$app->user->identity 这个执行的函数为:
protected function renewAuthStatus() { $session = Yii::$app->getSession(); $id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null; if ($id === null) { $identity = null; } else { /* @var $class IdentityInterface */ $class = $this->identityClass; $identity = $class::findIdentity($id); } $this->setIdentity($identity); if ($identity !== null && ($this->authTimeout !== null || $this->absoluteAuthTimeout !== null)) { $expire = $this->authTimeout !== null ? $session->get($this->authTimeoutParam) : null; $expireAbsolute = $this->absoluteAuthTimeout !== null ? $session->get($this->absoluteAuthTimeoutParam) : null; if ($expire !== null && $expire < time() || $expireAbsolute !== null && $expireAbsolute < time()) { $this->logout(false); } elseif ($this->authTimeout !== null) { $session->set($this->authTimeoutParam, time() + $this->authTimeout); } } if ($this->enableAutoLogin) { if ($this->getIsGuest()) { $this->loginByCookie(); } elseif ($this->autoRenewCookie) { $this->renewIdentityCookie(); } } }
你可以输出一下,看看这个id是哪里搞成了string。我从来没有遇到过,也没有人提到这个问题。
protected function renewAuthStatus() { $session = Yii::$app->getSession(); $id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null; var_dump($id); var_dump($session->getHasSessionId()); var_dump($session->getIsActive()); var_dump($session->get($this->idParam));
输入的结果为
string(1) "2" bool(true) bool(true) string(1) "2"
应该是这个有问题 $session->get($this->idParam) 这个在哪个文件里面?
对于
protected function renewAuthStatus() { $session = Yii::$app->getSession(); $id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null; var_dump($session->getHasSessionId()); var_dump($this->idParam); var_dump($session->get($this->idParam)); var_dump($id); if ($id === null) { $identity = null; } else { /* @var $class IdentityInterface */ $class = $this->identityClass; $identity = $class::findIdentity($id); }
我的输出为 bool(true) string(4) "__id" int(432) int(432)
bool(true) string(4) "__id" int(432) int(432)
$session = Yii::$app->getSession();
这个 $session , 得看配置
打开@common/config/main-local.php 看一下你的session的配置
'session' => [ 'class' => 'yii\redis\Session',
fecshop 默认推荐使用redis,你的session的class是否是'yii\redis\Session'
'yii\redis\Session'
对于上面的session值的写入,是在账户login的时候,还是 yii/web/User.php文件,我给你罗列下代码
登录函数
public function login(IdentityInterface $identity, $duration = 0) { if ($this->beforeLogin($identity, false, $duration)) { $this->switchIdentity($identity, $duration); $id = $identity->getId(); $ip = Yii::$app->getRequest()->getUserIP(); if ($this->enableSession) { $log = "User '$id' logged in from $ip with duration $duration."; } else { $log = "User '$id' logged in from $ip. Session not enabled."; } Yii::info($log, __METHOD__); $this->afterLogin($identity, false, $duration); } return !$this->getIsGuest(); }
里面有一行代码:$this->switchIdentity($identity, $duration);
$this->switchIdentity($identity, $duration);
这个函数的代码:
public function switchIdentity($identity, $duration = 0) { $this->setIdentity($identity); if (!$this->enableSession) { return; } /* Ensure any existing identity cookies are removed. */ if ($this->enableAutoLogin && ($this->autoRenewCookie || $identity === null)) { $this->removeIdentityCookie(); } $session = Yii::$app->getSession(); if (!YII_ENV_TEST) { $session->regenerateID(true); } $session->remove($this->idParam); $session->remove($this->authTimeoutParam); if ($identity) { $session->set($this->idParam, $identity->getId()); if ($this->authTimeout !== null) { $session->set($this->authTimeoutParam, time() + $this->authTimeout); } if ($this->absoluteAuthTimeout !== null) { $session->set($this->absoluteAuthTimeoutParam, time() + $this->absoluteAuthTimeout); } if ($this->enableAutoLogin && $duration > 0) { $this->sendIdentityCookie($identity, $duration); } } // regenerate CSRF token Yii::$app->getRequest()->getCsrfToken(true); }
这个函数里面有一行: $session->set($this->idParam, $identity->getId());
$session->set($this->idParam, $identity->getId());
也就是这里把这个id的值塞进去的,你可以退出下账户,然后重新登录,打印一下这个$identity->getId()的值,是否是int。
$identity->getId()
大致说的差不多了,你自己排查下原因把。
你可以试试先退出账户,然后重新登录,是否还是看不到收藏列表?
session 的redis配置和你一样的。
public function switchIdentity($identity, $duration = 0) { $this->setIdentity($identity); if (!$this->enableSession) { return; } /* Ensure any existing identity cookies are removed. */ if ($this->enableAutoLogin && ($this->autoRenewCookie || $identity === null)) { $this->removeIdentityCookie(); } $session = Yii::$app->getSession(); if (!YII_ENV_TEST) { $session->regenerateID(true); } $session->remove($this->idParam); $session->remove($this->authTimeoutParam); if ($identity) { var_dump($identity->getId()); exit();
执行退出重登录后,输出的还是 string(1) "2" 同时发现redis里面的内容好像类型就是 string的。
再次执行清空redis seesion所有数据。重新登录后 查看redis记录是
__flash|a:0:{}currency_current|s:3:"USD";FBRLH_state|s:32:"f9fd12780aa786c202a50eb88b997c52";__id|s:1:"2";current_session_cart_id|s:1:"7";
按理说应该是 __id|i:2; 吧? 我redis不熟悉 :(
你先把redis当成黑盒,你看看session,set的时候,set的值是字符串还是int,如果set的值是int,取出来是字符串,说明redis有问题,你的redis版本是多少,是不是版本过低?
我安装的是 Redis-x64-3.2.100.msi 这个版本的redis. 另外 redis 好像 set 值都是 string类型的。没有整型的。redis 不熟悉。楼主有测试的PHP代码? 另外fecshop设置和读取redis的函数在哪里。
@myred08 #21楼 上面给予的代码有的
你可以用Yii::$app->session 自己测试一下,set一个int类型,取出来看看是否还是int
public function switchIdentity($identity, $duration = 0) { $this->setIdentity($identity); if (!$this->enableSession) { return; } /* Ensure any existing identity cookies are removed. */ if ($this->enableAutoLogin && ($this->autoRenewCookie || $identity === null)) { $this->removeIdentityCookie(); } $session = Yii::$app->getSession(); if (!YII_ENV_TEST) { $session->regenerateID(true); } $session->remove($this->idParam); $session->remove($this->authTimeoutParam); if ($identity) { //var_dump($identity->getId()); //exit(); $session->set($this->idParam, $identity->getId()); $session->set("testint", 2233); var_dump($session->get("testint")); exit();
添加测试代码
$session->set("testint", 2233); var_dump($session->get("testint")); exit();
测试的结果是正常的。
应该是写入session的时候出哪里问题了。为了完美还是找找哪里出问题了。
$session->set($this->idParam, $identity->getId());: 这个是set 当前用户的id的值, 你调试一下,看看到底是哪里出现的问题(可能不止这一个地方set,你自己细细看看吧)
您自己慢慢研究下吧,我也只能说这么多了,您自己调试打印看看输出,导致这个问题的根源在什么地方。
好像是。 PHP取SQL数据库的问题。 PHP用pdo连接MYSQL会出现INT读取了变 string的情况。 请问fecshop的mysql连接方式是用pdo连接吗?
https://segmentfault.com/q/1010000002957162
@myred08 #26楼 是pdo。
对于Yii2
如果取数据使用的是 AR::find()->asArray()->where()->all() 取出来的int类型是字符串的
AR::find()->asArray()->where()->all()
如果取数据使用的 AR::find()->where()->all() 取出来的int类型,是int类型、
AR::find()->where()->all()
也就是说,如果存在asArray(),yii2的AR不会进行类型转换。
asArray()
你查看一下代码是否有asArray()
我去 yii/web/User.php 看了一下代码
protected function renewAuthStatus() { $session = Yii::$app->getSession(); $id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null; if ($id === null) { $identity = null; } else { /* @var $class IdentityInterface */ $class = $this->identityClass; $identity = $class::findIdentity($id); }
$identity = $class::findIdentity($id); 这个代码出来的 $identity
$identity = $class::findIdentity($id);
$identity
通过代码: $class = $this->identityClass;可以知道 $class 就是配置中的 identityClass
$class = $this->identityClass;
$class
identityClass
@fecshop/app/appfront/config/appfront.php 可以看到配置
'user' => [ 'class' => 'fecshop\yii\web\User', 'identityClass' => 'fecshop\models\mysqldb\Customer',
因此,上面的 $this->identityClass 就是 'fecshop\models\mysqldb\Customer'
$this->identityClass
'fecshop\models\mysqldb\Customer'
因此打这个文件,查看
/** * @property $id | Int , 用户id * 通过id 找到identity(状态有效) */ public static function findIdentity($id) { return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]); }
是这个函数
因此你可以这样改改,打印一下
public static function findIdentity($id) { $re = static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]); var_dump($re); exit; return $re }
看看这个里面的id是字符串还是int
对于Yii2的 findOne() 方法,是会转换相应的数据类型的,你先打印看看
@fecshop\models\mysqldb\Customer 的 函数 findIdentity($id) 返回值 是int还是string
打印的结果就是string
object(fecshop\models\mysqldb\Customer)#76 (10) { ["_attributes":"yii\db\BaseActiveRecord":private]=> array(19) { ["id"]=> string(1) "2" ["password_hash"]=> string(60) "$2y$13$I4udjWohgTL8BFP7SfQAeurUu9lJ083xUDADwpQtUgmB9KNqnONVC" ["password_reset_token"]=> NULL ["email"]=> string(10) "aa@126.com" ["firstname"]=> string(4) "jiji" ["lastname"]=> string(2) "ji" ["is_subscribed"]=> int(1) ["auth_key"]=> string(32) "XZBZx6HCoYKj-nLssW7ZKIv_vTK4n4hD" ["status"]=> int(1) ["created_at"]=> int(1523432665) ["updated_at"]=> int(1523432665) ["password"]=> string(0) "" ["access_token"]=> string(32) "BQJkwszDllrGrjezyFKtjMe6trHKSxOm" ["birth_date"]=> NULL ["favorite_product_count"]=> int(4) ["type"]=> string(7) "default" ["access_token_created_at"]=> NULL ["allowance"]=> NULL ["allowance_updated_at"]=> NULL } ["_oldAttributes":"yii\db\BaseActiveRecord":private]=> array(19) { ["id"]=> string(1) "2" ["password_hash"]=> string(60) "$2y$13$I4udjWohgTL8BFP7SfQAeurUu9lJ083xUDADwpQtUgmB9KNqnONVC" ["password_reset_token"]=> NULL ["email"]=> string(10) "aa@126.com" ["firstname"]=> string(4) "jiji" ["lastname"]=> string(2) "ji" ["is_subscribed"]=> int(1) ["auth_key"]=> string(32) "XZBZx6HCoYKj-nLssW7ZKIv_vTK4n4hD" ["status"]=> int(1) ["created_at"]=> int(1523432665) ["updated_at"]=> int(1523432665) ["password"]=> string(0) "" ["access_token"]=> string(32) "BQJkwszDllrGrjezyFKtjMe6trHKSxOm" ["birth_date"]=> NULL ["favorite_product_count"]=> int(4) ["type"]=> string(7) "default" ["access_token_created_at"]=> NULL ["allowance"]=> NULL ["allowance_updated_at"]=> NULL } ["_related":"yii\db\BaseActiveRecord":private]=> array(0) { } ["_relationsDependencies":"yii\db\BaseActiveRecord":private]=> array(0) { } ["_errors":"yii\base\Model":private]=> NULL ["_validators":"yii\base\Model":private]=> NULL ["_scenario":"yii\base\Model":private]=> string(7) "default" ["_events":"yii\base\Component":private]=> array(0) { } ["_eventWildcards":"yii\base\Component":private]=> array(0) { } ["_behaviors":"yii\base\Component":private]=> array(0) { } }
感觉要找到原因了。 :)
其实到这里已经说明问题,你的Yii2框架,为什么findOne()函数出来的,为什么id是string,但是 created_at status是int呢?
我也搞不明白,不过我可以继续说一下,下面是代码追踪
AR: yii/db/ActiveRecord.php 继承于 yii/db/BaseActiveRecord
在这个文件可以看到:findOne函数
/** * {@inheritdoc} * @return static|null ActiveRecord instance matching the condition, or `null` if nothing matches. */ public static function findOne($condition) { return static::findByCondition($condition)->one(); }
static::findByCondition 函数在 yii/db/ActiveRecord.php
/** * Finds ActiveRecord instance(s) by the given condition. * This method is internally called by [[findOne()]] and [[findAll()]]. * @param mixed $condition please refer to [[findOne()]] for the explanation of this parameter * @return ActiveQueryInterface the newly created [[ActiveQueryInterface|ActiveQuery]] instance. * @throws InvalidConfigException if there is no primary key defined * @internal */ protected static function findByCondition($condition) { $query = static::find(); if (!ArrayHelper::isAssociative($condition)) { // query by primary key $primaryKey = static::primaryKey(); if (isset($primaryKey[0])) { $pk = $primaryKey[0]; if (!empty($query->join) || !empty($query->joinWith)) { $pk = static::tableName() . '.' . $pk; } $condition = [$pk => $condition]; } else { throw new InvalidConfigException('"' . get_called_class() . '" must have a primary key.'); } } return $query->andWhere($condition); }
后面您自己慢慢玩吧
不过,你可以通过下面的方法来处理一下int字段,进来解决这个问题
你更改一下fecshop的代码,将@fecshop/models/mysqldb/Customer.php 的方法
public static function findIdentity($id) { return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]); }
更改为:
public static function findIdentity($id) { $result = static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]); $result['id'] = (int)$result['id']; return $result; }
这样应该就可以了。进行int转化一下,如果这样没有问题,可以看到产品收藏,那说明修改好了。
当然这种直接修改源码是不好的,最好用重写的方式,下面详细和你说一下(看在你这么钻研的态度上)
1.打开@appfront/config/fecshop_local.php , return数组中加入配置
return [ 'modules' => $modules, 'services' => $services, 'components' => [ 'user' => [ 'identityClass' => 'appfront\local\local_models\mysqldb\Customer', ], ], ];
然后新建文件 @appfront\local\local_models\mysqldb\Customer.php
这个class继承于 fecshop\models\mysqldb\Customer, 然后覆盖方法 findIdentity(),也就是将上面的函数赋值进去
fecshop\models\mysqldb\Customer
findIdentity()
<?php /** * FecShop file. * * @link http://www.fecshop.com/ * @copyright Copyright (c) 2016 FecShop Software LLC * @license http://www.fecshop.com/license/ */ namespace appfront\local\local_models\mysqldb; class Customer extends \fecshop\models\mysqldb\Customer { public static function findIdentity($id) { $result = static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]); $result['id'] = (int)$result['id']; return $result; } }
这样重写就完成了
@ #32 楼主牛X 按你的修改确实修复了。
@myred08 #33楼 你也很xx,喜欢刨根问底。
:sweat:
我刚用了一段代码测试了下,取出的是string的。
<?php $pdo = new PDO("mysql:host=localhost;dbname=fecshop","root","root"); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //不加取出就是string,加了就是int $pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); //不加取出就是string,加了就是int $rs = $pdo -> query("select * from customer"); while($row = $rs -> fetch()){ var_dump($row); } ?>
@myred08 #35楼 pdo是这样的,Yii2的AR查询,在没有加入asArray()的情况下,会给进行类型转换的。
但是你那个不正常,不知道为什么 findOne函数,是会给类型转换 的,不知道你的为什么不行~
findOne
@#36 我把mysql的 customer 的id UNSIGNED 属性替换为空了就可以了。 楼主你看一下。你的表里是否有这个属性。另外id有自增了。加不加UNSIGNED应该没有关系吧?我发现你的admin哪些表有的ID就没有加UNSIGNED 属性。
ALTER TABLE `customer` CHANGE `id` `id` INT( 20 ) NOT NULL AUTO_INCREMENT
id UNSIGNED 属性替换为空 不用改任何代码。
另外加了无符号只是ID的最大值变大了。 就算没有UNSIGNED范围也有 2147483647 我觉得够用了。另外也可以设置成BIGINT。哪更大了 :)
安装fecshop,这个是有的
https://github.com/fecshop/yii2_fecshop/blob/master/migrations/mysqldb/m170228_072156_fecshop_tables.php
CREATE TABLE IF NOT EXISTS `customer` ( `id` int(20) unsigned NOT NULL AUTO_INCREMENT, `password_hash` varchar(80) DEFAULT NULL COMMENT '密码', `password_reset_token` varchar(60) DEFAULT NULL COMMENT '密码token', `email` varchar(60) DEFAULT NULL COMMENT '邮箱', `firstname` varchar(100) DEFAULT NULL, `lastname` varchar(100) DEFAULT NULL, `is_subscribed` int(5) NOT NULL DEFAULT '2' COMMENT '1代表订阅,2代表不订阅邮件', `auth_key` varchar(60) DEFAULT NULL, `status` int(5) DEFAULT NULL COMMENT '状态', `created_at` int(18) DEFAULT NULL COMMENT '创建时间', `updated_at` int(18) DEFAULT NULL COMMENT '更新时间', `password` varchar(50) DEFAULT NULL COMMENT '密码', `access_token` varchar(60) DEFAULT NULL, `birth_date` datetime DEFAULT NULL COMMENT '出生日期', `favorite_product_count` int(15) NOT NULL DEFAULT '0' COMMENT '用户收藏的产品的总数', `type` varchar(35) DEFAULT 'default' COMMENT '默认为default,如果是第三方登录,譬如google账号登录注册,那么这里的值为google', PRIMARY KEY (`id`), KEY `email` (`email`), UNIQUE KEY `access_token` (`access_token`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; ", "
你这个可以整理个文章了
好的。谢谢楼主 :)
造成这个问题的原因已经找到,详细参看帖子: http://www.fecshop.com/topic/847
我也遇到了同样的问题,找了半天问题. 看了你们整个的对话,又学到了不少东西