CodeIgniter Unset A Signle Session Item In An Multidimensional Array - codeigniter

On my User.php library in my login function I create admin sessions by
$create_session = array(
'is_logged' => true,
'user_id' => $row->user_id
);
$this->CI->session->set_userdata('admin', $create_session);
The issue is when I try to unset admin session data individually it does not unset the session I select.
Var Dump:
Array
(
[__ci_last_regenerate] => 1449906266
[admin] => Array
(
[is_logged] => 1
[user_id] => 1
)
)
Logout function on library:
Does not Unset: Preferred Way
public function logout() {
$user_data = $this->CI->session->userdata('admin');
unset($user_data['is_logged']);
unset($user_data['user_id']);
}
But when I use this way below it works
public function logout() {
$this->CI->session->unset_userdata('admin');
}
For some reason will not let me unset session data individually from an array in sessions.
Question How am I able to unset codeigniter session data individually that are in my admin session array?
Full User.php library
<?php
class User {
private $user_id;
private $username;
public function __construct() {
$this->CI =& get_instance();
$this->CI->load->library('session');
}
public function login() {
if ($this->validate_password() == true) {
$this->CI->db->select('*');
$this->CI->db->from($this->CI->db->dbprefix . 'user');
$this->CI->db->where('username', $this->CI->input->post('username'));
$query = $this->CI->db->get();
if ($query->num_rows() > 0) {
$row = $query->row();
$create_session = array(
'is_logged' => true,
'user_id' => $row->user_id
);
$this->CI->session->set_userdata('admin', $create_session);
$this->user_id = $row->user_id;
$this->user_group_id = $row->user_group_id;
$this->username = $row->username;
return true;
} else {
return false;
}
}
}
public function is_logged() {
$get_session = $this->CI->session->userdata('admin');
return $get_session['is_logged'];
}
public function logout() {
$user_data = $this->CI->session->userdata('admin');
unset($user_data['is_logged']);
unset($user_data['user_id']);
}
public function validate_password() {
if (password_verify($this->CI->input->post('password'), $this->stored_hash())) {
return true;
} else {
return false;
}
}
public function stored_hash() {
$this->CI->db->where('username', $this->CI->input->post('username'));
$query = $this->CI->db->get($this->CI->db->dbprefix . 'user');
if ($query->num_rows() > 0) {
$row = $query->row();
return $row->password;
} else {
return FALSE;
}
}
}
Note:
I have two lots of sessions one admin for back end and catalog for front end that's why in array.

Using unset() by itself will not remove the values from the CodeIgniter session. You would need to save those changes to the session using $this->CI->session->userdata('admin', $user_data) again.
For example:
<?php
$user_data = $this->CI->session->userdata('admin');
print_r($user_data);
// Shows: Array ( [is_logged] => 1 [user_id] => 123 )
unset($user_data['is_logged']);
unset($user_data['user_id']);
print_r($user_data);
// Shows: Array ( )
// Check what values are saved in the session:
print_r($this->CI->session->userdata('admin'));
// Shows: Array ( [is_logged] => 1 [user_id] => 123 )
// Save your changes to the session
$this->CI->session->set_userdata('admin', $user_data);
// Check what values are saved in the session (now that we've updated the session)
print_r($this->CI->session->userdata('admin'));
// Shows: Array ( )
So, you need to do the following steps to update arrays stored in your session:
Get values from session: $arr = userdata('userdata')
Remove value(s) from array: unset($arr['key'])
Save changes to session: set_userdata('userdata', $arr)
As a workaround, you may be able to edit the $_SESSION directly, bypassing the CodeIgniter's Session library:
unset($_SESSION['admin']['is_logged']);
unset($_SESSION['admin']['user_id']);
I wouldn't advise bypassing the Session library like this, but it might suit your purposes more than the steps I've listed above.

Thanks to #Kirk Beard for advice I have found way to use CodeIgniter session and unset individually data that is in side my admin array();
I create the admin multidimensional array session
$create_session = array(
'is_logged' => true,
'other_item' => 'something'
);
$this->session->set_userdata('admin', $create_session);
Then if you need to unset a single item in the admin array.
unset($this->session->userdata['admin']['is_logged']);
Works for me.
To get multidimensional array session.
echo $this->session->userdata['admin']['is_logged'];
Or
$userdata = $this->session->userdata('admin');
echo $userdata['user_id'];

