Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Iron Squid
Nov 23, 2005

by Ozmaugh

fletcher posted:

Also check out define, it may be more suited to what you are trying to do. Personally, I've never ever used the global keyword.

Oh hey, define does look like what I'm after.

Can I have a file containing all my defines that I can access from another php file? Or are there scope issues with this, too?

Adbot
ADBOT LOVES YOU

Yay
Aug 4, 2007

Iron Squid posted:

Can I have a file containing all my defines that I can access from another php file? Or are there scope issues with this, too?
Yes, no. Constants are global, and immutable, but they can only store simple scalars, IIRC.

KuruMonkey
Jul 23, 2004

Maniaman posted:

Is it a horribly bad idea to use short tags? I've been writing an inhouse app that makes heavy use of <?=$foo;?> as opposed to <?php echo $foo; ?>. I'm not super concerned with portability (its an in-house app) but more concerned with them removing the short tags in a later version.

The actual answer is entirely predicated on your comment "I'm not super concerned with portability (its an in-house app)".

In that case; no problem, go wild!

If at any point you ARE concerned that your code must run on arbitrary lowest-common-denominator installs, then yes; short tags are the devil, and you must avoid them.

So; your own in-house project to run on a server you configure to suit: <?

When writing something that is to be deployed and maintained by someone else, on a server outside your immediate influence: <?php and nothing else will do.

Its because of that strict divide that I (and I guess anyone else that writes PHP to be deployed by others) tend to treat <? and <?= as a bad idea. But its only that for me it would be a dangerous habit.

KuruMonkey
Jul 23, 2004

Yay posted:

Yes, no. Constants are global, and immutable, but they can only store simple scalars, IIRC.

This is correct, with the aside that "simple scalars" can include serialized arrays and objects :devil:

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine

McGlockenshire posted:

Yup. Versions prior to 5.4 (aka the current trunk) don't have the ability to dereference an array returned from a function without assigning the array to a variable first. Once you get in that habit, it's easy to forget that you can still provide functions that provide arrays to other functions and language constructs that want arrays.

Between this and traits, I'm really looking forward to 5.4.

And since foreach copies the array, it's safe to run on this in my 5.2.9, whereas other functions/constructs may have issues?

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine

KuruMonkey posted:

This is correct, with the aside that "simple scalars" can include serialized arrays and objects :devil:

I look forward to the day when arrays can be constants.

KuruMonkey
Jul 23, 2004

Golbez posted:

I look forward to the day when arrays can be constants.

It will be known as "the day of sanity".

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Golbez posted:

And since foreach copies the array, it's safe to run on this in my 5.2.9, whereas other functions/constructs may have issues?

foreach copies the array values as it reads them. It will (or did - maybe this is fixed in 5.4+) gently caress with the array's internal pointer, for example.

Tad Naff
Jul 8, 2004

I told you you'd be sorry buying an emoticon, but no, you were hung over. Well look at you now. It's not catching on at all!
:backtowork:
oh bother, ignore this

Tad Naff fucked around with this message at 09:35 on Sep 18, 2010

Martenous
Feb 12, 2010
I'm still kind of new to PHP but I was working on my website and created a file with two functions, one to display the header of the website, and one to display the footer.

It's pretty much this:
code:
<?php function display_header($user_info, $page_title) { ?>
HTML OF HEADER
<?php } function display_footer() { ?>
HTML OF FOOTER
<?php } ?>
In the page, the code was:
code:
<?php
require_once "/templates/templateLayout.php";
display_header($user, "TITLE");
display_footer();
?>
But the first thing in the HTML output would be lot's of line breaks and then a ?> then the HTML that should be there. I was able to find out by narrowing it down that this was happening before display_header() was called. I checked every file for any missing <?php and ?>s. But there wasn't any, so for shits and giggles I deleted the ?> at the end of the template file. Now it worked, though I had a feeling this could be a very bad PHP practice, and I rather get it right now instead of later. Any ideas of what's going on here?

e: I should of mentioned in with the html I had a few <php echo $variable; ?>'s and stuff like that.

The most complex it got like was:

code:
<?php if ($user['permission'] == 1) { ?>
<?php } else if ($user['permission'] == 0) { ?>
<?php } else { ?>
<?php } ?>

Martenous fucked around with this message at 05:40 on Sep 19, 2010

McGlockenshire
Dec 16, 2005

