Yii2 creates new session instead of opening existing - php

I am working on a simple logic of storing my shopping cart in session using Yii2 native yii\web\Session.
Every time I add an item to a cart I call a method:
public function actionAdd( ) {
$id = Yii::$app->request->get('id');
$product = Product::findOne($id);
$session = Yii::$app->session;
$session->open();
$cart = new Cart();
$cart->addToCart($product);
$this->layout = false;
return $this->render('cart-modal', compact('session'));
}
this method works with a Cart model and adds my item to the session:
public function addToCart($product, $qty = 1) {
if(isset($_SESSION['cart'][$product->id])) {
$_SESSION['cart'][$product->id]['qty'] += $qty;
} else {
$_SESSION['cart'][$product->id] = [
'qty' => $qty,
'title' => $product->title,
'price' => $product->price,
'image' => $product->image,
];
}
}
and all goes well until I try add another item.
Then Yii instead of opening existing session creates a new one with this last item I've add. What can be the reason of this kind of behavior?
I'm working on a local web server OpenServer and haven't changed any setting that might be related to sessions.

You are basically not using session component at all. Change your code to:
public function actionAdd( ) {
$id = Yii::$app->request->get('id');
$product = Product::findOne($id);
// REMOVE THIS
// session is started automatically when using component
// $session = Yii::$app->session;
// $session->open();
$cart = new Cart();
$cart->addToCart($product);
$this->layout = false;
return $this->render('cart-modal', compact('session'));
}
public function addToCart($product, $qty = 1) {
$session = Yii::$app->session;
if ($session->has('cart')) {
$cart = $session['cart']; // you can not modify session subarray directly
} else {
$cart = [];
}
if(isset($cart[$product->id])) {
$cart[$product->id]['qty'] += $qty;
} else {
$cart[$product->id] = [
'qty' => $qty,
'title' => $product->title,
'price' => $product->price,
'image' => $product->image,
];
}
$session->set('cart', $cart);
}
I hope it helps. If not it means problem is somewhere else but nevertheless you should use session component properly.

Ok, I've figured. The problem was with my server. As soon as I moved to VPS this issue has gone.

Related

Unique data input to Laravel session

To create a shopping cart, I would like to add the same product only once to my Laravel session. I have tried this condition within my controller, but it's still not working. Any ideas?
Controller
$sessions = Session::get('items.item');
foreach ($sessions as $session) {
if ($request->name == $session['name']) {
return;
} else {
Session::push('items.item', [
'name' => $request->name,
]);
}
}
Your code will add the item immediately if the first item it finds does not have the same name. You have to check all items before adding the new one.
$sessions = Session::get('items.item');
$inItems = false;
foreach ($sessions as $session) {
if ($request->name == $session['name']) {
$inItems = true;
break;
}
}
if (!$inItems) {
Session::push('items.item',[
'name' => $request->name,
]);
}

Prestashop tab creation, specific page for each tabs

Somehow, I have to create admin pages of my module. And this is how I am creating tabs
private function createTab()
{
$data = array(
'id_tab' => '',
'id_parent' => 0,
'class_name' => 'AdminSomeMenu',
'module' => $this->name,
'position' => 1, 'active' => 1
);
$res = Db::getInstance()->insert('tab', $data);
$id_tab = Db::getInstance()->Insert_ID();
$lang = (int)Configuration::get('PS_LANG_DEFAULT');
//Define tab multi language data
$data_lang = array(
'id_tab' => $id_tab,
'id_lang' => $lang,
'name' => $this->name
);
// Now insert the tab lang data
$res &= Db::getInstance()->insert('tab_lang', $data_lang);
$arrayTabs = array('TAB1','TAB2','TAB3');
foreach ($arrayTabs as $requiredTabs)
{
$tab = new Tab();
// Need a foreach for the language
$tab->name[$lang] = $this->l($requiredTabs);
$tab->class_name = 'Admin'.$requiredTabs;
$tab->id_parent = $id_tab;
$tab->module = $this->name;
$tab->add();
}
return true;
}
I hope I am going fine.
Once the tabs are created am trying linking with the following code.
<?php
class AdminMenuController extends ModuleAdminController
{
public function __construct()
{
$module = "mymodulename"
Tools::redirectAdmin('index.php?controller=AdminModules&configure='.$module.'&token='.Tools::getAdminTokenLite('AdminModules'));
}
}
This way the controller not found was gone. But I can create only the configure page through such link.
How should I go to achieve personalized page for each tabs.
Ah ! That was a missing parent::__construct(); in controllers causing the problem for not letting tabs behave the way they should.
<?php
class AdminTAB1Controller extends ModuleAdminController
{
public function __construct()
{
parent::__construct();
/* Tools::redirectAdmin('index.php?controller=AdminModules&configure='.$module.'&token='.Tools::getAdminTokenLite('AdminModules')); */
echo "Support page";
/* or further function can be called to load tpl files from views/templates/admin/ */
}
}
Now I have different pages for my tabs in both PS 1.6 and 1.7 !

Set Parameter Variable Globally at all the backend Yii2