Generate sessions as $this->CI->session->set_userdata($create_session); instead of $this->CI->session->set_userdata('admin',$create_session);
such as
$create_session = array(
'is_logged' => true,
'user_id' => $row->user_id
);
$this->CI->session->set_userdata($create_session);
Now unset by name even individually
$this->CI->session->unset_userdata('is_logged');
$this->CI->session->unset_userdata('user_id');

Related

Yii2 Activerecord not saved before redirect and shown in "view"

Yii2 framework. When I save multiple ActiveRecords in AFTER_INSERT_EVENT of another ActiveRecord, the values in the database is not updated fast enough, so old values are shown when redirect to viewing the data.
To be more specific: Standard XAMPP environment with PHP 7.2.9. I have made a trait to make it easy to have extra attributes with history in model (either existing attributes or new attributes). The trait is used on ActiveRecord.
Notice the sleep(5) in function TL_save. This handled the problem, but it is not the correct solution. How do I ensure all is updated before it is read again? I want to avoid use locks on the row as that would require alteration of a table before it can be used. Is there a way around it? Transactions - I have tried it but perhaps not correct as it had no effect. A reload of the view page also solves the problem, but again: not very classy :-)
Also: Should I share this code on GitHub? I have not done so before and are not quite sure if it would be of any value to others really.
trait TimelineTrait
{
private $timelineConfig;
public function timelineInit($config)
{
$std = [
'attributes' => [], // required
'_oldAttributes'=>[],
'datetime'=> date('Y-m-d H:i:s'),
'validationRule'=>'safe',
'table'=>$this->tableName(),
'onlyDirty'=>true, // using !=, not !==
'events'=>[
self::EVENT_AFTER_INSERT=>[$this, 'TL_EventAfterInsert'],
self::EVENT_AFTER_UPDATE=>[$this, 'TL_EventAfterUpdate'],
self::EVENT_AFTER_FIND=>[$this, 'TL_EventAfterFind'],
self::EVENT_AFTER_DELETE=>[$this, 'TL_EventAfterDelete'],
],
'TimelineClass'=>Timeline::class,
/*
Must have the following attributes
id integer primary key auto increment not null,
table varchar(64) not null,
table_id integer not null,
attribute varchar(64) not null,
datetime datetime not null
value text (can be null)
*/
];
$this->timelineConfig = array_replace_recursive($std, $config);
foreach($this->timelineConfig["events"]??[] as $trigger=>$handler)
$this->on($trigger, $handler);
}
public function __get($attr)
{
$cfg = &$this->timelineConfig;
if (in_array($attr, array_keys($cfg["attributes"])))
return $cfg["attributes"][$attr];
else
return parent::__get($attr);
}
public function __set($attr, $val)
{
$cfg = &$this->timelineConfig;
if (in_array($attr, array_keys($cfg["attributes"]))) {
$cfg["attributes"][$attr] = $val;
} else
parent::__set($attr, $val);
}
public function attributes()
{
return array_merge(parent::attributes(), $this->timelineConfig["attributes"]);
}
public function rules()
{
$temp = parent::rules();
$temp[] = [array_keys($this->timelineConfig["attributes"]), $this->timelineConfig["validationRule"]];
return $temp;
}
public function TL_EventAfterInsert($event)
{
$this->TL_save($event, true);
}
public function TL_EventAfterUpdate($event)
{
$this->TL_save($event, false);
}
private function TL_save($event, $insert)
{
$cfg = &$this->timelineConfig;
if ($cfg["onlyDirty"])
$cfg["_oldAttributes"] = $this->TL_attributesOnTime();
foreach($cfg["attributes"] as $attr=>$val) {
$a = [
'table'=>$cfg["table"],
'table_id'=>$this->id,
'attribute'=>$attr,
'datetime'=>$cfg["datetime"],
];
if ($insert)
$model=null;
else
$model = Timeline::find()->where($a)->one();
$isNew = empty($model); // this exact attribute does not exist on timeline already
if ($isNew)
$model = new $cfg["TimelineClass"]($a);
$model->value = $val;
if (!$cfg["onlyDirty"]
|| $cfg["onlyDirty"] && $model->value!=($cfg["_oldAttributes"][$attr]??\uniqid('force_true'))) {
$ok = $model->save();
if (!$ok) $this->addErrors($attr, $model->getErrorSummary());
}
}
sleep(5);
}
public function TL_EventAfterFind($event)
{
$cfg = &$this->timelineConfig;
$data = $this->TL_attributesOnTime();
foreach($data as $attr=>$val)
$cfg["attributes"][$attr] = $val;
$cfg["_oldAttributes"] = $cfg["attributes"];
}
private function TL_attributesOnTime()
{
$cfg = &$this->timelineConfig;
$timelineTable = $cfg["TimelineClass"]::tableName();
$sql = "SELECT t1.* FROM $timelineTable AS t1
LEFT JOIN (SELECT * FROM $timelineTable WHERE `table`=:table AND table_id=:table_id AND datetime<=:datetime) AS t2
ON (t1.table=t2.table and t1.table_id=t2.table_id and t1.datetime<t2.datetime AND t1.attribute=t2.attribute)
WHERE t2.id IS NULL AND t1.datetime<:datetime AND t1.table=:table AND t1.table_id=:table_id
";
$params = [
'table'=>$cfg["table"],
'table_id'=>$this->id,
':datetime'=>$cfg["datetime"],
];
$data = \Yii::$app->db->createCommand($sql,$params)->queryAll();
$data = ArrayHelper::map($data,'attribute','value');
return $data;
}
public function TL_EventAFterDelete($event)
{
$cfg = &$this->timelineConfig;
$cfg["TimelineClass"]::deleteAll([
'table'=>$cfg["table"],
'table_id'=>$event->sender->id
]);
}
}
Example of it's use:
<?php
namespace app\models;
class KeyTime extends Key
{
use \app\behaviors\TimelineTrait;
public function init()
{
parent::init();
$this->timelineInit([
'attributes'=>[
// default values for attributes
'keyid'=>'historic id', // this is existing attribute in Key model
'label'=>'mylabel', // label and color does not exist in Key model
'color'=>'red',
],
]);
}
}
The actionUpdate
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
]);
}
After many "flashes" with microtime(true) on, I found the reason it worked sometimes with sleep(1).
The answer is in TL_attributesOnTime. the last line in $sql was
WHERE t2.id IS NULL AND t1.datetime<:datetime AND t1.table=:table AND t1.table_id=:table_id
…but it should be…
WHERE t2.id IS NULL AND t1.datetime<=:datetime AND t1.table=:table AND t1.table_id=:table_id
Notice the < is changed to <= Otherwise when the record was saved in the same second as it was populated it would not be included.
Hope it can help somebody else.

