473,387 Members | 1,483 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Help with OOP class and its members

348 100+
Hello,

I have a very small login script that I feel is kind of a mess. I would like to clean it up and do it the correct way. My script is posted below. I would like to have some help in understanding what members, if any I should declare.

[PHP]class Login
{
function Login($account,$operator,$password)
{
}
function getUser()
{
ob_start();
if(isset($account) && ($operator) && ($password))
{
$password = md5($password);
require_once("database.php");
$db = new Database();
$result = $db->query("");
$count = $db->count();
if ($count == 1)
{
foreach($result as $key)
{
$level = $key['level'];
$name = $key['last_name'];
}
$_SESSION['name'] = $name;
$_SESSION['user'] = $user;
$_SESSION['level'] = $level;
header("location:index.php?id=6");
}
else
{
header("location:index.php?id=1");
}
}
ob_end_flush();
}
}[/PHP]
Jun 21 '08 #1
36 2633
Atli
5,058 Expert 4TB
I don't know if creating a class solely for login is the right move.
I would create a class that handles all user interaction, and add a Login method to that class.

I would also not create a Database object inside the class. I would create it outside it and pass it into the class through the constructor. That way you could just create one database instance and use it wherever it is needed.

It is probably not a good idea to add the header-redirect into the method itself. That would be best placed outside the class.

Consider this example:
(It's a bit long, but it would take much longer to explain this in words :P)
Expand|Select|Wrap|Line Numbers
  1. <?php
  2. class User
  3. {
  4.   /**
  5.    * Members. These will probably not fit your
  6.    * application. They are just for show.
  7.    */
  8.   public $Name;
  9.   private $_role;
  10.   private $_whateverelse;
  11.  
  12.   private $_dbLink;
  13.   private $_isLoggedIn
  14.  
  15.   /**
  16.    * Class constructor. Logs the user in automatically if the
  17.    * user info is passed
  18.    */
  19.   public function __construct(Database &$dbLink, $password=null, $name=null) 
  20.   {
  21.     // Intialize members
  22.     $this->_dbLink = $dbLink;
  23.     $this->Name = $name;
  24.     $this->_role = "Guest";
  25.     $this->_whatever = "Whatever else data you may need";
  26.     $this->_isLoggedIn = false;
  27.  
  28.     // Log in the user if the info was passed.
  29.     if($name != null && $password != null) {
  30.       $this->login($password, $name);
  31.     }
  32.   }
  33.  
  34.   /**
  35.    * Attempts to log the user in.
  36.    *
  37.    * @throws Exception
  38.    */
  39.   public function login($password, $name=null) 
  40.   {
  41.     // Use the Name member if no $name was passed in the parameter
  42.     $name = ($name == null ? $this->Name : $name);
  43.  
  44.     // Check if the parameters have valid values
  45.     if(empty($name) || empty($password)) {
  46.       throw new Exception("Can't log in. Username or password is empty.", 001);
  47.     }
  48.  
  49.     // Query for the user info
  50.     $result = $this->_dbLink->query("");
  51.     if(!$result) {
  52.       throw new Exception("Unable to log in. Database query failed.", 002);
  53.     }
  54.  
  55.     // Validate the result data
  56.     if($result->getRowCount() == 1) {
  57.       // Fetch the row and set the members.
  58.       $dbRow = $result->fetchRow();
  59.       $this->Name = $name;
  60.       $this->_role = $dbRow['UserRole'];
  61.       $this->_isLoggedIn = true;
  62.     }
  63.     else {
  64.       throw new Exception("Unable to log in. User information is incorrect.", 003);
  65.     }
  66.   }
  67.  
  68.   /**
  69.    * Read-only properties
  70.    */
  71.   public function isLoggedIn() {
  72.     return $this->_isLoggedIn;
  73.   }
  74.   public function getRole() {
  75.     return $this->_role;
  76.   }
  77.   public function getWhateverElse() {
  78.     return $this->_whateverelse;
  79.   }
  80. }
  81. ?>
  82.  
Which could be used somewhat like this:
Expand|Select|Wrap|Line Numbers
  1. <?php
  2. try {
  3.   // Create a database
  4.   require_once("database.php");
  5.   $dbLink = new Database(...);
  6.  
  7.   // Create user and login
  8.   $user = new User($dbLink, "MyPassword", "Username");
  9.  
  10.   // Determing wether the user was successfully logged in.
  11.   if($user->isLoggedIn()) {
  12.     echo "Welcome {$user->Name}. You have been logged in";
  13.   } else {
  14.     echo "You were not logged in!"; 
  15.     echo "In fact... seeing as the class throws an exception if the login fails... you should never see this message :P";
  16.   }
  17. }
  18. catch(Exception $ex) {
  19.   echo '<strong>An error has occurred:</strong><br />'. $ex->getMessage()};
  20. }
  21. ?>
  22.  
Edit:
To understand the parameters in the constructor better, you may want to check out: type hinting and passing by reference
Jun 21 '08 #2
fjm
348 100+
Wow Atli, sometimes there are no words to describe a post and this is one of them. You are at a much higher level of OOP than I am. I am totally lost now.. :)

I honestly have no idea what to do with that code. I agree, there is probably a much better way of handling my logins than that script I posted but I am more lost now than I was before. haha...

I suppose I can play around with the code you posted but I can almost guarentee you that I will hack it up so bad that it won't be worth much afterward.

All of your help was not in vain tho. I got other bits and pieces of useful information that I can use. I always wondered if using an object within a method was the right way to go and I see that it is not. Also, using header() inside of a method.
Jun 22 '08 #3
fjm
348 100+
Ok Alti, I am up for the challange. I am going to take the user class and see what I can do with it. I will post back here when I have something useful or when I need some guidance, whichever occurs first :)


Thanks again!
Jun 22 '08 #4
Markus
6,050 Expert 4TB
I wonder why type hinting with 'int' and 'string' isn't supported?
Jun 22 '08 #5
fjm
348 100+
Ok Atli,

What I figured I would do is take the code you provided and firstly create tab indentations so that it becomes more readable to me, which makes it look less dawnting to me. :)