I have this code in layout/main.php:
$userId = Yii::$app->user->id;
$data = User::find()->where('id ="'.$userId.'"')->one();
$type = $data['type'];
Yii::$app->view->params['Type'] = $type;
I cant' access $this->params['Type'] from any controller except SiteController. If I navigated using any another controller i got this error:
PHP Notice – yii\base\ErrorException
Undefined index: Type
If I duplicated my query in every controller, It works well. But I don't want to do that. How to make it globally at the backend only?
You can definitely accomplish this (without explicitly session coding) successfully by
In your model (User.php)
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
// return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
$User = static::findOne(['id'=>$id]);
if(!$User)
{
return null;
}
else
{
$dbUser =
[
'id' => $User->id,
'image'=>$User->image,
'type'=>$User->type,
// 'usertype'=>$User->user_type, set other attributes too
'username' => $User->username,
'first_name' => $User->first_name,
'last_name' => $User->last_name,
'email' => $User->email,
];
return new static($dbUser);
}
}
Now if the user has logged in successfully, then you use all this attributes globally (through out the project For eg in model, view controller) by
For eg
echo Yii::$app->user->identity->id;
echo Yii::$app->user->identity->image;
echo Yii::$app->user->identity->type;
echo Yii::$app->user->identity->username;
echo Yii::$app->user->identity->frst_name;
echo Yii::$app->user->identity->last_name;
echo Yii::$app->user->identity->email;
What about using session :
$session = new \yii\web\Session;
$session->open();
$value1 = $session['name1']; // get session variable 'name1'
$value2 = $session['name2']; // get session variable 'name2'
foreach ($session as $name => $value) // traverse all session variables
$session['name3'] = $value3; // set session variable 'name3'
See docs for more details.

How to create a step by step form with Phalcon in PHP