CodeIgniter 3 code does not add data to database into 2 different tables (user_info & phone_info)

The problem is when I entered a new name no data is added. A similar thing happen when I entered an already existing name. Still, no data is added to the database. I am still new to CodeIgniter and not entirely sure my query builder inside the model is correct or not.
In the Model, I check if the name already exists insert data only into the phone_info table. IF name does not exist I insert data into user_info and phone_info.
Controller:
public function addData()
{
$name = $this->input->post('name');
$contact_num = $this->input->post('contact_num');
if($name == '') {
$result['message'] = "Please enter contact name";
} elseif($contact_num == '') {
$result['message'] = "Please enter contact number";
} else {
$result['message'] = "";
$data = array(
'name' => $name,
'contact_num' => $contact_num
);
$this->m->addData($data);
}
echo json_encode($result);
}
Model:
public function addData($data)
{
if(mysqli_num_rows($data['name']) > 0) {
$user = $this->db->get_where('user_info', array('name' => $data['name']))->result_array();
$user_id = $user['id'];
$phone_info = array(
'contact_num' => $data['contact_num'],
'user_id' => $user_id
);
$this->db->insert('phone_info',$phone_info);
} else {
$user_info = array(
'name' => $data['name']
);
$this->db->insert('user_info', $user_info);
$user = $this->db->get_where('user_info', array('name' => $data['name']))->result_array();
$user_id = $user['id'];
$phone_info = array(
'contact_num' => $data['contact_num'],
'user_id' => $user_id
);
$this->db->insert('phone_info', $phone_info);
}
}
DB-Table user_info:
DB-Table phone_info:
Extend and change your model to this:
public function findByTitle($name)
{
$this->db->where('name', $name);
return $this->result();
}
public function addData($data)
{
if(count($this->findByTitle($data['name'])) > 0) {
//.. your code
} else {
//.. your code
}
}
Explanation:
This:
if(mysqli_num_rows($data['name']) > 0)
..is not working to find database entries by name. To do this you can use codeigniters built in model functions and benefit from the MVC Pattern features, that CodeIgniter comes with.
I wrapped the actual findByName in a function so you can adapt this to other logic and use it elswehere later on. This function uses the query() method.
Read more about CodeIgniters Model Queries in the documentation.
Sidenote: mysqli_num_rows is used to iterate find results recieved by mysqli_query. This is very basic sql querying and you do not need that in a MVC-Framework like CodeIgniter. If you every appear to need write a manual sql-query, even then you should use CodeIgniters RawQuery methods.