Then I figured I would take the constructor and its members and focus on just that part. I have included the actual properties/members? in the constructor for you to look at. I also wanted to take this code section by section because I have questions about the way you did a few things that are not clear to me. So, here is the code.

[PHP]
public $Account;
public $Operator;
private $Password;
private $_dbLink;
private $_isLoggedIn

public function User(Database &$dbLink, $password=null, $name=null)
{
$this->_dbLink = $dbLink;
$this->Account = $name;
$this->Operator = null;
$this->Password = null;
$this->_isLoggedIn = false;

if($account != null && $operator != null && $password != null)
{
$this->login($account, $operator, $name);
}
}
[/PHP]
My questions are:

1. What is this? "Database &$dbLink"
2. What is the amp. sign for? I thought that was only used in php4
3. I changed __construct to User because I think that __construct was for php4 as well. Right? I mean, either way should be ok, I think.
4. I noticed that you use "_" to prepend your variables. Is there a reason for this? Just curious. :)
5. I added "Account", "Operator", "Password" as "Members". Am I correct on this?
Jun 22 '08 #6
Atli
5,058 Expert 4TB
My questions are:

1. What is this? "Database &$dbLink"
2. What is the amp. sign for? I thought that was only used in php4
3. I changed __construct to User because I think that __construct was for php4 as well. Right? I mean, either way should be ok, I think.
4. I noticed that you use "_" to prepend your variables. Is there a reason for this? Just curious. :)
5. I added "Account", "Operator", "Password" as "Members". Am I correct on this?
1. The "Database" part is what we call type hinting. It means that the $dbLink parameter must be an object based on the Database class. Anything else will cause an error.

2. The ampersand means that the $dbLink parameter will be passed by reference.
That is; rather than making a new copy of the variable and using that in the constructor, PHP passes the memory location of the original object, which will then be used instead.

3. Actually, __construct was first introduced in PHP5 and it is the preferred method. It just makes it easier to spot the constructor.
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class.
4. I do that so I can more easily spot what type of member I am using. As you see, I prefix private members and methods with a single _ char.
I encourage you to find a naming-convention you like and stick with it. It's extremely annoying when there is no rule to how members are named.

5. I can't see a reason why not. I would still encourage you to pick a naming-convention and stick to it, whether it is the one I use or something else. Your new Password member is a private member, so using my convention it should be named "_password", and the other two should start with a lowercase letter.

There are a lot of naming-conventions. I prefer the C# conventions, but the one I am using in the code I showed you is what is usually used with PHP.
Jun 22 '08 #7
Atli
5,058 Expert 4TB
I wonder why type hinting with 'int' and 'string' isn't supported?
I don't know. Even with PHP's loosely-typed syntax, these keywords are used for other purposes. I can't see why this should be allowed. The manual doesn't explain this, it just says it isn't supported.

Maybe this is something that will be fixed in PHP6?

Edit: Or not. Found this in this bug that was filed about this subject:
We will not provide typehints for primitive types as PHP has automatic
typeconversion for them Also we are not adding any checks for primitive
types since that would either slow down the compile step or would
require new keywords.
Jun 22 '08 #8
pbmods
5,821 Expert 4TB
Heya, Frank.

There's precious little I can add to Atli's comprehensive response, but I figured I'd get my 3¢ in (that's .005% of a stimulus check, you know):

Moving from procedural to object-oriented code also requires a shift in the way you look at your project.

With procedural code, you tend to think in terms of tasks and processes (e.g., login, logout, createUser, deleteUser and so on).

When you make the move to object-oriented code, you need to shift your thinking so that you are building objects that are able to do certain tasks (in this case, as Atli demonstrated, a User object that is able to login and so on).

One caveat I might as well point out (it's on the PHP 5 certification exam, by the way):

You don't need the ampersand operator when passing objects as parameters; all objects in PHP 5 are automatically passed by reference (this is not the case in PHP 4).
Jun 22 '08 #9
pbmods
5,821 Expert 4TB
Incidentally, I've never seen the '@throws' tag in the PHPDocumentor manual, nor do I remember it from my recent excursion through its source code.

Okay, NOW I'm done.

*puts nitpicking needles away*
Jun 22 '08 #10
fjm
348 100+
Hey Pbmods :) Long time no see man! I haven't seen you on this forum as much as before. Anyway, cool.. I'm glad your still around.

Thanks for the 3 cents. All the advice I get here is truly golden.

I have to say that OOP is a royal P A I N in the you know what. I can see that it requires me to think differently about how I need to lay out objects and such. Honestly, Alti is fantastic at what he teaches but I am still a noob when it pertains to OOP and my brain doesn't like it. :) I simply don't understand a lot of what is going on. I thought I understood the basics of OOP but I guess I really don't. "Members and Mutators"?? Good Lord man. :)

One good thing about procedural is that you just program.. you go.. With OOP my project has halted to an absolute standstill and I have no idea what to do. I simply do not have the knowledge.

I am going to try and sit down and read about some of the things that Alti has tried to help me with and see where that takes me.
Jun 22 '08 #11
fjm
348 100+
The "Database" part is what we call type hinting. It means that the $dbLink parameter must be an object based on the Database class. Anything else will cause an error.
Ok, thanks for your responses Atli. How would I go about using it? I mean, do I have to create the database object first in the user class? I googled it and am having a hard time understanding this.

Thanks for the explanation on the naming conventions. If it is ok with you, I will adopt your. I like it. :)

EDIT:
I found a terriffic example on passing_by_reference on phpBuilder's site. I understand it. It is a very simple concept really. :) The way I see it, I create a db object in my process script and pass it to the constructor of the user class. Am I correct?

