Php 基于基础数据的动态计算 故事。
我试图根据多种不同的因素来计算产品成本。我的系统目前使用PHP函数运行得非常好,但是我想添加一些Ajax,以产生更友好的用户体验 我现在是怎么做的。 实体 形式 正如我之前所说,这一切都很好,尽管有点无聊和静态 问题 正如你从图片上看到的。ProductRecipe用作配方表单中表单的集合。我想要的是,一旦用户从数据库中选择了一个产品(黄油),并声明了数量(1)和度量值(kg),我需要Ajax首先获得单位成本(所有单位都转换为克,并更新一个名为单位成本的字段)Php 基于基础数据的动态计算 故事。,php,jquery,mysql,ajax,symfony,Php,Jquery,Mysql,Ajax,Symfony,我试图根据多种不同的因素来计算产品成本。我的系统目前使用PHP函数运行得非常好,但是我想添加一些Ajax,以产生更友好的用户体验 我现在是怎么做的。 实体 形式 正如我之前所说,这一切都很好,尽管有点无聊和静态 问题 正如你从图片上看到的。ProductRecipe用作配方表单中表单的集合。我想要的是,一旦用户从数据库中选择了一个产品(黄油),并声明了数量(1)和度量值(kg),我需要Ajax首先获得单位成本(所有单位都转换为克,并更新一个名为单位成本的字段) 1kg换算为g=1000,100
1kg换算为g=1000,1000*单位成本(0.0079600000)=7.96英镑产品成本2安装成本似乎太复杂,且与模型状态有很大关系 如果您想在客户机每次发送ajax请求时更新数据库(或某些存储),可以使用productcost2amountcost。但这既昂贵又有风险。(您必须控制请求的顺序)[解决方案1] 如果您想更简单地处理请求,我认为您应该将productcost2amountcost转换为无状态(作为一个过程)和一些小逻辑。(由客户端管理的状态)[解决方案2]
新过程通过ajax接收一些参数(如产品、数量、度量),并发送响应(如产品成本)。
(如果您使用临时模型(非存储),则可以使用productcost2amountcost。但您应该从productcost2amountcost中删除对配方的引用) 但是在这种情况下,我认为您不必使用ajax。 为了可用性,您可以使用javascript和表单数据(包括隐藏单位成本和度量尺度)计算所有成本,最后在服务器端重新计算以进行更新。[解决方案3]
不同体系结构的逻辑复制和计算都很糟糕,但这可能是一个简单的解决方案 一种解决方案是安装“FOSJsRoutingBundle”()以在Javascript中公开路由。这样,您就可以在控制器中创建一个新操作,该操作将计算产品成本并将其作为JSON返回到HTML 控制器中的操作可能如下所示:
/**
* @Route("/productcost", name="calculate_cost", options={"expose"=true})
* @Method("POST")
*/
public function getProductCostAction(Request $request) {
$amount = $request->request->get('amount', null);
$productId = $request->request->get('product', null);
if (empty($amount) || empty($productId)) {
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => false, 'message' => 'Bad input')));
}
$product = $this->getDoctrine()->getManager()->getRepository('ProductBundle:ProductRecipe')->findOneBy(array('id' => $productId));
if (empty($product)) {
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => false, 'message' => 'Invalid product')));
}
$productCost = $product->getCostunit() * $amount;
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => true, 'productCost' => $productCost)));
}
<script>
$(document).on('change', '.products, .amounts', function(event) {
var amount = $(this).parent().children('.amounts').val();
var productId = $(this).parent().children('.products').val();
if (amount == "" || productId == "") {
// Don't make the Ajax call if you are missing one of the two values
return false;
}
// This will be triggered every time a product or amount input field is changed
$.post(
Routing.generate('calculate_cost'),
{
// Use the corresponding amount and product ID
amount: amount,
product: productId
},
function(data) {
data = JSON.parse(data);
if (!data.success) {
// An error was thrown in the controller
alert(data.message);
}
else {
// Update the corresponding productCost field using the data from the controller
$(this).parent().children('.product-costs').val(data.productCost);
}
}
);
});
</script>
然后AJAX调用可能如下所示:
/**
* @Route("/productcost", name="calculate_cost", options={"expose"=true})
* @Method("POST")
*/
public function getProductCostAction(Request $request) {
$amount = $request->request->get('amount', null);
$productId = $request->request->get('product', null);
if (empty($amount) || empty($productId)) {
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => false, 'message' => 'Bad input')));
}
$product = $this->getDoctrine()->getManager()->getRepository('ProductBundle:ProductRecipe')->findOneBy(array('id' => $productId));
if (empty($product)) {
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => false, 'message' => 'Invalid product')));
}
$productCost = $product->getCostunit() * $amount;
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => true, 'productCost' => $productCost)));
}
<script>
$(document).on('change', '.products, .amounts', function(event) {
var amount = $(this).parent().children('.amounts').val();
var productId = $(this).parent().children('.products').val();
if (amount == "" || productId == "") {
// Don't make the Ajax call if you are missing one of the two values
return false;
}
// This will be triggered every time a product or amount input field is changed
$.post(
Routing.generate('calculate_cost'),
{
// Use the corresponding amount and product ID
amount: amount,
product: productId
},
function(data) {
data = JSON.parse(data);
if (!data.success) {
// An error was thrown in the controller
alert(data.message);
}
else {
// Update the corresponding productCost field using the data from the controller
$(this).parent().children('.product-costs').val(data.productCost);
}
}
);
});
</script>
$(文档).on('change','products,.amounts',函数(事件){
var amount=$(this.parent().children('.amounts').val();
var productId=$(this.parent().children('.products').val();
如果(金额=“”| |产品ID=“”){
//如果缺少这两个值中的一个,请不要进行Ajax调用
返回false;
}
//每次更改产品或金额输入字段时都会触发此操作
美元邮政(
Routing.generate('calculate_cost'),
{
//使用相应的金额和产品ID
金额:金额,,
产品名称:productId
},
功能(数据){
data=JSON.parse(数据);
如果(!data.success){
//控制器中抛出了一个错误
警报(数据、消息);
}
否则{
//使用来自控制器的数据更新相应的productCost字段
$(this.parent().children('.productcosts').val(data.productCost);
}
}
);
});
真的不清楚您的问题是什么。productcost2amountcost与配方相关的原因是,在prePersist状态下,如果我忽略它,则无法正确设置关系。我没有固定使用该功能,在一天结束时,我仍然希望服务器端功能成为主要功能,这样我就不会有任何用户破坏任何计算的风险。我想要它的目的就是让用户在编写“配方”时可以看到总价格,所以解决方案3听起来最合适。但是,当他/她选择产品时,我如何加载单位成本?如果产品:单位成本=1:1且产品数量不太多,您可以在选项标记中使用自定义属性(例如“数据单位成本”)(在formbuilder中使用“attr”)或者javascript中的数据表。您可能希望在每次更改产品或数量输入中的值时调用$.post函数。这意味着您必须使用“on”函数(),然后在else部分中更新相应的productCost输入。如果您需要一些帮助,我可以稍后创建一个JSFIDLE。我刚刚编辑了我的答案,并使用这个JSFIDLE测试了jQuery部分。看看HTML部分,看看我是如何使用类的,希望这足以让您的代码运行:)只要您使用选项={“expose”=true}公开路由注释您可以将该操作放置在任何需要的位置。我不确定您的代码是如何组织的,但我认为将其放在ProductRecipeController中是有意义的,因为您正试图获得产品成本。
//ProductRecipeController.php
public function getProductCostAction(Request $request) {
$amount = $request->request->get('amount', null);
$productId = $request->request->get('product', null);
$unit = $request->request->get('unit', null);
if (empty($amount) || empty($productId)) {
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => false, 'message' => 'Bad input')));
}
$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('MyBundle:Product')->find($productId);
$u = $em->getRepository('MyBundle:Measures')->find($unit);
$mass = new Mass($amount, $u->getUnit());
$fam = $mass->toUnit('g');
if (empty($product)) {
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => false, 'message' => 'Invalid product')));
}
$productCost = $product->getCostunit() * $fam;
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => true, 'productCost' => $productCost)));
}
/**
* @Route("/productcost", name="calculate_cost", options={"expose"=true})
* @Method("POST")
*/
public function getProductCostAction(Request $request) {
$amount = $request->request->get('amount', null);
$productId = $request->request->get('product', null);
if (empty($amount) || empty($productId)) {
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => false, 'message' => 'Bad input')));
}
$product = $this->getDoctrine()->getManager()->getRepository('ProductBundle:ProductRecipe')->findOneBy(array('id' => $productId));
if (empty($product)) {
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => false, 'message' => 'Invalid product')));
}
$productCost = $product->getCostunit() * $amount;
return new \Symfony\Component\HttpFoundation\Response(json_encode(array('success' => true, 'productCost' => $productCost)));
}
<script>
$(document).on('change', '.products, .amounts', function(event) {
var amount = $(this).parent().children('.amounts').val();
var productId = $(this).parent().children('.products').val();
if (amount == "" || productId == "") {
// Don't make the Ajax call if you are missing one of the two values
return false;
}
// This will be triggered every time a product or amount input field is changed
$.post(
Routing.generate('calculate_cost'),
{
// Use the corresponding amount and product ID
amount: amount,
product: productId
},
function(data) {
data = JSON.parse(data);
if (!data.success) {
// An error was thrown in the controller
alert(data.message);
}
else {
// Update the corresponding productCost field using the data from the controller
$(this).parent().children('.product-costs').val(data.productCost);
}
}
);
});
</script>