With StripeClient I got error No API key provided

in my Laravel 8 / with stripe/stripe-php": "^7.75" I try to connect and create account on stripe side
and got error :
No API key provided. Set your API key when constructing the StripeClient instance, or provide it on a per-request basis using the `api_key` key in the $opts argument.
with code:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Session;
use Stripe;
use Stripe\StripeClient;
use App\Http\Controllers\Controller;
use Illuminate\Database\DatabaseManager;
use App\Models\Settings;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use App\Models\User;
use App\Models\StripeToken;
class SellerController extends Controller
{
protected StripeClient $stripeClient;
protected DatabaseManager $databaseManager;
public function __construct(StripeClient $stripeClient, DatabaseManager $databaseManager)
{
\Log::info(varDump($stripeClient, ' -1 SellerController ::'));
$this->stripeClient = $stripeClient;
$this->databaseManager = $databaseManager;
}
public function showProfile($id)
{
\Log::info('-1 showProfile $id ::' . print_r($id, true));
$seller = User::find($id);
if (!$seller) {
abort(404);
}
return view('market.seller', [
'seller' => $seller,
'balance' => null
]); // /_wwwroot/lar/tAdsBack/resources/views/admin/stripe/stripe.blade.php
} // public function showProfile($id)
public function redirectToStripe($id)
{
\Log::info('-1 redirectToStripe $id ::' . print_r($id, true));
$seller = User::find($id);
if (!$seller) {
abort(404);
}
$appEnv = strtolower(config('app.env'));
if ($appEnv == 'local' or $appEnv == 'dev') {
\Log::info('-1 config(app.STRIPE_TEST_KEY)::' . print_r(config('app.STRIPE_TEST_KEY'), true));
\Stripe\Stripe::setApiKey(config('app.STRIPE_TEST_KEY')); // LOOKS LIKE THAT IS NOT APPLIED
$this->stripeClient->apiKey = config('app.STRIPE_TEST_KEY'); // THIS DOES NOT HELP
$this->stripeClient->api_key = config('app.STRIPE_TEST_KEY'); // THIS DOES NOT HELP
}
if ($appEnv == 'production') {
\Stripe\Stripe::setApiKey(config('app.STRIPE_LIVE_KEY'));
$this->stripeClient->opts['api_key'] = config('app.STRIPE_LIVE_KEY');
}
if (!$seller->completed_stripe_onboarding) { // Complete onboarding process
$str = \Str::random();
$stripeToken = new StripeToken();
$stripeToken->token = $str;
$stripeToken->seller_id = $id;
$stripeToken->save();
if (empty($seller->stripe_connect_id)) { // if has no stripe account
// // Create a new Stripe Connect Account object.
\Log::info('-1 $$this->stripeClient ::' . print_r($this->stripeClient, true));
Checking log I see :
[2021-03-22 05:40:30] local.INFO: -1 $$this->stripeClient ::Stripe\StripeClient Object
(
[coreServiceFactory:Stripe\StripeClient:private] =>
[config:Stripe\BaseStripeClient:private] => Array
(
[api_key] =>
[client_id] =>
[stripe_account] =>
[stripe_version] =>
[api_base] => https://api.stripe.com
[connect_base] => https://connect.stripe.com
[files_base] => https://files.stripe.com
)
[defaultOpts:Stripe\BaseStripeClient:private] => Stripe\Util\RequestOptions Object
(
[apiKey] =>
[headers] => Array
(
[Stripe-Account] =>
[Stripe-Version] =>
)
[apiBase] =>
)
[api_key] => sk_test_NNNNNN
How to fix this error ?
I suppose I need to set api_key in some other way, not
$this->stripeClient->apiKey = config('app.STRIPE_TEST_KEY'); // THIS DOES NOT HELP
$this->stripeClient->api_key = config('app.STRIPE_TEST_KEY'); // THIS DOES NOT HELP
but how?
Thanks!
Before using stripe/stripe-php directly, check out Laravel Cashier.
https://laravel.com/docs/8.x/billing

Symfony3 error changing DateTime on entity with Ajax

I want to change the date of a doctrine entity but the change is not saved.
With ajax a call this function:
public function relancerTicketAction(Request $request, $id)
{
if (!$this->get('session')->get('compte'))
return $this->redirect($this->generateUrl('accueil'));
$isAjax = $request->isXMLHttpRequest();
if ($isAjax)
{
$ticket = $this->getDoctrine()->getManager()->getRepository('CommonBundle:Ticket')->find($id);
$ticket->setDateButoire($ticket->getDateButoire()->modify('+7 day'));
$this->getDoctrine()->getManager()->flush();
$response = array("code" => 100, "success" => true, 'date' => $ticket->getDateButoire()->format('d-m-Y'));
return new Response(json_encode($response));
}
$response = array("code" => 0, "success" => false);
return new Response(json_encode($response));
}
When I alert the result I get the right new value, but after reload there is no change saved.
This function called in the same conditions works:
public function traiterTicketAction(Request $request, $id)
{
if (!$this->get('session')->get('compte'))
return $this->redirect($this->generateUrl('accueil'));
$isAjax = $request->isXMLHttpRequest();
if ($isAjax)
{
$compte = $this->getDoctrine()->getManager()->getRepository('CommonBundle:Compte')->find($this->get('session')->get('compte')->getId());
$ticket = $this->getDoctrine()->getManager()->getRepository('CommonBundle:Ticket')->find($id);
$ticket->addDestinataire($compte);
$this->getDoctrine()->getManager()->flush();
$response = array("code" => 100, "success" => true);
return new Response(json_encode($response));
}
$response = array("code" => 0, "success" => false);
return new Response(json_encode($response));
}
see the docs
When calling EntityManager#flush() Doctrine computes the changesets of
all the currently managed entities and saves the differences to the
database. In case of object properties (#Column(type=”datetime”) or
#Column(type=”object”)) these comparisons are always made BY
REFERENCE. That means the following change will NOT be saved into the
database:
/** #Entity */
class Article
{
/** #Column(type="datetime") */
private $updated;
public function setUpdated()
{
// will NOT be saved in the database
$this->updated->modify("now");
}
}
So, in your case I suggest to clone dateButoire, like this
$ticket = $this->getDoctrine()->getManager()->getRepository('CommonBundle:Ticket')->find($id);
$newDateButoire = clone $ticket->getDateButoire();
$ticket->setDateButoire($newDateButoire->modify('+7 day'));
$this->getDoctrine()->getManager()->flush();

Codeigniter - Trying to count articles view

Im working with codeigniter and have a controller and 3 model functions to read, insert and update a column of table.
i want to get count of view from db and update it per each view!
but after the update an extra row added to table! with zero value for content_id.
please check once!
this is my controller:
public function daily_report($id="")
{
$counter=$this->home_model->counter($id);
if($counter)
{
$view=$this->home_model->counter($id)->row()->view;
$views=$view+1;
$this->home_model->update_counter($views,$id);
}
else{
$views=1;
$this->home_model->set_counter($views,$id);
}
}
This is the model functions:
public function counter($id)
{
$code=$id;
$lang=$this->session->userdata('lang');
$data = $this->db
->select('view')
->from('tbl_views')
->where("content_id",$code)
->where("language",$lang)
->get();
if ($data->num_rows() > 0) {
return $data;
}else{
return false;
}
}
public function set_counter($views,$id)
{
$data = array(
'content_id' => $id ,
'view' => $views,
'language'=>$this->session->userdata('lang')
);
$this->db->insert('tbl_views', $data);
}
public function update_counter($views,$id)
{
$data = array(
'view' => $views,
);
$this->db->where('content_id', $id);
$this->db->update('tbl_views', $data);
}

Resources