Currently I have used JavaScript to display an alert to notify that the execution was successful, merely for testing purposes. How can I do that in PHP object-oriented style?
I've tried:
public $msg='May the force be with you.';
$this->msg = new msg();
...but result was a white blank page. JavaScript piece I tried works well though. Below is the complete code:
<?php
class database {
public $mysql;
private $db_host='localhost';
private $db_username='admin';
private $db_password='password';
private $db_name='db';
function __construct() {
$this->mysql = new mysqli($this->db_host, $this->db_username, $this->db_password, $this->db_name) or die (mysql_error() ); {
echo
"<script type='text/javascript'>
alert ('The Force will be with you, always.');
</script>";
}
}
function __destruct() {
$this->mysql->close();
}
}
?>
PHP is server-side, which means it runs on a machine different from the user.
Javascript is client-side, which means it runs on the user's machine.
The server should have no control over anything on the user's machine.
Therefore, an alert box from PHP is not possible. :)
You've got to stick with Javascript, which only runs client-side. That, or echo plaintext out onto the document itself.
FYI, this relationship brings up other fun questions, like, "how can Javascript talk to the server" (answer:ajax) and "can a script talk to another computer" (answer: yes, but it's not supposed to).
Try this code:
<?php
class database {
public $mysql;
private $db_host='localhost';
private $db_username='admin';
private $db_password='correcthorsebatterystaple';
private $db_name='projekt';
function __construct() {
$this->mysql = new mysqli($this->db_host, $this->db_username, $this->db_password, $this->db_name) or die (mysql_error() );
}
function pri()
{
echo
"<script type='text/javascript'>
alert ('The Force will be with you, always.');
</script>";
}
function __destruct() {
$this->mysql->close();
}
}
$msg=new database();
$msg->pri();
?>
In PHP, you can do print_r() for any variable (or var_dump()) to see the contents of an object or array, etc.
Doing this will dump the contents directly on the page source (but not as a browser popup).
Related
I was recently experimenting with a "User.class" which handles login and logout (and some other functions). Login was easy to get to work, but logout was worse, because i didnt maintain the $user - object which i had declared in the beginning. Which took me way to long to understand.
I have a button for "log out", and i wanted to use my class to "do stuff" when i logged out. One way could be to do a classic one :
if(isset($_GET["logout"])) {
//do stuff in db
session_destroy();
header("Location: index.php");
}
but since i was using class and functions in that class, i wanted to call
if(isset($_GET["logout"])) {
$user->logOut();
}
But this didnt work. As said.
I found out that i could, after login, save the object in a serialized sessionvariable.
if(isset($_GET["login"])) {
$user = new User($dbh, $_POST["uid"], $_POST["key"]);
$r = $user->login();
$_SESSION["userObj"] = serialize($user);
}
if(isset($_GET["logout"])) {
$user = unserialize($_SESSION["userObj"]);
$user->logOut();
}
And, this is working.
But i think, i am handling this quite, bad on the "User.class" page, where i have this code:
public function __sleep() {
return array("login_id", "uid");
}
public function __wakeup() {
include_once("conn.php");
global $dbh;
$this->db = $dbh;
unset($dbh);
}
As you see, i have my database connection in another file, and during __wakeup(), i need to reinitialize the database conneciton.
Question is, is this good or bad practice?
This is totally new for me... :)
I have a chat bot which save some data into db which user is sending. I want to save it to db (a slow network call) after sending response to the user.
I could do that in Python Tornado but I havent been able to do it PHP Apache.
user sends input as request -> we process it -> we send output to user as response -> then we wish to store data
class A
{
function __construct()
{
echo "Hello World";
}
function __destruct()
{
sleep(15); //I want this to happen after response is being send
}
function calc()
{
echo "Progress World";
}
}
__destruct is called upon object deletion, the object being out of scope, or normal script ending. If the script isn't terminating normally but killed, the destructor may not be called at all.
If you just want to do cleanup task at specific points and ensure them being processed use the PHP 5.5-introduced finally clause
A __destruct example from the PHP site:
<?php
class my_class {
public $error_reporting = false;
function __construct($error_reporting = false) {
$this->error_reporting = $error_reporting;
}
function __destruct() {
if($this->error_reporting === true) $this->show_report();
unset($this->error_reporting);
}
?>
See the PHP Documentation on destructors. I hope this helps.
I've looked at existing answers for my problem.
I've echo'd the value right through the process and right up until the "header('Location" instruction the values remain intact.
I don't think it's a serialization problem as suggested for similar problems...
Here are the relevant bits of the class:
class clsSetUser {
protected $UserID = 0;
public function initUser($id) {
// get user details from database
$this->setUserID($id);
// etc...
}
private function setUserID($value) { $this->UserID = $value; }
public function getUserID() { return $this->UserID; }
}
common.php:
if(unset($clsUser)) $clsUser = new clsSetUser;
login-exec.php:
$clsUser->initUser($id);
header("Location: somewhere.php");
somewhere.php:
echo $clsUser->getUserID();
// here it equals 0
any ideas? does "header" serialize everything?
This is because PHP is actually starting from a clean slate in somewhere.php.
header("Location: somewhere.php"); sends a command the browser to connect to a different page. In this page non of variables of the previous page are available in PHP.
You need to set the userId in the $_SESSION so that you can reload the user from the database when he visits somewhere.php.
login-exec.php
$clsUser->initUser($id);
$_SESSION['user_id'] = $id;
header("Location: somewhere.php");
somewhere.php
$clsUser->initUser($_SESSION['user_id']);
I know, globals not (;
I am new to OOP, and I'm refactoring some functions I created into classes, but I come to a problem. Some of my classes are called from the pages themselves that the users enter (example: $Link->create('page/to/go');). Since this is outside any class, there's no problem, the links get created.
But then, I have a class that attempts to login the user when created, and if the email entered is not in the database it redirects the user to the register page. Obviously, only doing header ('Location '.$Link->create('page/to/go')) does not work.
What I would do is to set the create method as static and then call it from everywhere. But I think this would be similar to using globals and I am trying to correct bad habits. So how should I do this?
Here's some of the code for the class Link, implementing a 404-detect that I explained here:
class Link
{
private function valid($check)
{
$exceptions=array("help/report", "translate"); // More pages and rules to be added
return in_array($check,$exceptions);
}
public function create($arg)
{
if (!file_exists("/path/to/".$arg) && !$this->valid($arg))
{
// Call a function to store the error in a database.
error ("404 for ".$arg);
// One way of handling it. Replace '/' for ' ' and google that string in this page.
$arg=str_replace("/","%20",$arg);
return "https://www.google.com/#q=site%3A".Configuration::get('BaseUrl')."%20".$arg;
}
else
{
// If the page exists or is an exception, create the normal link.
if(empty($arg)) return Configuration::get('BaseUrl');
else return Configuration::get('BaseUrl').$arg;
}
}
}
As you can see in the code, when I implement error() into a class I will have a similar problem.
One option I just thought is that I might want to return an error and parse it from outside the __construct() of the User class. But it only works with this, as it's a yes/not, and I don't think making a error code up is proper for other cases.
So, what is your suggestion for passing properties and methods from one classes to others? Is it okay to use static for this context?
EDIT. The difficulty of my question it's that, almost all book, tutorial, page etc I've seen talks about how to create a SINGLE class. I haven't seen any explaining deeply how classes should talk to each other.
EDIT 2. As requested in the comments, here goes some more code. The user accesses his courses entering only the email (getting a level 1), while the user can only edit his settings if he gets a level 2 in the settings page. Not finished as I'll put some more methods.
class User
{
private $Email;
private $Name;
public function __construct()
{
if (!empty($_POST['logout'])) session_destroy();
else if ( !empty($_POST['email']) )
{
$this->loginEmail($_POST['email']);
}
else if ( $_SESSION['level'] == 1 )
{
if (!empty($_POST['password']))
{
$this->loginFull($_SESSION['email'],$_POST['password']);
}
else
{
$this->loginEmail($_SESSION['email']);
}
}
else if ( $_SESSION['level'] == 2 )
{
$this->loginFull($_SESSION['email'],$_SESSION['pass']);
}
else session_destroy();
}
private function loginEmail($Email)
{
$sql=mysql_query("SELECT * FROM users WHERE email='".mysql_real_escape_string($Email)."'"); //Retrieve the entries from the database
$row=mysql_fetch_assoc($sql);
if(mysql_num_rows($sql)==1)
{
$this->getData($row);
$_SESSION['level']=1;
}
else header ('Location: http://example.org/new/student/');
}
private function loginFull($Email,$Pass)
{
$sql=mysql_query("SELECT * FROM users WHERE email='".mysql_real_escape_string($Email)."' AND pass='".md5($Pass)."'"); //Retrieve the entries from the database
$row=mysql_fetch_assoc($sql);
if(mysql_num_rows($sql)==1)
{
$this->getData($row);
$_SESSION['pass']=$Pass;
$_SESSION['level']=2;
}
else $this->loginEmail($Email);
}
private function getData($row)
{
$_SESSION['email']=$row['email'];
$this->Email=$row['email'];
$this->Name=$row['name'];
}
public function get($Var)
{
return $this->$Var;
}
}
And now the class Error. As you can see, I already performed some DI without even knowing about it here.
class Error
{
private $Page;
private $Language;
private $User;
public function __construct($Page,$Language,$User="None")
{
$this->Page=$Page;
$this->Language=$Language;
$this->User=$User;
if (!empty($_REQUEST['banner']))
$this->Banner=$_REQUEST['banner'];
}
public function add($Kind)
{
if (!mysql_query("INSERT INTO error (kind, page, lang, user, version, date) VALUES ('".mysql_real_escape_string($Kind)."', '".mysql_real_escape_string($this->Page)."', '".mysql_real_escape_string($this->Language)."', '".mysql_real_escape_string($this->User)."', '".Configuration::get('Version')."',NOW() )"))
mail(Configuration::get('ErrorEmail'), "Error '".$Kind."' that couldn't be stored.",
"Full url: ".$FullUrl."\n Language: ".$this->Language->Lang."\n User: ".$Identif."\n Version: ".$Version); // Inform of the error by email
}
}
Create instance of Link class and pass it to where it is needed (using setter or constructor).
Definitelly read something abou DI (Dependency Injection) and then DI Containers.
Nice introduction in Nette Framework - Dependency Injection
Singletons and Static aren't a good choice. In the end everything falls onto the globals problem.
You should inject your link helper into the classes by constructor or setter (DI as #jasir said).
If you'll redirect the user, you can also inject an redirector helper:
$redirector->redirect('controller','action', array('my','params'));
Hint: this is bad too Configuration::get(). Inject the config instead.
And always remember: Don't look for things!
I've been working on a website, and currently at the stage of login/session handling.
I want to know what is a better design in your opinion. (this website will be available to the public, so it should be user-friendly too).
P.S. sorry if this is not the correct php 'conventions', I am used to c/c++ programming.
Design #1:
define("LOGGED_IN", false);
define("USERNAME", "Guest");
define("PASSWORD", "");
define("PLAYER_ID", -1);
...
if (!LOGGED_IN) {
header("Location: login.php");
} else {
...
}
...
if ({condition for successful login}) {
define("LOGGED_IN", true);
define("USERNAME", "AJ");
define("PASSWORD", "nottellingu");
define("PLAYER_ID", 1);
}
...
printf("Hi, %s. Have a nice day.", USERNAME);
Design #2:
class user {
private $id;
private $logged_in;
private $username;
private $password;
public function __construct($id, $username, $password, $logged_in = false) {
$this->id = $id;
... blablabla
}
public function get_id() {
return $this->id;
}
... blablabla (pretend i declared all needed functions)
}
...
if ({condition for successful login}) {
$id = get_userid($_SESSION['USERNAME']]);
$user = new user($id, $_SESSION['USERNAME'], $_SESSION['PASSWORD'], true);
}
...
printf("Hi, %s. Have a nice day.", $user->get_username());
You can give me your designs aswell.
Thanks
I think either way is okay. It really just depends on what you are trying to accomplish. If you are going to be consistently pulling user info, a class might be better. If you are going to just need a few basic things like ID and name and whether or not they are logged in, the first option is simpler and will work fine for that purpose.
There is no point to over complicating something when you can do it a simple way and be done with it.
IMO, design approach #2 is better. Not only do you get encapsulation for anything user related, but it is also modular, so you can refer to any of the attributes anywhere throughout your codebase.
You may also want to do some googling and see if there is a stand-alone user login system you can use, vs. re-inventing the wheel.