GOLLOCKS!

quote:

But there wasn't any, so for shits and giggles I deleted the ?> at the end of the template file. Now it worked, though I had a feeling this could be a very bad PHP practice

Quite the opposite. Excluding the closing tag from the bottom of the file is considered best practice to avoid the whitespace issue. Likewise, making sure that the opening tag is the first thing in the file and making sure your editor isn't inserting a unicode BOM is also best practice. Also consider output buffering.

That being said, mixing PHP and HTML as you're doing can be dangerous and hard to visually parse. Consider adding what might feel like "too much" space to make what's going on more obvious.

Also remember that PHP has heredocs and nowdocs, which are a good alternative to switching in and out of PHP code.

McGlockenshire fucked around with this message at 06:14 on Sep 19, 2010

Martenous
Feb 12, 2010

McGlockenshire posted:

Quite the opposite. Excluding the closing tag from the bottom of the file is considered best practice to avoid the whitespace issue. Likewise, making sure that the opening tag is the first thing in the file and making sure your editor isn't inserting a unicode BOM is also best practice.

That being said, mixing PHP and HTML as you're doing can be dangerous and hard to visually parse. Consider adding what might feel like "too much" space to make what's going on more obvious.

Also remember that PHP has heredocs and nowdocs, which are a good alternative to switching in and out of PHP code.

I did have the original code having much more white space to make it organized, like you said. When I posted, I wanted to conserve space and took away most of the white space and such.

I never even heard of heredocs and newdocs before, thanks for pointing them out. Same with output buffering. I really do have a lot to learn still.

butt dickus
Jul 7, 2007

top ten juiced up coaches
and the top ten juiced up players
I'm starting the long process of moving my poo poo to PDO because all of you convinced me. I'm running into one problem. $handle->query($query) returns a row of the result set. I can do a $handle->query("SELECT FOUND_ROWS()")->fetchColumn() to find the number of results, but only after I've gotten the first result. I'm sure this is something stupid I'm doing, but is there a good way to get the number of results before I start tooling through them? The immediate way I can think of to do this is to first store all the results in an array, but that seems sloppy.

edit: grammar, word choice
edit2: figured it out, I think
$statement = $handle->query($query);
$numrows = $handle->query("SELECT FOUND_ROWS()")->fetchColumn();
while($result = $statement->fetch(PDO::FETCH_ASSOC)) {
welp();
}

butt dickus fucked around with this message at 19:31 on Sep 20, 2010

McGlockenshire
Dec 16, 2005

GOLLOCKS!
I was about to point you at PDOStatement::rowCount(), but it says right there that it doesn't work for SELECTs and you should issue two statements, one with a COUNT(*) and then the real one. Your solution works just as well for MySQL, just be aware that unbuffered queries can bite you in the rear end when working with prepared statements and having multiple statement handles open at once. You may have to use PDO::MYSQL_ATTR_USE_BUFFERED_QUERY.

Out of curiosity, why do you need the result count ahead of time if you're iterating over them blindly?

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine
Sounds like a good argument for using mysqli, myself. :colbert:

butt dickus
Jul 7, 2007

top ten juiced up coaches
and the top ten juiced up players
e: ^^^^one of our machines is running an older version of MySQL and mysqli won't work on it. (no subqueries, either)

That's probably something else that I'm doing retardedly. I'm really just checking to see if I got any results at all, then let the user know that there are no records or just output the result set, sort of like this:
code:
if($numrows) {
 [loop through results]
} else {
 echo "couldn't find your poo poo";
}
I could also do something like this I guess
code:
$results_were_empty = true;
while([get a result array]) {
 [do poo poo]
 $results_were_empty = false;
}
if($results_were_empty) {
 echo "couldn't find your poo poo";
}
but that seems more convoluted.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
This should be fine for smaller result sets, but as McGlockenshire said, if you are iterating through them anyways, you can just keep a counter going.

php:
<?
$query = $db->prepare("select something from somewhere");
if ($query->execute()) {
    $rows = $query->fetchAll(PDO::FETCH_ASSOC);
    echo sizeof($rows);
    foreach ($rows as $row) {
        //stuff
    }
}
?>

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Doctor rear end in a top hat posted:

e: ^^^^one of our machines is running an older version of MySQL and mysqli won't work on it. (no subqueries, either)

