It is very helpfull for any one who want to create online shop.
In this project I use no any extension, due to most of them are less informative how to implement it in our own project.
I use simple term, because I assume your shop only use payment method by bank transfer, and we only use plain Yii2 features.
Little know-how on the use of yii\bootstrap\Modal will be advantage, it will make our forms more interactive.
1. Model
Structur of the model is like this:
- product, it will contain detail of product you will sell. The field required in this table are ID and price.
- order, it will save orderâs detail.
- order item, it will be our place to put item for each order.
Tabel 1
CREATE TABLE smf_product_pricing
(
id
int(3) UNSIGNED NOT NULL,
product_type
varchar(200) NOT NULL,
standard_id
int(2) UNSIGNED DEFAULT NULL,
currency
varchar(20) NOT NULL,
title
varchar(250) DEFAULT NULL,
description
text DEFAULT NULL,
price
decimal(10,2) UNSIGNED NOT NULL,
notes
varchar(200) DEFAULT NULL,
status
varchar(250) DEFAULT NULL,
created_at
datetime NOT NULL,
updated_at
datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE smf_product_pricing
ADD PRIMARY KEY (id
);
ALTER TABLE smf_product_pricing
MODIFY id
int(3) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;
On the above table there is standard_id, it is for detail description of the product. You can omit it if you do not need it.
Tabel 2
CREATE TABLE smf_product_order
(
id
int(6) UNSIGNED NOT NULL,
user_id
int(4) UNSIGNED DEFAULT NULL,
method
varchar(200) NOT NULL,
status
varchar(100) NOT NULL,
foto
varchar(300) DEFAULT NULL,
created_at
datetime DEFAULT NULL,
updated_at
datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE smf_product_order
ADD PRIMARY KEY (id
);
ALTER TABLE smf_product_order
MODIFY id
int(6) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;
In the above table, user_id is to record who make order. It is very important field.
Table 3
CREATE TABLE smf_product_order_item
(
id
int(6) UNSIGNED NOT NULL,
order_id
int(5) UNSIGNED NULL,
product_id
int(3) UNSIGNED NOT NULL,
quantity
int(3) UNSIGNED NOT NULL,
currency
varchar(100) DEFAULT NULL,
price
decimal(5,2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE smf_product_order_item
ADD PRIMARY KEY (id
);
ALTER TABLE smf_product_order_item
MODIFY id
int(6) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;
In the Table 3 above, order_id I created is NULL default. It is the key field for our trick shopping online.
product_id will be taken from Table 1.
Lets do Gii for all the above tables.
2. Process flow:
2. 1. We show product to be sold.
For icons you can get it from https://fontawesome.com/v4.7.0/icons/
Controller to displat it as below
public function actionShop()
{
$searchModel = new StandardPriceSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('shop', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
public function actionLists() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$product_type = (int)$parents[0];
$out = StandardPrice::find()
->where(['product_type'=>$product_type])
->select(['id'=>'id', 'name'=>'id']) //'id' will be recorded, 'name' will be showed
->asArray()
->all();
return Json::encode(['output'=>$out, 'selected'=>'']);
}
}
return Json::encode(['output'=>'', 'selected'=>'']);
}
There are some table use in this query, it will limit only certain product available to pick by any user.
My orange cart icon actually is
[
âformatâ => ârawâ,
âheaderOptionsâ => [âstyleâ => âwidth:5%â, âclassâ => âtext-centerâ],
âcontentOptionsâ => [âstyleâ => âwidth:5%â, âclassâ => âtext-centerâ],
âvalueâ => function ($model) {
return Html::a(ââ,
[â/product-order-item/createâ,âproduct_idâ=>$model->standard_id, âpriceâ=>$model->price],
[
âdata-toggleâ=>âmodalâ,
âdata-targetâ=>"#myModal",
âdata-titleâ=>âAdd to myCardâ,
]
);
},
],
If you rigth-click the orange cart icon, it will
âvalueâ => function ($model) {
return Html::a(ââ,
[â/product-order-item/createâ,âproduct_idâ=>$model->standard_id, âpriceâ=>$model->price],
[
âdata-toggleâ=>âmodalâ,
âdata-targetâ=>"#myModal",
âdata-titleâ=>âAdd to myCardâ,
]
);
},
If you not prefer to use Modal it will be like this
âvalueâ => function ($model) {
return Html::a(ââ,
[â/product-order-item/createâ,âproduct_idâ=>$model->standard_id, âpriceâ=>$model->price]
);
},
Icon myCart bottom appear only when we have any item picked. You can make sql to make it.
2.2. Put an item into myCart.
When we click orange icon it will appear like this
It could be like by implementing Modal. If you not experience of modal, just use plain form.
User just key in number of pcs product he/she need. I am hidden other field (order_id, product_id), my actual form is like this
<?= $model->standards->standardPrice->product_type.' '. $model->standards->title.' '.$model->standards->standardPrice->currency.' '.$model->standards->standardPrice->price; ?>
<?php $form = ActiveForm::begin([
'options'=>['onsubmit' => "myButton.disabled = true; return true;"]
]);
?>
<?= $form->field($model, 'order_id')->hiddenInput()->label(false) ?>
<?= $form->field($model, 'product_id')->hiddenInput()->label(false) ?>
<?= $form->field($model, 'currency')->hiddenInput(['value'=>'SGD'])->label(false) ?>
<?= $form->field($model, 'price')->hiddenInput(['value'=>$model->price])->label(false) ?>
<?= $form->field($model, 'quantity')->textInput(['placeholder'=>'Type how many pcs'])->label('Pcs Request') ?>
</div>
<div class="form-group">
<?= Html::submitButton('<i class="fa fa-send fa-lg fa-fw" aria-hidden="true" style="color:white"></i> Submit', ['class' => 'btn btn-info', 'name'=>'myButton']) ?>
</div>
<?php ActiveForm::end(); ?>
Controller for this action
public function actionCreate()
{
$model = new ProductOrderItem();
if ($model->load(Yii::$app->request->post())) {
$model->price = $model->quantity * $model->price;
$model->save();
return $this->redirect(['standard-price/shop']);
}
else{
$model->product_id = $_GET['product_id'];
$model->price = $_GET['price'];
}
return $this->renderAjax('create', [
'model' => $model,
]);
}
These lines
$model->product_id = $_GET[âproduct_idâ];
$model->price = $_GET[âpriceâ];
to use as default value for the fields. Then we could hide the field in the form ($form->field($model, âproduct_idâ)->hiddenInput()->label(false)
).
If you click Submit, our Table 3 will be inserted.
You can see that even in the Item List the price per unit is SGD10, if I typed 3pcs the price the above Table 3 is 30. In the controller I applied $model->price = $model->quantity * $model->price before we do $model->save();
Please see that only field order_id NULL.
2.3. myCart
If we click myCart icon within the Item List page, weâll see
There two icon in rightest side of myCart, pencil and trash bin. Those just update and delete as usual from our Gii of Table 3.
Controller to view mycart like below:
public function actionCart()
{
$query = Yii::$app->getDb()->createCommand('
SELECT smf_product_order_item.id,
smf_product_order_item.currency,
smf_product_order_item.price as price,
smf_product_order_item.quantity,
standards.title as title,
smf_product_pricing.price as unit
FROM smf_product_order_item
LEFT JOIN standards
ON standards.stdid = smf_product_order_item.product_id
LEFT JOIN smf_product_pricing
ON standards.stdid = smf_product_pricing.standard_id
WHERE smf_product_order_item.postedby = '.Yii::$app->user->id.'
AND DAY(smf_product_order_item.created_at) = "'.date('d').'"
AND smf_product_order_item.order_id IS NULL
')
->queryAll();
return $this->render('cart', [
'model' => $query,
]);
}
Please apologize me if I can not inform detail of table standards, you can use your own table for detail of the product.
A new icon is blue button for attach payment and check out. This is very simple online shop and we use bank transfer to complete our transaction. If you click this button, will appear form to upload.
the actual code of the button is
<?= Html::a('Attach payment and check out?',
['/product-order/create1', 'user_id'=>Yii::$app->user->id],
[
'class' => 'btn btn-info',
'data-toggle'=>"modal",
'data-target'=>"#myModal",
'data-title'=>"Upload Transfer Receipt",
]
)?>
I have modidy actionCreate1 as follows
public function actionCreate1()
{
$model = new ProductOrder();
if ($model->load(Yii::$app->request->post())) {
//save image
Yii::setAlias('newsfolder', dirname(dirname(__DIR__)) . '/frontend/web/images/selling');
$model->foto = UploadedFile::getInstance($model,'foto');
$filename = rand(0,9999).' - Product Order - Payment Receipt';
$model->foto->saveAs( Yii::getAlias('@newsfolder/').$filename.'.'.$model->foto->extension );
$model->foto = $filename.'.'.$model->foto->extension;
$model->save();
$imagine = Image::getImagine();
$image = $imagine->open(Yii::getAlias('@newsfolder/'.$model->foto));
$image->save(Yii::getAlias('@newsfolder/'.$model->foto, ['quality' => 40]));
//update
$query = Yii::$app->getDb()->createCommand('
UPDATE smf_product_order_item
SET order_id = '.$model->id.'
WHERE postedby = '.Yii::$app->user->id.'
AND DAY(created_at) = "'.date('d').'"
AND order_id IS NULL
')->execute();
//send email to buyer
$email = \Yii::$app->mailer->compose()
->setTo([Yii::$app->user->identity->email => Yii::$app->user->identity->profile->first_name.' '.Yii::$app->user->identity->profile->last_name])
->setFrom([\Yii::$app->params['adminEmail'] => \Yii::$app->params['nickName'] .' \'s Server'])
->setSubject('Your Order #'.sprintf('%04d', $model->id).' at '.\Yii::$app->params['nickName'].' Shop.')
->setHtmlBody('Dear '.Yii::$app->user->identity->profile->first_name.' '.Yii::$app->user->identity->profile->last_name.'
<br><br>Thank you for your payment made via bank transfer received on '.date('Y-m-d H:i:s').'
<br><br>We will revert to you if necessary.
<br><br>Best Regards.
<br><br><br>'.\Yii::$app->params['nickName'].' Office Admin'
)->send();
Yii::$app->session->setFlash('success', 'Thank you. Your order and transfer receipt has received by the server.');
return $this->redirect(['view', 'id' => $model->id, 'user_id'=>Yii::$app->user->id]);
}
return $this->renderAjax('create1', [
'model' => $model,
]);
}
</code
I will not explain about saving image, assume you have familiar with it.
The trick is lie in the above $query. We must do it because when we put any item into Table 3, order_id has NULL by default. By doing this trick, we entried order_id into the table.
When our form executed it will send notification email to user.
This our Attache payment form
3. End Result
If our order successful, will show this page
If we click Attachment tab in the above image, it will show just our uploaded file.
Thats itâŚwish you luck.