I'm currently working on a project using the Phalcon Framework that has pages with complex forms and a lot of inputs, to break it down nicely I'm dividing the forms into a step-by-step process.
How would one validate the form on each step before going to the next step and then save the whole form on the final step?
I can't seem to find anything documented about this sort of process as it likes to validate the form in it's entirety if I use the form builder.
Simple, just create a custom methods in your form class to validate any step, and the posted data from some step save into message class and store it into session by "stepX", when posted data is not valid just set defaults from post. When valid save it into session as i describe above.
For example how i mean "controller"
<?php
class MyController extends BaseController {
public function processStep1Action(){
$form = new MyForm();
if($this->request->isPost()){//im using my custom request class
if(!$form->isValid($this->request->getPost()){
//error messages goes here
$form->setDefaultsFromRequest($this->request); // it will set the filled data
}
else {
$messageClass = new MyMessageContainer();
$messageClass->setData($this->request);//inside parse requested data into message class, or parse it as $messageClass->name = $this->request->getPost('name');
$this->session->save('step1',$messageClass); //maybe it would be want to serialize it
//then redirect to the step 2 or x
}
}
}
}
So in the next step you can access data from sessions $this->session->get('step1'); so you can in final step load all posted data and store it into DB.
I hope this helps! :)
here is my form maybe it can be helpful for you.
<?php
namespace Manager\Library\Forms\User;
use Phalcon\Forms\Form,
Phalcon\Forms\Element\Email,
Phalcon\Forms\Element\Select,
Phalcon\Forms\Element\Password,
Phalcon\Forms\Element\Check,
Phalcon\Validation\Validator\Confirmation,
Phalcon\Validation\Validator\StringLength,
Phalcon\Forms\Element\Submit,
Phalcon\Validation\Validator\PresenceOf,
Model\Group;
class AddUser extends Form {
public function initialize()
{
$email = new Email('email');
$email->addValidators(array(
new \Phalcon\Validation\Validator\Email(array(
'message' => 'Nezadali jste email nebo má nesprávny tvar(email#domena.tld).'
))
));
$this->add($email);
$this->initGroupElement();
$password = new Password('password');
$password
->addValidator(new StringLength(array('min' => 6,'messageMinimum' => 'Nezadali jste heslo nebo je příliš krátke, minimální počet znaků je 6.')))
->addValidator(new Confirmation(array('with' => 'password-again',"message" => "Zadané hesla se neshodují.")));
$this->add($password);
$repeatPassword = new Password('password-again');
$this->add($repeatPassword);
$this->initializeProfileElements();
$active = new Check('active',array('value' => 1));
$this->add($active);
$this->add( new Submit('save') );
\Phalcon\Tag::setDefault('password', '');
\Phalcon\Tag::setDefault('password-again', '');
}
public function initializeEdit(){
$email = new Email('email');
$email->addValidators(array(
new \Phalcon\Validation\Validator\Email(array(
'message' => 'Nezadali jste email nebo má nesprávny tvar(email#domena.tld).'
))
));
$this->add($email);
$this->initGroupElement();
$password = new Password('password');
$this->add($password);
$repeatPassword = new Password('password-again');
$this->add($repeatPassword);
$this->initializeProfileElements();
$active = new Check('active',array('value' => 1));
$this->add($active);
$this->add( new Submit('save') );
\Phalcon\Tag::setDefault('password', '');
\Phalcon\Tag::setDefault('password-again', '');
}
protected function initGroupElement(){
$auth = \Core\Auth::getIdentity();
$groups = new Group();
// $groups->addColumns(array('id','name'));
//set global condition about Super Admin
$groups->addFilter('id', 1,'<>');
if($auth){
//set restrictions for main groups
if((int)$auth->group_id === 1){ //super admingroup
//no filter
}
else if((int)$auth->group_id === 2){ //admin group
$groups->addFilter('id', 1,'>');
}
else if((int)$auth->group_id === 6){//Provozovatel group
$groups->addFilter('id',array(3,6,7));
$groups->addFilter('public', 1,'=',true);
}
else { // other groups
$groups->addFilter('public', 1);
}
}
$groups = $groups->findFiltered();
$groupElement = new Select('group');
foreach($groups as $group){
$groupElement->addOption(array($group->id => $group->name));
}
$this->add($groupElement);
}
protected function initializeProfileElements(){
$forename = new \Phalcon\Forms\Element\Text('forename');
$this->add($forename);
$surname = new \Phalcon\Forms\Element\Text('surname');
$this->add($surname);
$street = new \Phalcon\Forms\Element\Text('street');
$this->add($street);
$postal = new \Phalcon\Forms\Element\Text('postal');
$this->add($postal);
$city = new \Phalcon\Forms\Element\Text('city');
$this->add($city);
$ic = new \Phalcon\Forms\Element\Text('ic');
$this->add($ic);
$dic = new \Phalcon\Forms\Element\Text('dic');
$this->add($dic);
}
public function setDefault($fieldName,$value){
\Phalcon\Tag::setDefault($fieldName, $value);
}
public function setDefaults($object){
if($object instanceof \Model\User){
$this->setDefaultsFromObject($object);
}
else if($object instanceof \Phalcon\Http\Request){
$this->setDefaultsFromRequest($object);
}
}
protected function setDefaultsFromObject(\Model\User $user){
$profile = $user->getRelated('\Model\Profile');
\Phalcon\Tag::setDefaults(array(
'email' => $user->email,
'group' => $user->group_id,
'active' => $user->active,
'forename' => $profile->forename,
'surname' => $profile->surname,
'street' => $profile->street,
'city' => $profile->city,
'postal' => $profile->postal,
'ic' => $profile->IC,
'dic' => $profile->DIC
));
}
protected function setDefaultsFromRequest(\Phalcon\Http\Request $request){
\Phalcon\Tag::setDefaults(array(
'email' => $request->getPost('email'),
'group' => $request->getPost('group'),
'active' => $request->getPost('active')
));
\Phalcon\Tag::setDefaults(array(
'forename' => $request->getPost('forename'),
'surname' => $request->getPost('surname'),
'street' => $request->getPost('street'),
'city' => $request->getPost('city'),
'postal' => $request->getPost('postal'),
'ic' => $request->getPost('ic'),
'dic' => $request->getPost('dic')
));
}
}
In addition to Kamil's answer, another option to consider is to use Javascript on the front-end to handle your multi-step form. This will add some complexity as you will need to have the javascript to handle the form steps and do preliminary validation, but it only requires a single submit where you can validate content within a single method.

why coinbase callback url not working?

i have the below code for button creation.
public function createButton($name, $price, $currency, $custom=null, $options=array(),$callback)
{
// $callback=$this->generateReceiveAddress("http://www.tgigo.com");
// print_r($callback);exit;
$params = array(
"name" => $name,
"price_string" => $price,
"price_currency_iso" => $currency,
"callback_url"=>"http://www.tgigo.com"
);
if($custom !== null) {
$params['custom'] = $custom;
}
foreach($options as $option => $value) {
$params[$option] = $value;
}
return $this->createButtonWithOptions($params);
}
public function createButtonWithOptions($options=array())
{
$response = $this->post("buttons", array( "button" => $options ));
if(!$response->success) {
return $response;
}
$returnValue = new stdClass();
$returnValue->button = $response->button;
$returnValue->embedHtml = "<div class=\"coinbase-button\" data-code=\"" . $response->button->code . "\"></div><script src=\"https://coinbase.com/assets/button.js\" type=\"text/javascript\"></script>";
$returnValue->success = true;
return $returnValue;
}
and i have the below response for above code.
{"success":true,"button":{"code":"675cda22e31b314db557f0538f8ad27e","type":"buy_now","style":"buy_now_large","text":"Pay With Bitcoin","name":"Your Order #1234","description":"1 widget at $100","custom":"my custom tracking code for this order","callback_url":"http://www.tgigo.com","price":{"cents":100000,"currency_iso":"BTC"}}}
using this code payment process completed,but not redirected to the call back url.
any one please help me.
Thanks in advance :)
The callback_url parameter is for a callback that receives a POST request behind the scenes when payment is complete. The user's browser is not redirected there. You probably want success_url.
https://coinbase.com/api/doc/1.0/buttons/create.html

Categories