That's probably something else that I'm doing retardedly. I'm really just checking to see if I got any results at all, then let the user know that there are no records or just output the result set, sort of like this:
code:
if($numrows) {
 [loop through results]
} else {
 echo "couldn't find your poo poo";
}
I could also do something like this I guess
code:
$results_were_empty = true;
while([get a result array]) {
 [do poo poo]
 $results_were_empty = false;
}
if($results_were_empty) {
 echo "couldn't find your poo poo";
}
but that seems more convoluted.

Sounds like you need to be separating your model and display logic. The piece of code that grabs data from the database should be separate from the piece of code that uses those results to be displayed from the user. The model doesn't care if it returns any results or not, only the view does.

butt dickus
Jul 7, 2007

top ten juiced up coaches
and the top ten juiced up players
In other words, you're telling me to store the results data in an array/object and then go through that for the output.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Doctor rear end in a top hat posted:

In other words, you're telling me to store the results data in an array/object and then go through that for the output.

Exactly, but do them in separate files even. Follow the Model-View-Controller concept, separate the logic. My controllers usually look something like this, where $view is a Smarty object:

php:
<?
public function doGet($user, $request, $view) {
    if ($user->isAuthed()) {
        $articles = Articles::getArticles();
        $view->assign("articles", $articles);
        $view->display("articles.tpl");
    }
}
?>

McGlockenshire
Dec 16, 2005

GOLLOCKS!

Doctor rear end in a top hat posted:

In other words, you're telling me to store the results data in an array/object and then go through that for the output.

Exactly. However, PDO doesn't always make it easy. There's no one-step method to prepare a statement and execute it. There's only just blind execution without placeholders. Then again, you're already working without them if you're stuck on the old mysql extension.

It's not uncommon to create class that extends PDO and includes convenience methods to work around this problem.

Also,

Doctor rear end in a top hat posted:

one of our machines is running an older version of MySQL and mysqli won't work on it. (no subqueries, either)
Holy poo poo, that means you're still running 3.x. 3.23.58 was released seven years ago last week, and all support options ended at the end of 2006. Further, they've stated that the old version manuals may be removed after the end of this year. Maybe this might be enough ammo to convince whoever needs convincing to dedicate whatever resources are needed to get things running on something more modern?

butt dickus
Jul 7, 2007

top ten juiced up coaches
and the top ten juiced up players
We've just built a new machine with the latest MySQL version and will be migrating all of our databases to it, and I had initially planned to switch to mysqli at that point, but PDO seems more attractive. I'm really excited about the 700+MB/s reads we're getting on the SSD RAID that's in it.

I've already started extending PDO to do what I need and it's working fairly well now that I'm figuring things out, and placeholders aren't an issue.

As for MVC, I (unknowingly) used it in a lot of my more complicated scripts, but the majority of my queries that have output are a table that's displayed via AJAX. I've been pretty lazy on these since they're so simple, but I intend to fix this in the future.

butt dickus
Jul 7, 2007

top ten juiced up coaches
and the top ten juiced up players
I don't understaaaaaaaaaaaaaaaaaaaaaand.

this works just fine:
php:
<?
  $query = "DESCRIBE hylafax";
  $result = $conn->query($query);
  while($row = $result->fetchColumn(0)) {
    $columns[] = $row;
  }
?>
This doesn't, and I don't get any errors.
php:
<?
  $conn->prepare("SELECT count(*) FROM hylafax WHERE FaxDate = :FaxDate");
  $blah = "01/01/2001 00:00";
  echo "works fine until here."; //this prints
  $conn->bindParam(':FaxDate', $blah);
  echo "this doesn't print at all";
?>

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
Like this dawg:

php:
<?
$query = $conn->prepare("SELECT something FROM somewhere WHERE field = :field");
$query->bindParam(":field", "whatever");
?>
You want to bind the parameter to the query, not the connection. Do you have error reporting turned on while you do development? I would have guessed it would have thrown an error here.

butt dickus
Jul 7, 2007

top ten juiced up coaches
and the top ten juiced up players
Oh goddamn I'm loving retarded. I didn't even see that prepare returns anything. It makes a lot more sense to bind the paramater to the query, too. Thanks!


VVVV This is also helpful!

butt dickus fucked around with this message at 19:21 on Sep 21, 2010

McGlockenshire
Dec 16, 2005