Also, just for clarification, would I need the word "Database" as it appears in the constructor? (function User(Database &$DBLink......)

Would I be ok with just &$DBLink?
Jun 22 '08 #12
Atli
5,058 Expert 4TB
One caveat I might as well point out (it's on the PHP 5 certification exam, by the way):

You don't need the ampersand operator when passing objects as parameters; all objects in PHP 5 are automatically passed by reference (this is not the case in PHP 4).
I was under the impression that objects and variables passed without the ampersand would be passed by reference until they were modified. Then the passed object would receive it's own, separate, memory allocation, independent of the original object.

Is that wrong?

Edit:
Turns out that I am wrong. I just tested it and even without the ampersand, the passed object remains a reference to the original, no matter what I do to it.

Nice... that means I can stop adding ampersands all over the place :P

Incidentally, I've never seen the '@throws' tag in the PHPDocumentor manual, nor do I remember it from my recent excursion through its source code.
According to what I've read, it isn't supported yet. But I still tested it and found that some of the layouts in the newest build (at the time) did use it tho.
So I'm just adding it no matter what the manual says, if only to make my code... forward-compatible (I guess :P).
Jun 22 '08 #13
Atli
5,058 Expert 4TB
Also, just for clarification, would I need the word "Database" as it appears in the constructor? (function User(Database &$DBLink......)

Would I be ok with just &$DBLink?
That would work to. You could leave it out and it would work fine.

It is only used to make sure the passed variable is a certain type of object.
It's a completely optional thing, no need to bother with it if it is getting in your way.
Jun 22 '08 #14
Atli
5,058 Expert 4TB
I found a terriffic example on passing_by_reference on phpBuilder's site. I understand it. It is a very simple concept really. :) The way I see it, I create a db object in my process script and pass it to the constructor of the user class. Am I correct?
Yea that's exactly it. But now that pbmods has pointed out the fact that objects are always passed as references, we don't need the ampersand anymore.

Sorry, meant to add that to my other post. forgot :P
Jun 22 '08 #15
fjm
348 100+
Great Atli, thanks! :)

I am going to make use of the user class and post back when it is finished. If you wouldn't mind looking it over and giving me your suggestions, I would sure appriciate it.

I also saw what pbmods posted as well about passing by reference. That is good news.

Thanks,

Frank
Jun 22 '08 #16
fjm
348 100+
Atli! I got it! :)

I played with the script after reading more about OOP and going back and reading your posts. See? All of your efforts were not in vain man.

I am going to make a few more changes, put some duct tape over the big gaping holes I made in the script and then post it here for you to look at. Actually, I didn't have to do much to it. The hard part was "understanding" what went where and "why". I also took your advice and redid my db class and it is now working great too. :)

One thing I had a major problem with was stripping out the database object from the user class. I could not get that to work so I just put the object into the user class. Maybe we can go over what I am doing wrong.

I'm sure the scripts are not perfect, but I think you will see a little improvement. Thanks bro!

Frank
Jun 22 '08 #17
fjm
348 100+
In post #2 line 59 $name is initialized and it is also initialized in the constructor: $this->Name. It is duplicated. Was this a typo or an oversight?

Would it be wrong or a bad practice to initialize the variable in its own method then just call the method in the constructor?

Like:
[php]public function __construct()
{
$this->Name($value)
}[/php]

instead of:
[php]public function __construct($Name)
{
$this->Name = $name
}[/php]

Which way is better or more proper?
Jun 23 '08 #18
Atli
5,058 Expert 4TB
In post #2 line 59 $name is initialized and it is also initialized in the constructor: $this->Name. It is duplicated. Was this a typo or an oversight?
No I did that on purpose.
Consider what would happen if you were to call the login method more than once, using different user info... like:
Expand|Select|Wrap|Line Numbers
  1. $user = new User($dbLink, "pass1", "user1");
  2. echo $user->Name; // User1
  3.  
  4. $user->login("pass2", "user2");
  5. echo $user->Name; // User2
  6.  
If I didn't set the Name member in the login method, the second echo would echo the name of the first user, rather then the second.

Besides, I always initialize everything in the constructor, even if the members are set later elsewhere. It's just good practice.

Would it be wrong or a bad practice to initialize the variable in its own method then just call the method in the constructor?

Like:
[php]public function __construct()
{
$this->Name($value)
}[/php]

instead of:
[php]public function __construct($Name)
{
$this->Name = $name
}[/php]

Which way is better or more proper?
The second example would be the better way... mostly because the first would cause an error (or two) :)

I don't really get what you are trying to do in the first example. Name is a member (variable), right? Not a method.
If that is the case, calling it as a method would cause an error.
Not to mention that the $value you are passing it doesn't exist.

What you do in the second example is the preferred way. Initializing the members in the constructor, passing initial values through as parameters if needed.
Jun 23 '08 #19
fjm
348 100+
Well, here is my finished class. Is it ok?

[PHP]class User
{
public $Account;
public $Operator;
public $Company;
private $_Password;
private $_isLoggedIn;

public function __construct($Account=null, $Operator=null, $Company=null, $Password=null, $NRows)
{
if($Account != null && $Operator != null && $Password != null)
{
$this->Login($Account, $Operator, $Company, $Password, $NRows);
}
}

public function Login($Account=null, $Operator=null, $Company=null, $Password=null, $NRows)
{
if($NRows == 1)
{
if(session_is_registered("error"))
{
session_unregister("error");
}
session_register("account");
$this->Account = "$Account";
$this->Operator = "$Operator";
$this->Company = "$Company";
$this->_Password = "$Password";
$this->_isLoggedIn = true;
}
else
{
session_register("error");
header("location:index.php?id=1");
}
}

public function isLoggedIn()
{
return $this->_isLoggedIn;
}
}[/PHP]

This is from my action page:
[PHP] if(!empty($_POST['account']) && !empty($_POST['operator']) && !empty($_POST['password']))
{
$Account = $_POST['account'];
$Operator = $_POST['operator'];
$Password = $_POST['password'];
require_once("lib/classes/db.php");
$db = new Database("test");

$Account = $db->QuoteSmart($Account);
$Operator = (int) $db->QuoteSmart($Operator);
$Password = $db->QuoteSmart(sha1(md5($Password)));
$result = $db->Query("SELECT t1.login, t1.company, t2.operator, t2.passwd FROM account ........");
$NRows = $db->NRows();

$dbRow = $db->Row();
$Company = $dbRow['company'];

require_once("lib/classes/user.php");
$login = new User("$Account","$Operator","$Company","$Password" , "$NRows");

if($login->isLoggedIn())
echo "logged in";
}[/PHP]

What I did was strip out the database object from the user class and put it into the action script. Please tell me if there is a better way to do this.

"QuoteSmart is a function that I put into my db class that will handle the mysql_real_escape_string in case anyone was wondering.

One thing that I also did was to remove the try/catch exception handler because it was halting the script. I also want to ask some questions and clarify a bit before I put them back into the class.

Thanks,

Frank
Jun 23 '08 #20
fjm
348 100+
No I did that on purpose.
Consider what would happen if you were to call the login method more than once, using different user info... like:
Expand|Select|Wrap|Line Numbers
  1. $user = new User($dbLink, "pass1", "user1");
  2. echo $user->Name; // User1
  3.  
  4. $user->login("pass2", "user2");
  5. echo $user->Name; // User2
  6.  
If I didn't set the Name member in the login method, the second echo would echo the name of the first user, rather then the second.

Besides, I always initialize everything in the constructor, even if the members are set later elsewhere. It's just good practice.
Ok, this helps me greatly. I can totally see why it is important to set the member in the method. Thanks for clarifing that for me.

I don't really get what you are trying to do in the first example. Name is a member (variable), right? Not a method.
Yes Atli, your right. Forget that.. I was very tired when I wrote it and all OOP code started to look the same. :)
Jun 23 '08 #21
Atli
5,058 Expert 4TB
Hi, sorry for the wait.. been a little busy :P

You class looks fine, except for a couple of things.

The SQL query should be executed inside the method, not outside it.
Your way, you always have to manually execute some code before calling the method, which is exactly what OOP is created to prevent. It is meant to automate such repetitive tasks.

Another thing is the header function there. Ideally, classes are meant to handle specific tasks, related to a specific thing, but independent of the project. The class should not be "aware" of the "bigger picture", but only handle it's small part.
A method, like your login method, should either throw exceptions (preferably), or return a result that can be used to determine how to proceed.

If you don't want to user Exceptions, consider something like this:
Expand|Select|Wrap|Line Numbers
  1. class User {
  2.   private $_dbLink;
  3.   public function __construct($db) {
  4.     $this->_dbLink = $db;
  5.   }
  6.   public function login(...) {
  7.     $result = $this->_dbLink->query(...);
  8.     // etc...
  9.     if(/* login succeeded */) {
  10.       // Set some members
  11.       return true;
  12.     }
  13.     else {
  14.       return false;
  15.     }
  16.   }
  17. }
  18.  
Which could be used:
Expand|Select|Wrap|Line Numbers
  1. $db = new Database(...);
  2. $user = new User($db);
  3.  
  4. if($user->login(...)) {
  5.   header("Location: loginSuccess.php");
  6. }
  7. else {
  8.   header("Location: loginFailiure.php");
  9. }
  10.  
Jun 25 '08 #22
fjm
348 100+
Hi, sorry for the wait.. been a little busy :P
Thanks for sticking with me on this Atli. I appriciate it and I know how busy can be. :)

The SQL query should be executed inside the method, not outside it.
Ok, I think I may be starting to understand where I am screwing up. In my database class, in my constructor, I have the mysql_connect, then mysql_select_db and mysql_query. So, the constructor calls all 3 methods and is then set up to do the query. When you say "db_link", is that referring to the connection only? I mean, should I be only connecting to the db outside the "user" class and then inside inside the user class, calling the query? I hope that I am explaining this ok..

[PHP]
public function __construct($db) {
$this->_dbLink = $db;
[/PHP]
Is the $db here simply the connection? if it is, then that is where I am making my mistake and need to redo my database class.

Another thing is the header function
It is kind of funny, but I just went back an looked at the user class after reading this because I thought I had removed that header function before posting my final class. I can see that it is still there. In my call, I have the if($login->isLoggedIn); header(.....

The header func in the call is not even being executed because the method is doing the redirect. Thanks for pointing that out Atli.

Now, on the exceptions, I would love to pick your brain a little because I don't believe that I have been using them correctly. I basically left them in the script you gave me and figured I would test them out. All I can see is they halted the script (fatal errors) whenever a user entered their password/username incorrectly. I don't think that exceptions were meant to function like that, or were they? :confused:
Jun 25 '08 #23
Atli
5,058 Expert 4TB
Is the $db here simply the connection? if it is, then that is where I am making my mistake and need to redo my database class.
If you have a Database wrapper class that makes the connection and then waits for a query call, you can simply pass and instance of that class into your other classes.
You definitely don't want to be creating new connections for each and every object you created.

Maybe this will explain what I'm thinking:
Expand|Select|Wrap|Line Numbers
  1. // The Database wrapper class
  2. // (Kind of pointless, granted, but it's just an example)
  3. class Database {
  4.   private $this->_link;
  5.   public function __construct($host, $user, $passwd, $dbName) {
  6.     $this->_link = mysql_connect($host, $user, $passwd);
  7.     mysql_select_db($dbName, $this->_link);
  8.   }
  9.   public function query($query) {
  10.     return mysql_query($query, $this->_link);
  11.   }
  12. }
  13.  
  14. // The User class
  15. class User {
  16.   private $_dbLink;
  17.   public function __construct($db) {
  18.     // Store the passed Database object as _dbLink
  19.     $this->_dbLink = $db;
  20.   }
  21.   public function login($user, $passwd) {
  22.     // Call the query method of the Database instance that
  23.     // was passed to the constructor and stored as _dbLink
  24.     $result = $this->_dbLink->query("SELECT whatever...");
  25.     // etc...
  26.   }
  27. }
  28.  
  29. // Create an instance of the Database class
  30. $db = new Database("localhost", "usr", "pwd", "dbname");
  31.  
  32. // Create an instance of the User class
  33. // passing along the instance of the Database class
  34. // we just created.
  35. $user1 = new User($db);
  36. $user1->login("Username", "passwd");
  37.  
Jun 25 '08 #24
fjm
348 100+
Whoh whoh.. I had NO IDEA you could do this.

[PHP]$this->_dbLink->query[/PHP]
That clears up a few things for me for sure! I'm still looking over the ex. you posted.
Jun 25 '08 #25
Atli
5,058 Expert 4TB
Now, on the exceptions, I would love to pick your brain a little because I don't believe that I have been using them correctly. I basically left them in the script you gave me and figured I would test them out. All I can see is they halted the script (fatal errors) whenever a user entered their password/username incorrectly. I don't think that exceptions were meant to function like that, or were they? :confused:
Exceptions are very simple, really. Check out Exceptions in the manual. They do a pretty good job of explaining it.

In simple terms, you can throw an exception anywhere in you code, causing your code execution to stop.
If this occurs inside a "try" block, the matching "catch" block will be executed, after which the rest of the code (if any) will be executed as normally.

Consider this:
Expand|Select|Wrap|Line Numbers
  1. try {
  2.   $num1 = mt_rand(0, 5);
  3.   $num2 = mt_rand(0, 5);
  4.  
  5.   if($num2 == 0) {
  6.     throw new Exception("Can not divide by 0");
  7.   }
  8.   else {
  9.     echo "$num1 / $num2 = ". ($num1 / $num2);
  10.   }
  11. }
  12. catch(Exception $ex) {
  13.   echo "<b>Error: </b> ". $ex->getMessage();
  14. }
  15. echo "<p>Finished!</p>";
  16.  
If the second number happens to be 0, the exception will be thrown. The "try" block will catch it, and the "catch" block will be executed.
No matter what happens, the "Finished" message will be printed.

If an exception is thrown outside a try clause, there will be nothing to catch it. In that case PHP will stop with a fatal "Uncaught Exception" error.

What makes this powerful, is that Exceptions thrown within objects will be caught by any try block that encapsulates the point where it is thrown, even if that is nested withing any number of objects.

Hope that makes sense :P

Thanks for sticking with me on this Atli. I appriciate it and I know how busy can be. :)
No problem. I'm always happy to help :)
Jun 25 '08 #26
fjm
348 100+
Exceptions are very simple, really. Check out Exceptions in the manual. They do a pretty good job of explaining it.
I will read about exceptions tonight. Thank you for the link Atli.

In simple terms, you can throw an exception anywhere in you code, causing your code execution to stop.
But would I want my code to stop if a user entered his password incorrectly? I believe in your original example that was what I was seeing. My second question about exceptions is how to echo the message to the user. Would I assign the message to a session? That is how I have been handling error messages.

OK, NOW... The good stuff. :)

