根据条件在 UI 上回显图像
Posted
技术标签:
【中文标题】根据条件在 UI 上回显图像【英文标题】:Echo image on an UI from a table based on a condition 【发布时间】:2017-04-21 02:14:16 【问题描述】:我有一张桌子:
场景:在这里您将看到 5 个徽章(badge1
到 badge5
)。当员工获得徽章奖励时,它变为1
,否则变为0
。 例如: Brinda 赢得所有徽章,而 lyka 仅赢得 badge1
。
徽章作为 blob 图像存储在不同的 badgePhoto
表中:
显示徽章的 UI:
现在,我有一个 UI,我想在其中显示最近赢得的 3 个徽章。
如果赢得 1 个徽章,则只会显示 1 个。 如果赢得 5 个徽章,将随机显示 3 个徽章。 如果没有赢得徽章,则回显“没有赢得徽章”。与上述 UI 中的徽章相关的 html:
<div class="panel">
<div class="form" style="width: 350px; height: 220px;">
<div class="login">Recent badges</div>
<span class="fa-stack fa-5x has-badge">
<div class="badgesize">
<img src="images/7.png" >
</div>
</span>
<span class="fa-stack fa-5x has-badge">
<div class="badgesize">
<img src="images/1.png" >
</div>
</span>
<span class="fa-stack fa-5x has-badge">
<div class="badgesize">
<img src="images/2.png" >
<!-- <img class="cbImage" src="images/7.png" style="width:50px;height:50px"/> -->
</div>
</span>
</div>
</div>
<!-- badges panel ends here -->
图像标签讲述了徽章。
我有一些 php 来获取数据:
$q2 = "SELECT * FROM pointsBadgeTable WHERE EmployeeID = '" . $_SESSION['id'] . "' ";
$stmt1 = sqlsrv_query($conn,$q2);
if ($stmt1 == false)
echo 'error to retrieve info !! <br/>';
die(print_r(sqlsrv_errors(),TRUE));
$pbrow = sqlsrv_fetch_array($stmt1);
然后,如果条件足够,即如果该徽章的计数值为 1,我将从表中回显徽章的图像。我将在上面的 html 代码中回显它。
<?php echo "" . $pbrow['badge1/badge2/...'] . "" ?>
我在这里尝试做的类似于 Stack Overflow 中的配置文件。在最新版下,您可以看到“评论家”徽章。我们如何根据条件携带最新的徽章或任何徽章?
【问题讨论】:
"..如果有人有任何想法,请提供帮助。" 但是,你没有写你要找的东西吗?您面临什么问题?什么输出来了? 我认为您没有得到问题。没问题。抱歉。我正在尝试从表格中显示上述 UI 中的最近三个徽章,其中徽章的值为 1。我已经提到了 html,我想在其中回显。无论如何,谢谢。上帝保佑。 @NanaPartykar 我认为@NanaPartykar 的意思是您已经很好地编写了您的场景并且它似乎已完全编码,但您没有说明代码失败的地方。 另外,只是对数据库设计的观察...您是否考虑过诸如 EmployeeID、BadgeName、DateAwarded 之类的东西?当徽章数量发生变化时,这会更加灵活。 嘿,IMO 200+ 代表太多了,您需要一些声誉才能进行其他活动,例如进入聊天室询问他人,为另一个棘手的问题提供赏金等。 【参考方案1】:您面临的问题是您存储数据的方式是您只知道用户拥有或不拥有哪些徽章。要了解最新的“最近”徽章,您需要将更多信息存储到数据库中。
让我们先重构一下数据库;在大多数情况下,第一列id
应该是PRIMARY KEY
和IDENTITY
,这样每次插入都会创建一个唯一的ID。让我们从删除 employees
表和 badgePhoto
中的过时列开始,我们将添加一个 id
和一个小的名称更改,这样一切都变得更有意义了。
+------+---------+ +---------------------------+
| employees | | badges |
+------+---------+ +----+--------------+-------+
| id | name | | id | name | image |
+------+---------+ +----+--------------+-------+
| 34 | Anil | | 1 | First Badge | blob |
+------+---------+ +----+--------------+-------+
| 1122 | Lyka | | 2 | Second Badge | blob |
+------+---------+ +----+--------------+-------+
| 2233 | brinda | | 3 | Third Badge | blob |
+------+---------+ +----+--------------+-------+
现在创建一个新表,以便我们可以通过连接 ID 上的表来链接数据。
+--------------------------------------------------+ CREATE TABLE employee_badges(
| employee_badges | id int NOT NULL IDENTITY PRIMARY KEY,
+----+-------------+----------+--------------------+ employee_id int NOT NULL,
| id | employee_id | badge_id | earned_on | badge_id int NOT NULL,
+----+-------------+----------+--------------------+ earned_on datetime NOT NULL DEFAULT GETDATE()
| 1 | 1122 | 1 | 2016-12-7 12:10:08 | )
+----+-------------+----------+--------------------+
| 2 | 34 | 1 | 2016-8-7 12:10:08 | INSERT INTO employee_badges (employee_id, badge_id) VALUES (1122, 1)
+----+-------------+----------+--------------------+ INSERT INTO employee_badges (employee_id, badge_id) VALUES (34, 1)
| 3 | 34 | 2 | 2016-9-6 08:10:14 | INSERT INTO employee_badges (employee_id, badge_id) VALUES (34, 2)
+----+-------------+----------+--------------------+
| etc.. each row represents an earned medal |
+--------------------------------------------------+
现在尝试可视化我们将如何连接数据,目前在此表中,员工 Lyka
有 1 个奖牌,员工 Anil
有两个。让我们将'第三枚徽章'授予'Lyka':
$sql = "INSERT INTO employee_badges (employee_id, badge_id) VALUES (1122, 3)";
$date = date("Y-m-d H:i:s", strtotime("-1 year")); // give badge at today's date, last year.
$sql = "INSERT INTO employee_badges (employee_id, badge_id, earned_on) VALUES (1122, 3, '$date')";
仅仅因为列有default value
并不意味着它不允许被覆盖。您可以根据自己的喜好调整此表(例如添加进度列),但让此示例保持简单。目前earned_on
的默认值为GETDATE()
,因此每次插入新行时,都会自动为您设置当前时间。
如果要选择员工Anil
获得的徽章,可以进行如下查询:
SELECT b.name, b.image FROM badges AS b
INNER JOIN employee_badges AS e
ON e.badge_id = b.id
WHERE e.employee_id = 34
您也可以使用像这样的过滤器来选择最新徽章。
...
WHERE e.employee_id = 34
ORDER BY e.earned_on DESC
LIMIT 1
这会将列表从最新到最早排序,如果您添加LIMIT 1
,则仅返回最上面的行。
您可以让您的 SQL 服务器做几乎所有事情,但也许您应该一次迈出一步。只需使用上面的查询并让 PHP 对其进行排序。计算返回的行数,如果 rowcount > 0,那么您就知道用户赢得了徽章,只需遍历结果并显示它。
if(sqlsrv_has_rows($stmt))
while($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))
$result[] = $row;
if(count($recentBadge) > 3)
foreach(array_rand($recentBadge, 3) as $key)
$data[] = $recentBadge[$key];
$recentBadge = $data;
foreach($recentBadge as $row)
echo
$row['name'],
# Keep in mind to fix vvvv the mime-type. If you stored it as png, then png, or gif or w/e.
'<img src="data:image/jpeg;base64,'.base64_encode($row['image']).'"/>',
'<br>'
;
else
echo 'no results';
【讨论】:
@Xorfifelse ...你是个天才。你给了我一个完美的解决方案。我唯一担心的是如何创建这个employee_badge表。我如何记录时间戳?无论如何,Thnaks。上帝保佑。 我相信我需要在这里使用更新触发器。但是我在这里的查询很困难。 @jane 我已经更新了有关表格的问题。我的专长更多是 mysql 语法,但我添加了 sql-server-2012 的查询 @感谢您的所有帮助。当您使用“限制”时,我知道您使用了“我的 sql”。但没问题。我解决了问题。但我在这里面临的问题是回显图像。 如上图选择图片时不显示?还是您的意思是将其打印到 HTML 中?【参考方案2】:首先,如果您想根据时间(这里是最近的)测量显示某些东西,您需要将时间与“事物”一起保存。在您的示例中,我建议使用单独的表来保存对用户的引用、徽章并保存收到徽章时的时间戳。这样您就可以更改您的查询,以便它根据最近收到的顺序获取徽章。
为了显示图像本身,我建议给出here 的答案(下面引用中的相关信息)
如果您有大量这样的图像,我不建议您使用第一种方法,即使用内联 base64 编码。这是通过以下方式完成的:
<img src="data:image/jpeg;base64,<?php echo base64_encode($image); ?>" />;
第二种方法是创建一个“图像” PHP 文件,该文件将数据库中图像的 ID 作为查询字符串参数并输出图像。因此,您的 HTML 将类似于:
<img src="image.php?id=<?php echo $image_id; ?>" />
【讨论】:
我和你说的一样,我正在存储时间和赢得的徽章。赢得的徽章,我将其标记为'1',其他未赢得的标记为' 0'。这就是我区分徽章与赢得和未赢得的方式。现在我还将徽章的图像存储在不同的表中。我如何相互关联,两者并仅显示(其中随机 3 个)那些赢得的徽章。谢谢。 或只有 1 个最新的徽章,在 UI 中,正如我们在堆栈溢出配置文件中看到的那样。【参考方案3】:这实际上可以通过多种方式完成,但我建议您选择其中一种:
如果可能,更改employee
表的结构,而不是boolean
获得的徽章使用datetime
(默认为NULL
);每当赢得徽章时,将timestamp
存储在该单元格中。通过这种方式,您将知道哪一个是最新的(只需查询该行,然后在结果数组中检查最大的数字) - 您也可以通过保持当前结构并添加另一列来引用最新的来实现这一点赢得徽章 ID。
关于限制 UI 中可见徽章的其他问题,您可以简单地将其添加到您的查询中:
order by rand() limit 3;
【讨论】:
【参考方案4】:如果您不想通过添加更多表来更改数据库结构,那么您面临的这个问题有一个更简单的解决方案。
为了不彻底改变你的数据库结构,我会提出这个简单的解决方法。
更改您的徽章表,而不是使用
0
或1
作为值 徽章列使其成为DATETIME
字段。当用户获得徽章时,将日期和时间作为徽章的值写入数据库,而不是1
。
通过这种方式,您可以通过运行一个简单的查询轻松获取每个用户的最新徽章。所以为了回答以下问题。
我们如何根据条件携带最新的徽章或任何徽章?
示例SQL Fiddle 的条件是在我们的查询结果中为每个用户提供过去 7 天的徽章。小提琴的测试数据如下。
CREATE TABLE `TEST` (
`id` int(10) NOT NULL PRIMARY KEY,
`name` varchar(255),
`badge1` datetime,
`badge2` datetime,
`badge3` datetime,
`badge4` datetime,
`badge5` datetime
);
INSERT INTO `TEST` (`id`,`name`,`badge1`,`badge2`,`badge3`,`badge4`,`badge5`) VALUES
(1,'Nick','2016-12-10 13:58:13','0000-00-00 00:00:00','2016-12-07 17:28:19','0000-00-00 00:00:00','0000-00-00 00:00:00'),
(2,'Sharah','2016-11-10 13:58:13','2016-11-17 13:01:13','2016-12-06 17:28:19','0000-00-00 00:00:00','0000-00-00 00:00:00'),
(3,'John','2016-11-12 11:58:13','2016-11-19 13:05:13','2016-12-08 17:28:19','0000-00-00 00:00:00','0000-00-00 00:00:00') ;
使用 MySQL 的 IF() 和 DATEDIFF() 获取最近 7 天徽章的查询
SELECT `id`,`name`,
IF(DATEDIFF(NOW(),`badge1`)>7,'0000-00-00 00:00:00', `badge1`) as `Badge1`,
IF(DATEDIFF(NOW(),`badge2`)>7,'0000-00-00 00:00:00', `badge2`) as `Badge2`,
IF(DATEDIFF(NOW(),`badge3`)>7,'0000-00-00 00:00:00', `badge3`) as `Badge3`,
IF(DATEDIFF(NOW(),`badge4`)>7,'0000-00-00 00:00:00', `badge4`) as `Badge4`,
IF(DATEDIFF(NOW(),`badge5`)>7,'0000-00-00 00:00:00', `badge5`) as `Badge5` FROM `TEST`;
编辑
您还可以尝试此查询以获取最新的徽章(日期和名称),您可以在更新后的SQL Fiddle 中看到结果
SELECT `id`,`name`,GREATEST(COALESCE(IF(DATEDIFF(NOW(),`badge1`)>0,CONCAT(`badge1`,'_badge1'),'0000-00-00 00:00:00')),
COALESCE(IF(DATEDIFF(NOW(),`badge2`)>0,CONCAT(`badge2`,'_badge2'),'0000-00-00 00:00:00')),
COALESCE(IF(DATEDIFF(NOW(),`badge3`)>0,CONCAT(`badge3`,'_badge3'),'0000-00-00 00:00:00')),
COALESCE(IF(DATEDIFF(NOW(),`badge4`)>0,CONCAT(`badge4`,'_badge4'),'0000-00-00 00:00:00')),
COALESCE(IF(DATEDIFF(NOW(),`badge5`)>0,CONCAT(`badge5`,'_badge5'),'0000-00-00 00:00:00'))) as `latest_badge` FROM `TEST`;
上述查询的输出。每个用户的最新徽章字段是日期、时间和徽章名称的组合。
id name latest_badge
1 Nick 2016-12-10 13:58:13_badge1
2 Sharah 2016-12-06 17:28:19_badge3
3 John 2016-12-08 17:28:19_badge3
【讨论】:
以上是关于根据条件在 UI 上回显图像的主要内容,如果未能解决你的问题,请参考以下文章