GOLLOCKS!
FYI, you can also pass an array into execute rather than doing each bind on it's own.

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine
Hip hip hooray, I may be able to use objects. However, having gone without for nearly a year, I'm now pretty rusty. A few questions for the peanut gallery:

1) This class has about 20 properties. Should I store them individually, or have a single array containing them? I'm leaning towards using an array for the properties that will be written/taken from the database, with extra properties for anything else that might be needed (current errors, etc.)

2) Getters and setters. Pros and cons? Right now I'm going without, and using a validation command just before committing to the DB, rather than validating on property set.

3) Let's say I have a class "User". This handles the stuff for a single employee. I also have a class "Users", which handles listing and searching. Is this a proper method of doing it? I'm also instantiating User, but only using Users statically.

spiritual bypass
Feb 19, 2008

Grimey Drawer
I say unless you're going to iterate over them, don't put variables into an array.

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine
True, and the only iteration I'd do is escaping them, and that's not really a big issue.

I've decided to merge the classes, putting the static functions from 'User' into 'Users'. Seems to make sense to me. So I can get a list of Users by doing User::ListUsers(), and then get the detail with $user = new User; $user->GetUser($id). (I don't trust params in constructors, since I'm not dealing with exceptions here)

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Golbez posted:

True, and the only iteration I'd do is escaping them, and that's not really a big issue.

I've decided to merge the classes, putting the static functions from 'User' into 'Users'. Seems to make sense to me. So I can get a list of Users by doing User::ListUsers(), and then get the detail with $user = new User; $user->GetUser($id). (I don't trust params in constructors, since I'm not dealing with exceptions here)

Couple of little things:
1) Maybe rename it to something like User::getUsers()
Why? ListUsers sounds like it's going to do something to display information, the word get makes more sense here. Also follows lowercase naming convention used everywhere else in PHP.

2) The function should return a bunch of User objects, you shouldn't have to instantiate user objects with whatever ListUsers returns. You may already be doing this, wasn't clear from your post. For example, this should work:

php:
<?
$users = User::getUsers();
foreach ($users as $user) {
    echo $user->id;
}
?>

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine

fletcher posted:

Couple of little things:
1) Maybe rename it to something like User::getUsers()
Why? ListUsers sounds like it's going to do something to display information, the word get makes more sense here. Also follows lowercase naming convention used everywhere else in PHP.

2) The function should return a bunch of User objects, you shouldn't have to instantiate user objects with whatever ListUsers returns. You may already be doing this, wasn't clear from your post. For example, this should work:

php:
<?
$users = User::getUsers();
foreach ($users as $user) {
    echo $user->id;
}
?>

I thought about that, but for a list which will only display maybe 6 elements of the object, which has 20 main properties and three arrays consisting of other properties, and a much more complex query, it seemed like a lot of overhead to 1) query for all that extra information for every single item in the list, and to 2) port it over to an object each time, when I could just run a shrunken query for the 6 elements and then run through the array.

You do have a point, though. And I'm probably veering into premature optimization with tht one.

McGlockenshire
Dec 16, 2005

GOLLOCKS!
Getters/setters: Avoid. You either have to write them all yourself manually or dick around with the visibility of the property and use __get/__set. Not worth it now.

For your User class, putting in static methods to retrieve relevant data might make the class feel cluttered. Consider creating a class that handles those tasks on it's own, and can also be responsible for fetching User instances. So, $users = UserManager::list() and $user = UserManager::retrieve($id). Errors on the latter can just return null.

There's a pattern name for this process, but it escapes me. The general theme is that classes should do one thing. The class named User should deal with one user. If you need to work with multiple users, you probably shouldn't wedge that functionality into the User class.

This only works well for certain types of data.

Begby
Apr 7, 2005

Light saber? Check. Black boots? Check. Codpiece? Check. He's more machine than kid now.
Yes, there is a pattern for this in the martin fowler book, the name escapes me.

Basically you want a set of domain objects, like User, Order, Address, etc. These can be composites of each other (for instance, a user can have multiple addresses and multiple orders).

Then you want a set of repository classes. You use these to save and retrieve the objects from your datastore. This adds a second layer that lets you separate your domain logic and classes from where they are stored so your application won't care if the data is stored in a DB, in a file, or on a SOAP service.

You don't need a repository for every domain object. For instance you might never need to save an address separately from a user, in that case you the UserRepository would handle saving the addresses.