Ok, here is my revised user class. It looks a bit different than what I last posted:

[PHP]class User
{
public $Account;
public $Operator;
public $Company;
private $_Password;
private $_isLoggedIn;
private $_LinkID;
public function __construct($Account=null, $Operator=null, $Password=null, $LinkID)
{
$this->Account = $Account;
$this->Operator = $Operator;
$this->_Password = $Password;
$this->_LinkID = $LinkID;
if($Account != null && $Operator != null && $Password != null)
{
$this->Login($Account, $Operator, $Password, $LinkID);
}
}
public function Login($Account=null, $Operator=null, $Password=null, $LinkID)
{
$this->_LinkID = $LinkID;
$Account = $this->_LinkID->QuoteSmart($Account);
$Operator = (int) $this->_LinkID->QuoteSmart($Operator);
$Password = $this->_LinkID->QuoteSmart(sha1(md5($Password)));
$result = $this->_LinkID->Query("SELECT ...");
$NRows = $this->_LinkID->NRows();
if($NRows == 1)
{
if(isset($_SESSION['error']))
{
unset($_SESSION['error']);
}
$_SESSION["account"] = "account";
$row = $this->_LinkID->Row();
$this->Account = "".$row['login']."";
$this->Operator = "".$row['operator']."";
$this->Company = "".$row['company']."";
$this->_Password = "".$row['passwd']."";
$this->_isLoggedIn = true;
}
else
{
$_SESSION["error"] = "error";
}
}
public function isLoggedIn()
{
return $this->_isLoggedIn;
}
}[/PHP]

EDIT:
Forgot to add the call :)
[PHP] if(!empty($_POST['account']) && !empty($_POST['operator']) && !empty($_POST['password']))
{
$Account = $_POST['account'];
$Operator = $_POST['operator'];
$Password = $_POST['password'];
require_once("lib/classes/db.php");
require_once("lib/classes/user.php");
$db = new Database("test");
$login = new User("$Account","$Operator","$Password", $db);
if($login->isLoggedIn())
header("location:../hoochimama/index.php");
else
header("location:index.php?id=1");
}
else
{
header("location:index.php?id=1");
}[/PHP]
Jun 26 '08 #27
coolsti
310 100+
Maybe a minor and insiginficant point, but if I was to code this, I would not make the $password to be a member variable of the class. A user's $password is a very sensitive piece of information, and as hacker-safe as it may seem to be, I still would not wish to carry around this piece of information in memory for the script-lifetime of every user object that is instantiated.

The point is, you use $password immediately in the constructor to log the user in. So why save it as $this->password? I would just use it in the log in function but not save it in a class member variable.
Jun 26 '08 #28
Atli
5,058 Expert 4TB
That looks good. Exactly like a proper class should :)

Two things I would like to mention tho.

You pass a $linkID into your Login function and set it as the linkID member, which is also done in your constructor.
I guess it can be convenient to allow the Database object to be passed directly into the Login function, but I wouldn't recommend it.
I would remove the $linkID from the Login function, and rely on the linkID member that was initialized in the constructor instead.

You seem to encapsulate a lot of variables in unnecessary quote marks, like:
Expand|Select|Wrap|Line Numbers
  1. $login = new User("$Account","$Operator","$Password", $db);
  2. // and
  3. $this->Account = "".$row['login']."";
  4.  
You don't need to do that. You could just do:
Expand|Select|Wrap|Line Numbers
  1. $login = new User($Account,$Operator,$Password, $db);
  2. // and
  3. $this->Account = $row['login'];
  4.  
PHP will recognize them as strings either way. PHP is nothing if not good at determining variable types :)

But would I want my code to stop if a user entered his password incorrectly? I believe in your original example that was what I was seeing. My second question about exceptions is how to echo the message to the user. Would I assign the message to a session? That is how I have been handling error messages.
I tend to use exceptions for all errors, whatever they are... old C# habit :P
It probably looks strange to people new to these things.

