In my laravel 5.7 app I use MessageComponentInterface for chat app with a class like
<?php
namespace App\Classes\Socket;
use App\Classes\Socket\Base\BaseSocket;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class ChatSocket extends BaseSocket
{
protected $clients;
public function __construct()
{
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo '<pre>New Connection ::'.print_r($conn->resourceId,true).'</pre>';
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv= count($this->clients)-1;
echo '<pre>onMessage $msg::' . print_r( $msg, true ) ;
// var_dump($from);
dump($from);
die("-1 XXZ000");
echo '<pre>onMessage $from::' . print_r( $from, true ) ;
...
The problem is that in onMessage event I want to this message write to db table, but I can not find where to get user_id of user
who sent this message?
I tried to debug outputing values to screen with
echo '<pre>onMessage $from::' . print_r( $from, true ) ;
But I got outof memmory error, but in /etc/php/7.2/cli/php.ini I modified options:
max_execution_time = 3330
max_input_time = 240
memory_limit = 4048M
and restarted my server, but anyway I got outof memory error
using these metods:
// var_dump($from);
dump($from);
I got endless output in console and I could not catch anything...
How to debug these values ?
UPDATED # 2
I try example at
https://laravel.io/forum/01-16-2015-loading-laravels-session-using-ratchet
article, but when I tried to run it with method :
public function onMessage(ConnectionInterface $from, $msg) {
$from->session->start();
$idUser = $from->session->get(Auth::getName());
I got error :
Undefined property: Ratchet\Server\IoConnection::$session
In the mentioned article there was a comment :
(you must decrypt cookie to get the session id in Laravel 5) :
I search for this I found this
In web request context cookies are usually automatically encrypted and
decrypted by the EncryptCookies middleware. So easiest option would
be just to enable this middleware (and it's enabled by default in
Laravel).
and in my app/Http/Kernel.php there is line with EncryptCookies
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
but that is web application, but I run console app.
Can the reason of the error that I have to add EncryptCookies to some other group in app/Http/Kernel.php ?
Or why error ?
Also
In file:///etc/php/7.2/cli/php.ini
I modified
memory_limit = 8048M
and restarted apache
also I tried to check how many of memory in my script :
echo '<pre>onMessage getNiceFileSize(memory_get_usage()) ::' . print_r( $this->getNiceFileSize(memory_get_usage()) , true ) ;
it shows :19241736 ~18 MiB
error message :
Out of memory (allocated 1623195648) (tried to allocate 1600131072 bytes)
I tried to calculated and got values 1.51 GiB and 1.49 GiB...
1) why memory_get_usage returns such small value 2) Why dumping gets
1.5 GiB? That is a big value 3) Any ideas how to deal it? 4) Auth::id() returns nothing and as far I understand it would not help,
as message can be sent by some other logged user, but not currently
logged...
Thanks!
Did yo see this https://laravel.io/forum/01-16-2015-loading-laravels-session-using-ratchet article ?
It has similar example :
public function onMessage(ConnectionInterface $from, $msg) {
// start the session when the user send a message
// (refreshing it to be sure that we have access to the current state of the session)
$from->session->start();
// do what you wants with the session
// for example you can test if the user is auth and get his id back like this:
$idUser = $from->session->get(Auth::getName());
if (!isset($idUser)) {
echo "the user is not logged via an http session";
} else {
$currentUser = User::find($idUser);
}
// or you can save data to the session
$from->session->put('foo', 'bar');
// ...
// and at the end. save the session state to the store
$from->session->save();
}
Related
Laravel 6
There are 2 possible scenario:
Logged in user connect to Google account
Guest user connect to Google account (will create a new user if not exists)
Let's talk about the first scenario
In my routes/web.php, no middleware
Route::get('connect/{provider}', [ConnectController::class, 'connect'])
->name('connect');
Route::get('connect/{provider}/callback', [ConnectController::class, 'callback'])
->name('connect.callback');
In ConnectController.php
class ConnectController extends Controller
{
public function connect(Request $request, $provider)
{
$scopes = config('services.google.scopes');
// dump(auth('customer')->user()); <------- this 1 has value
return Socialite::driver($provider)
->scopes($scopes)
->redirect();
}
public function callback(Request $request, $provider)
{
$oauthUser = Socialite::driver($provider)->stateless()->user();
$user = auth('customer')->user();
debugbar()->log('callback user: ' . ($user->name ?? 'null'));
// ...
if (!auth('customer')->check()) {
debugbar()->log('user not logged in, log in now: ' . $u->name);
auth('customer')->login($u);
}
return redirect()->route('accounts');
}
Then the debugbar output is
log callback user: null
Suppose the user is logged in, and try to connect with google, but when reached the callback, the user session gone. What am I missing?
P/S: The default auth driver is admin, cannot be changed.
After a day of research, I found out that the session ID is different from before navigate out to Google, and in the callback request.
Just update config/session.php, and set to lax (originally was strict)
[
// ...
'same_site' => 'lax',
]
I have a problem with testing controllers in Laravel 4.
I have the next code:
public function getRemind()
{
$status = \Session::get('status');
$error = \Session::get('error');
$email = \Session::get('email');
return \View::make('admin/reminds/remind_form', compact('status', 'error', 'email'));
}
And I want to test if correct data passed in views by controller:
public function testGetRemind()
{
\Session::set('status', 'status');
\Session::set('error', 'error');
\Session::set('email', 'email');
$response = $this->action('GET', 'Admin\RemindersController#getRemind');
$this->assertTrue($response->isOk(), 'Get remind action is not ok');
$this->assertViewHas('status', 'status');
$this->assertViewHas('error', 'error');
$this->assertViewHas('email', 'email');
}
But this doesn't work.
Also I can't mock Session-class, because it not allowed by framework - there are a lot of errors when I try doing it.
Call Session::start() at the start of your test. When you call an URL in a test, the session is started if it has not already been started, wiping any existing data put into it.
Since v4.1.23, you can also do $this->session($arrayOfSessionData), which handles the starting of the session for you.
I am trying to dynamically set database connection credentials based on who logs into a web page. I'm pretty sure it's not working because of the $connectdb variable not being defined. Can someone please check out my code and try to get it working? Thanks!
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$connectdb="";
class Main extends CI_Controller {
function __construct() {
parent::__construct();
echo $connectdb;
$this->load->database($connectdb);
$this->load->helper('url');
$this->load->library('grocery_CRUD');
}
public function index() {
if ($_POST["username"] == "root") {
global $connectdb="default";
}
if ($_POST["username"] == "user1") {
global $connectdb="user1";
}
if ($_POST["username"] == "user2") {
global $connectdb="user2";
}
$connect = #mysql_connect("localhost", $_POST["username"], $_POST["password"]);//won't display the warning if any.
if (!$connect) {
echo 'Server error. Please try again sometime. CON';
} else {
print("Employees");
echo "<br>";
print("Visitors");
}//Just an example to ensure that we get into the function
// LOAD LIBRARIES
}
public function employees() {
$this->grocery_crud->set_table('employees');
$output = $this->grocery_crud->render();
$this->_example_output($output);
}
public function visitors() {
$this->grocery_crud->set_table('visitors');
$output = $this->grocery_crud->render();
$this->_example_output($output);
}
function _example_output($output = null) {
$this->load->view('our_template.php',$output);
}
}
A quick read of THE MANUAL will show you it's pretty easy to have multiple database connections. You define the connection parameters in your database.php config file then call the database with the group name.
if($user == 'someguise'){
$this->load->database('guiseDB');
}
HTH
For something as important as this i would strongly suggest running the form input through CI form validation first. You really should be validating and doing things like limit the number of characters, make sure its letters only, trim whitespace and XSS cleaning - all before you do anything else. (this helps your user as well)
then to get the value from the form - do something like this
$username = $this->input->post( 'username', TRUE ) ;
and work with the one variable $username. the TRUE XSS cleans the value, and then instead of repeating
$_POST["username"] ==
over and over and over, you are just checking $username. also makes the code easier to read. if you need $username in different methods just use:
$this->username = $this->input->post( 'username', TRUE ) ;
and then $this->username will work in any method in the class.
finally consider having a table of users or config list -- and then use a different value to call your database. in other words maybe they log in with the user name: "root" but then its a different name like global $connectdb = "rootadmin"
set_flashdata is not working directly after redirect with only one redirect.
I am using one controller in this process - Profilers' Controller. It handles the member confirmation process and also displays the login page on the redirect. The process is as follows:
this session set_flashdata ('topic', 'newmember')
redirect ('login')
route ['login'] = 'profilers/signIn'
topic = $this session flashdata ('topic')
I have turned off all database session configuration for cleaner debugging and even though session library is turned on in configs, I have started calling it anyways which doesn't seem to work either.
Here is my code. As you can see, I am sending path info to a log file path.log:
in controller Profilers, function confirmMember:
public function confirmMember()
{
//use_ssl();
$this->form_validation->set_rules('handle', 'Unique Member Name', 'trim|xss_clean|required|min_length[5]|max_length[30]');
$this->form_validation->set_rules('confirmation', 'Confirmation Code', 'trim|xss_clean|required|min_length[20]|max_length[20]|alpha_numeric');
if ($this->form_validation->run() === FALSE) {echo "here";exit;
$data['handle']=$this->input->post('handle');
$data['confirmation']=$this->input->post('confirmation');
$this->load->view('signing/defaults/header',$data);
$this->load->view('defaults/heading',$data);
$this->load->view('defaults/banner');
$this->load->view('defaults/banner_right');
$this->load->view('member/temp/index',$data);
$this->load->view('defaults/footer',$data);
} else {
$post = $this->input->post(NULL,TRUE);
$data['member'] = $this->Signing_model->model_confirmMember($post);
if ($data['member']['confirmed']!==FALSE) {
/* PATH CHECK */
error_log("member confirmation not false\n",3, LOG_DIR.'path.log');
unset($post);
$this->session->sess_destroy();
$this->session->set_flashdata('topic', 'newmember');
// $this->session->keep_flashdata('topic');
redirect('login','refresh');
} else {
/* PATH CHECK */
error_log("member confirmation IS FALSE\n",3, LOG_DIR.'path.log');
$this->load->view('member/temp/index',$data);
}
My log file shows that the path is using the correct path and showing "member confirmation not false".
I have tried with keep_flash data on (which I assumed wouldn't work since there are no other redirects) and off.
I have also tried redirect without 'refresh'.
In config/routes.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$route['join'] = 'profilers/joinUp';
$route['login'] = 'profilers/signIn';
...
Login page uses Profilers Controller, signIn function as show above:
public function signIn()
{
$topic = $this->session->flashdata('topic');
if (isset($topic)) {
$message = "topic is set. topic = ".$topic."\n";
if ($topic!==FALSE) {
error_log("flash var topic is not false\n", 3, LOG_DIR.'path.log');
} else {
error_log("flash var topic is FALSE\n", 3, LOG_DIR.'path.log');
}
} else {
$message = "topic is NOT set\n";
}
error_log($message,3,LOG_DIR.'path.log');
exit;
...
...
}
log file is showing that topic is set but is false.
"flash var topic is FALSE"
"topic is set. topic = "
Of course topic var not set since it is FALSE.
As you can see, I have moved the get flash data function to the beginning of my controller function to bypass anything that may be corrupting data.
You may need to start the session again after you have destroyed it.
Try adding this after your call to sess_destory():
$this->session->sess_create()
Alternatively you could avoid destroying the session, and unset() the values you wish to get rid of.
I'm looking for a way to catch all the database errors (if and when they occur) and sent an error report my email. For regular php error I extended the CI_Exceptions class and added my email sending code in addition to logging. But the database errors don't go trough CI_Exceptions but instead are logged directly from CI_DB_Driver->query() and I don't want to modify any file in the System folder.
Also I don't want to write logging code around every query the app does.
I'd be tempted to extend CI_Exceptions show_error method to catch any errors passed with the 'error_db' template rather than hunting through the db driver.
As you've already extended CI_Exceptions with email code this would seem like the best practice.
function show_error($heading, $message, $template = 'error_general', $status_code = 500)
{
set_status_header($status_code);
$message = '<p>'.implode('</p><p>', ( ! is_array($message)) ? array($message) : $message).'</p>';
if ($template == 'error_db')
{
// do email send here with $message
}
if (ob_get_level() > $this->ob_level + 1)
{
ob_end_flush();
}
ob_start();
include(APPPATH.'errors/'.$template.'.php');
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}