One thing, stay away from static methods for this. Otherwise when you start unit testing (which you should do) its going to be a disaster. Pass in database connections or login information into the constructors of your repositories.

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine
So, how about having one manager for the whole application that handles listing and searching of users, of payments, of companies, etc., and then individual classes for user, payment, and company? Or should there be a manager class for each user, payment, company, etc.? This is all a pretty unified application, so I'd like to 1) keep the number of objects low, and 2) There'll be a lot of interaction between them, with the user object searching payments, company object searching users, etc.

As for a separate set of classes to write and get from the DB, that seems at this point to be an unnecessary amount of abstraction. There's no database connections to pass in a constructor anyway; our universal mysql command handles all of that. (yes yes i know pdo mysqi, not my call)

excidium
Oct 24, 2004

Tambahawk Soars
I've set up a website on my work intranet for people to use. As it's on the intranet, security is not a huge issue, but I want to be able to track who is making what changes/restrict access to certain areas without adding another login. Am I able to pull in the active Windows usernames from each of the site's users using PHP/Apache?

Currently I'm on Apache 2.2.11 and PHP 5.3.0. I've been googling and haven't really found what I'm looking for.

Begby
Apr 7, 2005

Light saber? Check. Black boots? Check. Codpiece? Check. He's more machine than kid now.

Golbez posted:

So, how about having one manager for the whole application that handles listing and searching of users, of payments, of companies, etc., and then individual classes for user, payment, and company? Or should there be a manager class for each user, payment, company, etc.? This is all a pretty unified application, so I'd like to 1) keep the number of objects low, and 2) There'll be a lot of interaction between them, with the user object searching payments, company object searching users, etc.

As for a separate set of classes to write and get from the DB, that seems at this point to be an unnecessary amount of abstraction. There's no database connections to pass in a constructor anyway; our universal mysql command handles all of that. (yes yes i know pdo mysqi, not my call)

The domain objects should just define your data.

So, lets say you are modeling cats. Your domain objects might be

Cat
Toy
Dish

Each cat has 0 or more toys, and each cat has a name, color, single water dish and a single food dish. Dishes can never be shared and must belong to a cat. Toys can be shared between cats and created and saved on their own, then assigned to cats.

There are no hard and fast rules, but in this case we will probably have a CatRepository, and a ToyRepository. Notice, we don't have a dish repository, if we were to work with a cat, we might do this.

php:
<?
$cat = new Cat('Fred', 'Brown');
$cat->WaterDish = new Dish('Red');
$cat->FoodDish = new Dish('Blue');

$catRepo = new CatRepository($config);
$catRepo->Save($cat);

$otherCat = $catRepo->Find($catId);
$otherCat->WaterDish = new Dish('Green');
$catRepo->Update($otherCat);
?>
Notice, when we set the dishes, and the toys below, the cat is not doing the saving. THIS IS KEY. The domain objects should not have any dependencies on the datastore, they should only be concerned about their own functionality. This will keep your app from turning into a pile of poo poo.

Secondly, the dishes do not need to be a separate table, depending on what data needed to be associated with a dish, they could go in the same record as the cat. However, we still have a separate object for it. It might also be the case where you have two tables, but only have a single class representing those two tables. The domain objects should be set up however it works logically best in your code. This is a big advantage of this strategy.

Now, for the toys. In this case we might set it up so that we have to create toys first, then assign the toys to a cat. As far as retrieving cats, you can either have the cat repository populate the toys, or have the toy repository pull the toys for a given cat.

php:
<?
$toyMouse = new Toy('Mouse');
$toyRepo->Save($toyMouse);

$cat->Toys->Add($toyMouse);
// Or $cat->AddToy($toyMouse) or $cat->Toys[] = $toyMouse
// Using a method you can check if the toy has an ID set and throw an exception if it doesn't

$catRepo->Update($cat);

// To retrieve a cat and get its toys, any of these might work
$cat = $catRepo->FindByName('Fred');

// Have it fetch for a given cat
$cat->Toys = $toyRepo->FindForCat($cat);

// Have it populate the cat
$toyRepo->FillToys($cat);

// Or just have the CatRepository populate it when you read it out
$cat = $catRepo->Find($catId);
?>
So in short:

There is flexibility, you do not need a single manager or repository for every domain object. Write out some requirements on a sheet of paper, that should get your started as to what domain objects and repositories you might need. Only write methods you are going to actually use, you can add more later as needed.