This is how I would structure my login page, given the class I originally posted.
Maybe this will explain what I'm doing there:
Expand|Select|Wrap|Line Numbers
  1. <?php
  2. try {
  3.   // This would of course be cleaned up and validated
  4.   $userName = $_POST['Username'];
  5.   $password = $_POST['Password'];
  6.  
  7.   $dbLink = new MySQL_Database("host", "usr", "pwd", "db");
  8.   $user = new User($dbLink);
  9.  
  10.   $user->Login($userName, $password);
  11.  
  12.   header("Location: memberPage.php");
  13.   echo "<b>Welcome back $userName</b><br />";
  14.   echo "You will be redirected in 3 secs...";
  15. }
  16.  
  17. // Catch a specially made UserException.
  18. catch(UserException $ex) {
  19.   if($ex->getCode() == 003) { // The code for invalid login
  20.     echo "<b>User login failed</b>Please try again.";
  21.   }
  22.   else {
  23.     echo "<b>User error occurred:</b>". $ex->getMessage();
  24.   }
  25. }
  26.  
  27. // Catch a specially made DatabaseException
  28. catch(DatabaseException $ex) {
  29.   echo "<b>Database error occurred:</b> <pre>". $ex->getSqlError();
  30. }
  31.  
  32. // Catch all other exceptions
  33. catch(Exception $ex) {
  34.   echo "<b>An error has occurred: </b>". $ex->getMessage();
  35. }
  36. ?>
  37.  
The DatabaseException and UserException exceptions are custom made for my Database and User classes. Check out this link to see how to do that.
Jun 26 '08 #29
Atli
5,058 Expert 4TB
The point is, you use $password immediately in the constructor to log the user in. So why save it as $this->password? I would just use it in the log in function but not save it in a class member variable.
A good point. Your code doesn't really need the password for anything but logging in.
Jun 26 '08 #30
fjm
348 100+
Atli and Coolsti, you guys both make great points about the password not being carried around. I am going to remove that. Thanks. As far as the _LinkID, as I look at that today, I have absolutley no idea why I did that. Actually, I know why I put it there and raises a question..

My thoughts on putting _LinkID in the login method was because I had it here:
[PHP]public function Login($Account=null, $Operator=null, $Password=null, $LinkID)[/PHP]
I am under the impression that ANYTHING inside of the function Login() must also be initialized as $this->whatever inside of that login method.

In other words, if I had:
[PHP]public function Login($Account=null, $Operator=null, $Password=null)[/PHP]
and I referenced:
[PHP]$this->_LinkID->Query("...")[/PHP] INSIDE of the Login method
I wouldn't think it would be correct, or even work for that matter because _LinkID references nothing inside the function/method (Man, I know I am not making any sense here, sorry... This is probably why I don't understand)

Atli, remember when I asked you the other day if was a typo when you coded $this->Name twice? I saw that you had it once in the constructor and again in the method and I think you said that it was good to do that. That was why I did it.

See... most of the time I don't really know what to initialize and exactly where. That is what is really screwing me up. Another reason for me doing that was because of this:
[PHP]$this->_LinkID->NRows();[/PHP]
If I don't (initialize, not sure if that is the right word) $this->_LinkID in the login method than how will $this->_LinkID->NRows() work? There is a reference to _LinkID.

Atli, I am going to look over your exception handler and see what I can do with it. BTW: you mentioned a link but I don't see one. Did you forget to include it or is all this programming making me blind? :)
Jun 26 '08 #31
fjm
348 100+
Now, this is very interesting. I removed the password member totally because you guys are correct... I don't need it following the user around. I removed the _LinkID from the Login method and the class still works. Here is what I have. Is this really right????

[PHP] public $Account;
public $Operator;
public $Company;
private $_isLoggedIn;
private $_LinkID;

public function __construct($Account=null, $Operator=null, $Password=null, $LinkID)
{
$this->Account = $Account;
$this->Operator = $Operator;
$this->_LinkID = $LinkID;

if($Account != null && $Operator != null && $Password != null)
{
$this->Login($Account, $Operator, $Password);
}
}

public function Login($Account=null, $Operator=null, $Password=null)
{
$Account = $this->_LinkID->QuoteSmart($Account);
$Operator = (int) $this->_LinkID->QuoteSmart($Operator);
$Password = $this->_LinkID->QuoteSmart(sha1(md5($Password)));

$result = $this->_LinkID->Query("........");
$NRows = $this->_LinkID->NRows();

if($NRows == 1)
{
if(isset($_SESSION['error']))
{
unset($_SESSION['error']);
}

$_SESSION["account"] = "account";
$row = $this->_LinkID->Row();
$this->Account = $row['login'];
$this->Operator = $row['operator'];
$this->Company = $row['company'];
$this->_isLoggedIn = true;
}
else
{
$_SESSION["error"] = "error";
}
}

public function isLoggedIn()
{
return $this->_isLoggedIn;
}[/PHP]
I don't get it. Why am I not getting a fatal error? Is it because _LinkID was initialized in the constructor then passed into the Login function? Its the only logical explanation I can come up with.
Jun 26 '08 #32
Atli
5,058 Expert 4TB
Ahh I see what you mean.

The parameters of a method have absolutely nothing to do with the class members.
They are often used to initialize the members tho, so I can see why you would confuse them.

$this does not refer to the method it is being called in. It refers to the Object to which the method belongs.
Each method in a class belongs to that class, meaning that every other method or member that belongs to that same class can be called from within a method by using $this-> and then the member or method name.

So using $this->Something is in fact using a member called Something, which belongs to the class.
Calling $Something, however, will use a parameter or a local variable.

Consider this:
Expand|Select|Wrap|Line Numbers
  1. class testclass
  2. {
  3.   public $Member;
  4.   public function __construct() {
  5.     $this->Member = "Some value";
  6.   }
  7.   public function doSomething() {
  8.     $localVar = "I am local";
  9.  
  10.     echo $this->Member . " - ". $localVar;
  11.   }
  12. }
  13.  
Jun 26 '08 #33
fjm
348 100+
It is funny, but I have played with your code sample above and I totally understand but yet I don't understand. When I try and apply the simple example to my real world problems is when I get messed up.

I think I may be getting hung up on exactly what really qualifies as a "member". Like in my user class, I made account, user and password members. Then Coolsti brought up the point about security and I agreed which makes me wonder why I ever used password in the first place.

Is there some sort of guideline to use when choosing members?

Thanks guys, you have no idea how much I appriciate all this help. :)
Jun 27 '08 #34
fjm
348 100+
[PHP] public $id;
public $style;
public $title;

public function __construct($id,$style,$title)
{
$this->id = $id;
$this->style = $style;
$this->title = $title;
$this->Head($title);
$this->Body($id,$style);
}

public function Head()
{
echo " <title>:: $this->title ::</title>\n";
}

public function Body()
{
echo " <div id=\"".$this->id."\" style=\"".$this->style."\"></div>\n";
}[/PHP]
Since I am trying to learn the OO concept I have gone through some of my other classes and tried to apply some of what I have learned here.

Like I mentioned above, in my last post, when I try and apply those principals, I hit a brick wall because I am questioning if what I am doing is correct. It is one thing to do something and write code that you know is correct and it is another thing entirely to hack away at it until it works.

My goal in all of this is to learn OOP well. I want to be as good as you guys. :)

So here is one of my real world examples. I have id, style and title for variables.

The million dollar question is, do I make these class members or local variables? What is it exactly that determines how they are used? My feeling here is that I could use these as local variables and probably be ok, but again, I'm not certain.

The above example uses these 3 vars as class members. If I were to use them instead as local variables, I would rewrite the code to reflect:
[PHP]
public function __construct($id,$style,$title)
{
$this->Head($title);
$this->Body($id,$style);
}
public function Head($title)
{
echo " <title>$title</title>\n";
}
public function Body($id,$style)
{
echo " <div id=\"$id\" style=\"$style\"></div>\n";
}[/PHP]

Which way would be correct and why? I'd guess that its the "why" that I am really trying to understand in all of this.
Jun 27 '08 #35
pbmods
5,821 Expert 4TB
Looks like you are modeling an HTML document.

In practice, you'll probably be better served by using a templating engine such as Smarty (http://smarty.php.net/). But for the sake of theory, let's continue.

HTML documents have three basic attributes: a doctype, a head and a body.

For now, we'll skip the doctype.

The basic format of an HTML page (sans doctype) is:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2.   <head>
  3.     <title>Title is always required.</title>
  4.     <!-- Additional head tags. -->
  5.   </head>
  6.  
  7.   <body>
  8.     <!-- Body content goes here. -->
  9.   </body>
  10. </html>
  11.  
Everything in between the <head> tags is the head, and everything in between the <body> tags is the body.

Note also that the head tag has to have a title. It is a requirement as per XHTML specs (and probably HTML -- but that was years ago!).

So we have three things that have to be in every HTMLDoc: A head, a body and a title inside of the head.

Now, for the sake of the example, the head and body will be stored as strings. This is key because it means that, short of parsing the head before we output it, we have no way of knowing if there's a <title> tag in the head.

So we have to control access to the head. The body we don't care about; that can be public - put whatever you want in there. But the head has to be protected (or private) to prevent just anyone from editing it.

We'll provide access to $head via an addHeadTag() method.

Since we're storing the head as a string, we won't be able to 'check' to see if we added a title tag, so we'll need to create a private member variable to keep track of whether we've added a title tag.

Here's some code:

Expand|Select|Wrap|Line Numbers
  1. class HTMLDoc
  2. {
  3.   public $body;
  4.   protected $head;
  5.   private $_hasTitle;
  6.  
  7.   public function __construct(  )
  8.   {
  9.     $this->head = '';
  10.     $this->body = '';
  11.  
  12.     $this->_hasTitle = false;
  13.   }
  14. }
  15.  
Since we'll most likely be adding one tag at a time to the <head>, we'll create an addHeadTag() method:

Expand|Select|Wrap|Line Numbers
  1. public function addHeadTag( $tag, array $attrs, $innerHTML = null )
  2. {
  3.   /** XHTML requires lowercase tags. */
  4.   $tag = strtolower($tag);
  5.  
  6.   $html = "<{$tag}";
  7.  
  8.   if( ! empty($attrs) )
  9.   {
  10.     foreach( $attrs as $key => $val )
  11.     {
  12.       /** XHTML requires lowercase attributes. */
  13.       $key = strtolower($key);
  14.  
  15.       $html .= " {$key}=\"{$val}\"";
  16.     }
  17.   }
  18.  
  19.   if( $innerHTML )
  20.   {
  21.     $html .= ">{$innerHTML}</{$tag}>";
  22.   }
  23.   else
  24.   {
  25.     $html .= ' />';
  26.   }
  27.  
  28.   /** Check to see if we set a title.
  29.    *
  30.    * Note that we could also refuse to set <title> twice, but
  31.    *  for now, we'll let it slide.
  32.    */
  33.   if( $tag == 'title' )
  34.   {
  35.     $this->_hasTitle = true;
  36.   }
  37.  
  38.   $this->head .= "\n\t\t{$html}";
  39. }
  40.  
Note that in this case, we have a couple of temporary variables ($tag, $attrs and $innerHTML) passed as parameters to the addHeadTag() method. They only get used once, and they're not directly properties of the HTMLDoc, so there's no reason to make them class members.

Note also that addHeadTag() will set $_hasTitle to true when you use it to create a <title> tag.

So far we can create an HTMLDoc, we can add tags to the <head> and we can freely edit the body (because it is public).

Now let's create a method to output the actual HTML:

Expand|Select|Wrap|Line Numbers
  1.   const DEFAULT_TITLE = 'My HTMLDoc';
  2.  
  3.   public function __toString(  )
  4.   {
  5.     if( ! $this->_hasTitle )
  6.     {
  7.       $this->addHeadTag('title', array(), self::DEFAULT_TITLE);
  8.     }
  9.  
  10.     return <<<END
  11. <html>
  12.   <head>
  13.     {$this->head}
  14.   </head>
  15.  
  16.   <body>
  17.     {$this->body}
  18.   </body>
  19. </html>
  20. END;
  21.   }
  22.  
__toString() is a magic method that gets invoked anytime you attempt to cast the instance as a string. In other words, the following statements are identical:
Expand|Select|Wrap|Line Numbers
  1. echo $htmlDoc->__toString();
  2. echo $htmlDoc; // Equivalent to `echo $htmlDoc->__toString()`.
  3.  
Note that we check to make sure $_hasTitle is true before we generate the HTML. If we haven't provided a title, we have a couple of options; we could generate an error or we could use a default value. I have opted for the latter.

To keep things more easily maintainable, I have packaged the default title as a class constant. Whether I should have just used a literal is a topic for another day.

Now we have a reasonably functional HTMLDoc class.

Expand|Select|Wrap|Line Numbers
  1. $doc = new HTMLDoc();
  2.  
  3. $doc->addHeadTag('meta', array('http-equiv' => 'Content-Type', 'content' => 'text/html; charset=UTF-8'), null);
  4. $doc->addHeadTag('title', array(), 'Hello, World!');
  5.  
  6. $doc->body = '<p>My HTMLDoc functions beautifully!</p>';
  7.  
  8. echo $doc;
  9.  
The end result should look like this:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2.   <head>
  3.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  4.     <title>Hello, World!</title>
  5.   </head>
  6.  
  7.   <body>
  8.     <p>MyHTMLDoc functions beautifully!</p>
  9.   </body>
  10. </html>
  11.  
Yay. Okay, so let's talk about the member variables.
  • Easy one first. Every HTML document has a body. Since it is directly a part of the HTML Document, and because it should be mutable (able to be altered), it makes sense to make the body a member variable.

  • The head is similar to the body in that it is always present in an HTML document. It should also be mutable, but we need to control access to it. Therefore, we made it a protected member variable.

  • The presence of a title tag ($_hasTitle) is an 'internal' thing. It doesn't describe the title tag itself; rather it describes the presence (or absence) of the text '<title>...</title>' in the head of the HTML Document.

    In fact, this variable actually describes the head, not the HTML document as a whole, so it would actually make sense for this to be a member of the HTMLHead class... but since $head is a string and not an object, we'll have to settle for making it a member of the HTMLDoc class instead.
Now let's look at some things that are not member variables.
  • The class constant DEFAULT_TITLE is a property of the HTMLDoc class; again, it probably makes more sense to attach this to an HTMLHead class, but since we're not using one of those, we have to make it a member of the HTMLDoc class, instead.

    The main difference between DEFAULT_TITLE and $head is that DEFAULT_TITLE is immutable (not alterable). Whatever value we assign to DEFAULT_TITLE is not supposed to change. So it is a class constant rather than a member variable.

  • We also pass three parameters to the addHeadTag() method: $tag, $attrs, $innerHTML. These are transient in nature; that is, the next time we call addHeadTag(), we will provide new values for these variables.

    Because they are not directly related to the HTMLDoc (they are only used to assemble the proper code that will be added to $head), they are not good candidates for member variables.

The rule of thumb when creating member variables:
  • If it is directly related to the class (or would be suitable as a property of one of the class' members... but that member is not an object), it is a good choice as a member variable.

    (every HTML document has a body, so $body is a good member variable for HTMLDoc)

  • If its value will be changed multiple times during the course of script execution, and you need to be able to keep track of its value between method calls, it is a good choice as a member variable.

    (the head will be modified by calling addHeadTag(), and we need to be able to keep track of every tag that gets added, so $head is a good member variable for HTMLDoc)

  • If the value is directly related to the class (or one of its non-object properties), but its value never changes, it would make a good class constant.

    (DEFAULT_TITLE is directly related to $head [which cannot have properties because it's a string], but its value never changes, so it is a class constant)

  • If the variable is used to modify a class property, but you don't need to track changes to that variable, it is not a good candidate for member variable.

    ($tag and $attrs are passed as parameters to addHeadTag(), but once we've added the head tag, we don't care about $tag and $attrs anymore, so we don't need to save them as member variables)

Hope that helped de-fuzz the issue a bit.
Jun 27 '08 #36
fjm
348 100+
Pbmods, thanks! I just want to tell you that I am going to take a few hours to study all this and I will post back with any questions.

One thing that I picked up through the first read was that any variable that only needs to be used once within its method does not need to be made a class member. Wow, that was simple. I had a huntch that was the way it was supposed to be but I still wanted to have that clarified by one of you guys here. Thanks!

Frank
Jun 28 '08 #37

Sign in to post your reply or Sign up for a free account.

Similar topics

0
by: Carlos Ribeiro | last post by:
I thought about this problem over the weekend, after long hours of hacking some metaclasses to allow me to express some real case data structures as Python classes. I think that this is something...
4
by: Revman | last post by:
I'm having problems opening and reading from a file to test a Class. My diver main.cpp is fairly short but with a longer file open function // Project #4 -- Main/driver program #include...
8
by: CoolPint | last post by:
I read in books that nested class cannot access private members of nesting class and vice versa unless they are made friends. Somehow, my compiler is letting my nested class member functions access...
3
by: DanielBradley | last post by:
Hello all, I have recently been porting code from Linux to cygwin and came across a problem with static const class members (discussed below). I am seeking to determine whether I am programming...
11
by: dhnriverside | last post by:
Hi peeps Ok, so I thought I'd have a go at making a console app in VS2k5... I haven't written any windows apps for years, let alone dos apps (been web programming) and I've hit a dumb error... ...
6
by: **Developer** | last post by:
usually I'd do: Drawing.Image.FromFile( I noticed I once did without thinking: Drawing.Bitmap.FromFile( I assumed this worked because Bitmap inherits from Image, but for fun I thought I'd...
1
by: D Witherspoon | last post by:
Coming up with a scenario here. For example there is the standard .NET MailMessage class. I am creating a project (let's call it CommonBase) that has the following 2 classes ...
5
by: Learner | last post by:
Hello, Here is the code snippet I got strucked at. I am unable to convert the below line of code to its equavalent vb.net code. could some one please help me with this? static public...
10
by: CuTe_Engineer | last post by:
hii, i have cs assignment i tried to solve it but i still have many errors , plzz help mee :"< it`s not cheating becuz i`ve tried & wrote the prog. i just wanna you to show me my mistakes ...
20
by: d.s. | last post by:
I've got an app with two classes, and one class (InventoryInfoClass) is an object within the other class (InventoryItem). I'm running into problems with trying to access (get/set) a private...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.