Domain objects do not need to map 1 to 1 to database records (take the dish example above, there might not be a dish db table, but you might want to have it be represented as an object).

One big global manager is probably not good practice. Less classes does not mean better code. However, you can probably split it up later.

There are a lot of different strategies for fetching domain objects, but do not have the domain objects themselves do any database or repository calls. The domain objects should have no dependencies whatsoever on your repository classes.

Use unit tests.

Alex007
Jul 8, 2004

excidium posted:

I've set up a website on my work intranet for people to use. As it's on the intranet, security is not a huge issue, but I want to be able to track who is making what changes/restrict access to certain areas without adding another login. Am I able to pull in the active Windows usernames from each of the site's users using PHP/Apache?

Currently I'm on Apache 2.2.11 and PHP 5.3.0. I've been googling and haven't really found what I'm looking for.

I'm pretty sure PHP can't read it as it is never passer to the server.

But JavaScript could be able to read it on the client-side, and dump it into a hidden form field for PHP to retrieve.

code:
var wshshell=new ActiveXObject("wscript.shell");
var username=wshshell.ExpandEnvironmentStrings("%username%");
Of course this code only works in IE.

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine
Begby, that sounds like it adds a layer of complexity; if I change the data model, I now have to change two objects (the domain object and the repository) rather than one? In the past I would have simply had methods like Cat->Get($id), Cat->Write, etc. I'm not at the point where data access has to be abstracted; if we ever change DB methods, this will be a drop in the pond compared to the work that will have to be done on the rest of the site.

And the domain object only holds data, with no methods apart perhaps from getting and setting said data?

McGlockenshire
Dec 16, 2005

GOLLOCKS!

Golbez posted:

And the domain object only holds data, with no methods apart perhaps from getting and setting said data?

It depends on what, if any, additional logic is required.

A bit part of my job deals with configurators. We're right now in the process of rebuilding our configurator tool to allow better, more foolproof end-user interaction.

So, we then have a Configurator class. Right now, while we're building it, it's pretty barren. It's little more than a name and a list of Options. Options live in Widgets (with special UI behavior). Each Option has a list of Choices. Each Choice is composed of one or more Components. Each Component has a specific type with specific attributes, some of which are relied upon by other Choices. Each Component is also attached to a SKU in our ERP system.

From the top to the bottom, it's simple properties and very little logic. The only place where logic comes into play is in Widgets, which need to do smart things with Component attributes in order to display the right data to the end users.

When designing this collection of objects, we decided not to use the repository concept. Instead, we chose to write a very thin layer of ORMish goodness to make loading and saving each of these objects easy, and elected to write all of the list-generating code as queries in the appropriate controller. This has ended up working well for us, to a point.

For example, when setting up a Widget, you have to pick one or more Options. In order to get the list of Options, the Widget has to directly poke the database. This is kind of rude. Proper OO procedures dictate that the Option class (or something that also deals with Options) should provide that list. My team has argued against this practice, not because there's anything procedurally wrong with it, but because it adds an additional level of complexity that we don't need at this exact moment in time. We're trying to do "the most simple thing that could possibly work."

So really, it all depends on what tradeoffs you want to make. "Unnecessary" OO is The Right Thing(tm), but it adds complexity at the probable cost of reducing maintenance later. Under-engineering can reduce initial complexity, but may become a maintenance burden later.

Given that you're working with someone that doesn't care for OO, you probably want to go the subtle route while simultaneously pointing out what the alternatives are. I'd sooner use the repository thing myself, but nobody here dislikes OO to that extent.

Adbot
ADBOT LOVES YOU

Golbez
Oct 9, 2002

1 2 3!
If you want to take a shot at me get in line, line
1 2 3!
Baby, I've had all my shots and I'm fine
Yeah, what I am doing right now is far from pretty, but I'm rusty and also doing this somewhat under the radar. I figure, it's a *lot* easier to convert from OO to procedural than vice versa, so if they truly want me to go back it's a day's work, whereas it's been several days going the other direction.

A question about the cat example. You say a Cat can have multiple Toys; I assume these would be stored inside the Cat in an array? So to add one, you'd either need a setter like $Cat->AddToy('mouse'), or something like $Cat->Toys[] = new Toy('mouse')?

I do love working with objects, though. There's just something so solid about simply doing a "$foo->dostuff" rather than having to throw it all there in the middle of the code, or keep track of what's where.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply