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
Blinkz0rz
May 27, 2001

MY CONTEMPT FOR MY OWN EMPLOYEES IS ONLY MATCHED BY MY LOVE FOR TOM BRADY'S SWEATY MAGA BALLS
Yeah, scrubbing all L3 documentation is seriously not cool.

Adbot
ADBOT LOVES YOU

Depressing Box
Jun 27, 2010

Half-price sideshow.
The L3 docs are still up, they just got moved.

EDIT: It looks like they still have a 3.0 branch on GitHub, last updated 10 days ago.

Depressing Box fucked around with this message at 04:54 on Jun 1, 2013

Nebulon Gate
Feb 23, 2013
Outside of the Composer stuff and Facades, most of the Laravel 3 docs still hold true. I have no idea why information on Blade and the like still isn't included.

SimonNotGarfunkel
Jan 28, 2011
http://laravel.com/docs/templates#blade-templating ?

FrenchConnection
Aug 27, 2007

"I'm the hand up Mona Lisa's skirt. I'm a surprise, Kevin. They don't see me coming: that's what you're missing."
Does anyone know of any good books / guides / articles that teach you how to secure your PHP code and SQL queries?

Stephen
Feb 6, 2004

Stoned

FrenchConnection posted:

Does anyone know of any good books / guides / articles that teach you how to secure your PHP code and SQL queries?

I would recommend this: http://ca1.php.net/manual/en/intro.pdo.php as the best place to start. PDOs are delicious.

Maniaman
Mar 3, 2006
It's been probably 2 years since I've worked with PHP frameworks. I used CakePHP on a bunch of projects, mostly version 1.2. I see they are up to 2.3 now. Since I'm already experienced with their framework should I stick with it on a new project or is 2.3 some horrible mess that I'd be better off dumping?

Likewise, I'm not sure if this is the best thread or if I should post in the SQL thread, but the app I'm getting ready to write will rely heavily on custom fields. I don't want to serialize the data to store it, I'd prefer something more on the database side so I can index it and such. Is EAV the best method or am I setting myself up for a world of hurt?

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.
CakePHP 2 hasn't changed remarkably since 1, so you should be good to start where you left off. A few things have changed deeper in the system like how you include other objects, some model magic and doing crazy things with views, but if you already know CakePHP 1 you should be able to transition to CakePHP 2 with only a small amount of docs reading when you hit an issue.

I don't have an opinion on EAV itself or alternatives, but there's this: https://github.com/abalonepaul/eav_behavior

Orbis Tertius
Feb 13, 2007

Maniaman posted:

Likewise, I'm not sure if this is the best thread or if I should post in the SQL thread, but the app I'm getting ready to write will rely heavily on custom fields. I don't want to serialize the data to store it, I'd prefer something more on the database side so I can index it and such. Is EAV the best method or am I setting myself up for a world of hurt?

A good overview of the drawbacks of EAV is chapter 6 of this book. It also goes over several alternative schemas for doing variable attributes.

Personally I would avoid EAV, but if its really the best way to model your data you should definitely use a library like v1nce posted.

Vintersorg
Mar 3, 2004

President of
the Brendan Fraser
Fan Club



I am looking online for a easy way to parse a website to get school days. I see there is the php curl method or even using the HTML DOM to read in another URL (http://stackoverflow.com/questions/5465690/php-simple-html-dom-parser-find-string) but im having a bitch of a time trying to sort it out. Is this even possible to grab certain elements and take the text?

I am basically looking to grab any element that has the text "School Day " and get the number from it.

Sereri
Sep 30, 2008

awwwrigami

Vintersorg posted:

I am looking online for a easy way to parse a website to get school days. I see there is the php curl method or even using the HTML DOM to read in another URL (http://stackoverflow.com/questions/5465690/php-simple-html-dom-parser-find-string) but im having a bitch of a time trying to sort it out. Is this even possible to grab certain elements and take the text?

I am basically looking to grab any element that has the text "School Day " and get the number from it.

Almost 2 years ago I used PHPQuery for something similar.

Nebulon Gate
Feb 23, 2013

Vintersorg posted:

I am looking online for a easy way to parse a website to get school days. I see there is the php curl method or even using the HTML DOM to read in another URL (http://stackoverflow.com/questions/5465690/php-simple-html-dom-parser-find-string) but im having a bitch of a time trying to sort it out. Is this even possible to grab certain elements and take the text?

I am basically looking to grab any element that has the text "School Day " and get the number from it.

I used to use this all the time (http://simplehtmldom.sourceforge.net/).

code:
<?php

$html = file_get_html('http://www.schoolsite.com/');

$eles = $html->find('*');
foreach($eles as $e) {
    if(strpos($e->innertext, 'School') !== false) {
        echo $e->id;
    }
}
What do you mean by 'number'? Can you link to the website you're trying to use, or freeze page it at least?

Depressing Box
Jun 27, 2010

Half-price sideshow.
There's also Symfony's DomCrawler, which seems to work similarly to the other two suggestions.

Mister Chief
Jun 6, 2011

I'm having a bit of a nightmare right now trying to serve some big files on shared hosting. Basically I'm trying to use xsendfile and a .php script to serve files located outside of my web root but due to some dreamhost bullshit I can't access anything outside of the web root using this module. Creating a symlink didn't work (this could just be me messing something up but it seemed like it should have worked) so other than moving the files inside the web root I'm not sure what to do. The files themselves are digital goods which are being served once a users credentials are checked and I'm not too familiar with linux folder permissions so I'm worried I'd mess something up and people would be able to access these files without permission.

Any suggestions would be appreciated.

McGlockenshire
Dec 16, 2005

GOLLOCKS!
Put the files inside the webroot in an appropriately named directory.

Enable symlink following in your .htaccess.

When a user requests a download, create a randomly named symlink to the file, redirect the user there.

Log that you created the symlink at time X.

Every Y minutes, delete all symlinks more than Z minutes old.

Mister Chief
Jun 6, 2011

Is it possible to delete a symlink after a download is started but before it has finished?

McGlockenshire
Dec 16, 2005

GOLLOCKS!

Mister Chief posted:

Is it possible to delete a symlink after a download is started but before it has finished?

Yes, that won't impact the download at all.

b0red
Apr 3, 2013

Vintersorg posted:

I am looking online for a easy way to parse a website to get school days. I see there is the php curl method or even using the HTML DOM to read in another URL (http://stackoverflow.com/questions/5465690/php-simple-html-dom-parser-find-string) but im having a bitch of a time trying to sort it out. Is this even possible to grab certain elements and take the text?

I am basically looking to grab any element that has the text "School Day " and get the number from it.

code:
<?php
      $dom = new DOMDocument();
      $dom->validateOnParse = true;
      $dom->loadHTML(file_get_contents("file/path.html"));
      $name = $dom->getElementById("Element ID here")->nodeValue;
      print $name;
?>
I had this exact problem yesterday so I used DOMDoc to do it.

Mister Chief
Jun 6, 2011

McGlockenshire posted:

Yes, that won't impact the download at all.

I decided to cave and move to a VPS and I've gotten it all working now. Thanks for the suggestions anyway.

McGlockenshire
Dec 16, 2005

GOLLOCKS!
5.5 is out.

Here's the migration guide.

5.3 will no longer be updated with anything other than security fixes, and will no longer be updated at all one year from now.

Social Animal
Nov 1, 2005

Sorry in advance if this is a dumb question but I started thinking about this last week. I know PHP was created for dynamic websites, but is there anything else noteworthy to use PHP for? I'm currently a very newbie web developer and I've made some scripts in PHP as well. But I look over and see Python with its plethora of modules for all sorts of things and it gets me wondering if PHP is used at all in non-web projects.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
You could, in theory, use PHP as a general-purpose accepting language. But you almost certainly wouldn't unless you were trying to prove a point or win a bet or something, because PHP is really a terrible language for that. (It's a templating engine wrapped around a bunch of C APIs, neither of which are especially useful for general-purpose scripting).

The primary reason PHP is used on the web is due to first-mover advantage - it was the legitimately best option when it first appeared, and now, there are a lot of hosts that will run PHP and nothing else, plus a lot of existing software written for PHP. Outside of the web, though, any sane developer would choose a language more suited to general-purpose scripting and without PHP's general cruftiness.

mooky
Jan 14, 2012
I'm trying to wrap my mind around something that may be fairly straight forward.

I have an array like so:
code:
array (
    0 => 0
    1 => 0
    2 => 2
    3 => 0
    4 => 0
    5 => 2
    6 => 0
    7 => 0
    8 => 0
    9 => 0
    A => 55
    B => 39
    C => 61
    D => 38
    E => 23
    F => 29
    G => 24
    H => 20
    I => 25
    J => 28
    K => 30
    L => 29
    M => 52
    N => 19
    O => 16
    P => 33
    Q => 5
    R => 32
    S => 72
    T => 73
    U => 21
    V => 8
    W => 28
    X => 2
    Y => 4
    Z => 5
)
I want to group the array into new arrays based on the total value of the values.
Create new arrays of key => value pairs if the sum of the values is under 100. It's important to keep the keys in the order they are in.

Example:
code:
0 thru 9 and A thru B total 98 and are assigned to a new array.
array (
    0 => 0
    1 => 0
    2 => 2
    3 => 0
    4 => 0
    5 => 2
    6 => 0
    7 => 0
    8 => 0
    9 => 0
    A => 55
    B => 39
)

C thru D total 99

array (
    C => 61
    D => 38
)
What is the best way to split the original array like this? I'm having a hard time getting started.

Depressing Box
Jun 27, 2010

Half-price sideshow.
Maybe an overly blunt way to solve it, but this should work:

PHP code:
$i = 0;
$total = 0;

foreach ($input as $key => $value) {
	if (($total += $value) >= 100) {
		$i++;
		$total = $value;
	}
	$output[$i][$key] = $value;
}

var_dump($output);

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies
Alternatively, you can use array_splice. The primary downside is that you have to run a final splice outside the loop to pick up the final group.

php:
<?
$groups = array();
$check = 0;
$last = 0;
$count = 0;
foreach($a as $k => $v) {
    $check += $v;
    if ($check >= 100) {
        $groups[] = array_slice($a,$last,($count-$last));
        $last = $count;
        $check = $v;
    }
    $count++;
}
$groups[] = array_slice($a,$last,($count-$last));
?>

mooky
Jan 14, 2012

Depressing Box posted:

Maybe an overly blunt way to solve it, but this should work:

PHP code:
$i = 0;
$total = 0;

foreach ($input as $key => $value) {
	if (($total += $value) >= 100) {
		$i++;
		$total = $value;
	}
	$output[$i][$key] = $value;
}

var_dump($output);


Master_Odin posted:

Alternatively, you can use array_splice. The primary downside is that you have to run a final splice outside the loop to pick up the final group.

php:
<?
$groups = array();
$check = 0;
$last = 0;
$count = 0;
foreach($a as $k => $v) {
    $check += $v;
    if ($check >= 100) {
        $groups[] = array_slice($a,$last,($count-$last));
        $last = $count;
        $check = $v;
    }
    $count++;
}
$groups[] = array_slice($a,$last,($count-$last));
?>

Thanks guys, I was really trying to over think it for sure. Depressing Box's solution suits me best and does exactly what I was trying to accomplish.
Goon's to the rescue!!!

Nebulon Gate
Feb 23, 2013
There's also an in-built function called array_sum.

http://php.net/manual/en/function.array-sum.php


Which could be useful, potentially.

mooky
Jan 14, 2012
Looking at my previous example a couple posts up and the replies after.
What if I wanted to take the same array and create a new array with XX equal groups?

Instead of grouping the arrays by the total of the values, how can I just create 5 groups of equal or similarly sized arrays?

This way I end up with 5 total new arrays, each array contains part of the original array while maintaining key order and the corresponding value but the total of the values in each new array are close in size so that there isn't one new array with a value of 400 while another is 100 or so.

Modified from the original code from Depressing Box. This almost works, depending on the original array and the values, I can end up with 5,6 or 7 batches.
php:
<?
$i = 0;
$total = 0;
$total_values = 614; // fictitious sum, realistically this would be the sum of all of the values in the original array...
$batch_size = 5; // create 5 new arrays.

foreach ($input as $key => $value) {
    if (($total += $value) > ($total_values / $batch_size )) {
        $i++;
        $total = $value;
    }
    $output[$i][$key] = $value;
}
?>
Any help would be appreciated.

Edit:
I came up with this, it's clunky but it works. Is there a better way to do this? I had issues with the end result not matching what the += amounted to.
php:
<?
$i = 0;
$total = 0;
$total_values = 614; // fictitious sum, realistically this would be the sum of all of the values in the original array...
$batch_size = 5; // create 5 new arrays.

foreach ($input as $key => $value) {
    $reset = false;
    if (($total + $value) > ($total_values / $batch_size )) {
        $reset = true;
        $total = 0;
    } else {
        $total += $value;
    }
    $output[$i][$key] = $value;
    if ($reset) {
        $i++;
    }
}
?>

mooky fucked around with this message at 17:40 on Jul 3, 2013

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!
Has anyone ever created links to everytimezone.com?

I've found it very useful and neat to show what time something is going to happen.
I am trying to create links to certain times and have found that their links are a little odd.

Apparently they are basing everything off New Zealand time (NZST) which is making things a little complicated.

Here's what I have come up with

code:
Desired date: 7/15/2013 20:00 CST
Translated date: 7/16/2013 13:00 NZST
Time since 12am NZST : 13 hours
13 hours * 60 minutes = 780
Url = http://everytimezone.com/#2013-7-15,780,6bj
That is pretty straight forward, as long as the time is after 12am NZST, you can just multiply the hours by 60 and append that to the url in place of the 780 in my link.
My issue is if it's before 12am, or the previous day as in this example:

code:
Desired date: 7/15/2013 05:00 CST
Translated date: 7/15/2013 22:00 NZST
Time since 12am NZST: -2 hours
-2 hours * 60 minutes = -120
Url = http://everytimezone.com/#2013-7-15,-120,6bj
After taking the start date/time and calculating the proper NZST time equivalent, what is the best way to determine the proper minutes value to feed to the url?
I'm trying to create the links dynamically after doing the time calculations with the PHP DateTime class.

ManiacClown
May 30, 2002

Gone, gone, O honky man,
And rise the M.C. Etrigan!

I'm currently trying to output a two-step database query, looking first to OEMs and then to system models, which should look as follows in an unordered list:
  • Acer
    • Model 1
    • Model 2
  • Asus
    • Model 1
    • Model 2
I'm getting hung up with this code. I don't know why, but it's giving me "Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given." It's doing so in the line with the while() statement that checks the $smq_row variable. It's identical to the same query language above, but the only thing I can think of is that it's choking on trying to use the array from the query as part of the search criterion. It's either that or it's some stupid mistake I'm overlooking.
php:
<?
$system_oem_query="SELECT oem_name FROM manufacturers WHERE oem_type='System' OR oem_type='Both' ";
$soq_result=mysql_query($system_oem_query);
while ($soq_row=mysql_fetch_array($soq_result))
    {
echo "<h3>".$soq_row['oem_name']."</h3>";
//-----Queries the system model for output
$system_model_query="SELECT system_model, system_type FROM systems WHERE system_oem = ".$soq_row['oem_name']." ORDER BY system_model";
$smq_result=mysql_query($system_model_query);
    while ($smq_row=mysql_fetch_array($smq_result)) 
        {
    echo "<div>";
    echo "<p>".$smq_row['oem_name']."</p>";
    echo "</div>";
        }
    }?>
The relevant DB tables and their fields are as follows:
  • manufacturers
    • oem_id
    • oem_name
    • oem_type
  • systems
    • id
    • system_oem
    • system_model
    • system_type

Edit: I should note that it's correctly outputting the manufacturers themselves. It's just not outputting the system models under them.

Edit 2: I just read about subqueries. Would that be the best way to handle this? From the examples I've seen so far it doesn't look like it, but I could be wrong.

ManiacClown fucked around with this message at 21:25 on Jul 16, 2013

musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.
It probably means one of your queries is failing and mysql_query() is returning false instead of a resource to a result set.

Chances are, it's this:

$system_model_query="SELECT system_model, system_type FROM systems WHERE system_oem = ".$soq_row['oem_name']." ORDER BY system_model";

You need single quotes around $soq_row['oem_name'] in the query.

But! That said, please, please, please switch to PDO (http://us2.php.net/pdo). The mysql extensions are discontinued in PHP 5.5 and are overall horrible. Also, clean up your code a bit, that code is not very well formatted and difficult to read.

ManiacClown
May 30, 2002

Gone, gone, O honky man,
And rise the M.C. Etrigan!

musclecoder posted:

Also, clean up your code a bit, that code is not very well formatted and difficult to read.

How so? Do you mean I need to insert manual breaks in places like the query?

Also, I do have single quotes where you say. Do you mean I need it to read as '$soq_row["oem_name"]'?
Wait, never mind, I see what you meant after echoing $system_model_query. I've got it outputting now. Now I just need to commit the acts of MySQL fuckery that'll let me get to the REAL object of all this, which will surely send me back into this thread when it's done!

ManiacClown fucked around with this message at 22:59 on Jul 16, 2013

musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.
Clean up your code by tabbing it in properly so it flows better:

php:
<?php

// Spaces around = signs to make it easier to read the variables and the
// functions being called.
$system_oem_query "SELECT oem_name FROM manufacturers WHERE oem_type = 'System' OR oem_type = 'Both'";
$soq_result mysql_query($system_oem_query);

// Removed weird Whitesmith's indentation style. I don't think I've
// ever seen that done. Look into PSR-0 and PSR-1 for current PHP coding standards.
while ($soq_row mysql_fetch_array($soq_result)) {
    echo "<h3>".$soq_row['oem_name']."</h3>";

    // Some whitespace to make it obvious when you're outputting
    // something and when you're making a function call.
    $system_model_query "SELECT system_model, system_type FROM systems WHERE system_oem = '".$soq_row['oem_name']."' ORDER BY system_model";
    $smq_result mysql_query($system_model_query);
    
    while ($smq_row mysql_fetch_array($smq_result)) {
        echo "<div>";
        echo "<p>".$smq_row['oem_name']."</p>";
        echo "</div>";
    }
}

Now your code flows better and is easier to read. But still use PDO and not the mysql extension!

Also, not sure what you mean by getting the REAL object of this, but you can do mysql_fetch_object() which will return the result into an object instead of an array. But use PDO (which can do the same thing)!

ManiacClown
May 30, 2002

Gone, gone, O honky man,
And rise the M.C. Etrigan!

musclecoder posted:

Also, not sure what you mean by getting the REAL object of this, but you can do mysql_fetch_object() which will return the result into an object instead of an array. But use PDO (which can do the same thing)!

I was referring to my ultimate goal of the project. This is actually an intermediate step. Thank you for the help so far. PDO looks nice. I'll end up migrating to it, probably before I proceed much further but after I get the jQuery accordion working. Right now it won't work for some reason and everything's just outputting plain.

Edit: Fixed (sort of) completely now.

ManiacClown fucked around with this message at 18:45 on Jul 17, 2013

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.
musclecoder has you on the right track, but I'd like to push you off the cliff-of-enlightenment and show you a few tricks.

ManiacClown posted:

php:
<?
$system_oem_query="SELECT oem_name FROM manufacturers WHERE oem_type='System' OR oem_type='Both' ";
[...]
while ($soq_row=mysql_fetch_array($soq_result))
{
    [...]
    $system_model_query="SELECT system_model, system_type FROM systems WHERE system_oem = ".$soq_row['oem_name']." ORDER BY system_model";
    $smq_result=mysql_query($system_model_query);

    while ($smq_row = mysql_fetch_array($smq_result)) {
        [...]
    }
    [...]
}
?>
I realise you're just starting out and you've only just heard of sub-queries, but where possible you'll want to avoid doing what you've got above, where you have a loop repeatedly going over a query.
I've seen no end of systems slowed down to a snails pace thanks to loops running over the same query hundreds of times. Yes, databases and networks are faster and more optimised these days, but looping over a query is usually a red flag that you're doing something that needs optimising, and depending on the query it can mean a night and day difference.

For instance, you could optimise the your queries a little bit by using the IN operator on the second query, and fetching all your data at once.
You could also push your code towards MVC (separation of models, views and controller logic) by constructing your menu into an array, then rendering that array.

php:
<?
// Fetch list of manufacturers
$system_oem_query = "SELECT oem_name FROM manufacturers WHERE oem_type = 'System' OR oem_type = 'Both'";
$soq_result = mysql_query($system_oem_query);

// Condense the list of manufacturers to an array
$manufacturers = array();
while ($soq_row = mysql_fetch_array($soq_result)) {
    $manufacturers[] = $soq_row['oem_name'];
}

// Fetch all system models
// Note: This query will not return the parent (manufacturer/oem) if there's no system_model to go with it.
$system_model_query = "SELECT system_oem, system_model, system_type FROM systems WHERE system_oem IN (".implode(',', $manufacturers).") ORDER BY system_oem, system_model";
$smq_result = mysql_query($system_model_query);

// Condense SMQ result to a menu array of our own design
$menu = array();
while ($smq_row = mysql_fetch_array($smq_result)) {

    // Add the header item if it doesn't exist
    if ( !isset($menu[ $smq_row['system_oem'] ]) ) {
        $parent = array();
        $parent['name'] = $smq_row['oem_name'];
        $parent['children'] = array();
        $menu[ $smq_row['system_oem'] ] = $parent;
    }

    // Add the sub-item (if set)
    if ( !empty($child['model']) ) {
        $child = array();
        $child['model'] = $smq_row['system_model'];
        $child['type'] = $smq_row['system_type'];
        $menu[ $smq_row['system_oem'] ]['children'][] = $child;
    }
}

// Holy crap, now we have a $menu with the entire menu structure.
// Build the menu
$output = array();

foreach ($menu as $parent)
{
    // Parent title
    $output[] = "<h3>{$menu['name']}</h3>";

    // Children (if there are any)
    if ( sizeof($menu['children']) )
    {
        foreach ($menu['children'] as $child)
        {
            $output[] = '    <div>';
            $output[] = "        <p>{$child['model']}</p>";
            $output[] = '    </div>';
        }
    }
}

// Echo the output
echo implode("\n", $output);
?>
The above code basically fetches a flat list of "system" entries with the OEMs you specified, then loops over those and constructs a $menu array with a hierarchical structure.
In any other system that $menu variable would be fed to a view - in this case it's our second set of loops which renders out the hierarchy to HTML.
I'm also pushing the output into an array rather than using a straight echo because I can then use implode with a line break (\n) to quickly insert line breaks between my entries and make everything pretty in HTML source. Just because.

Now you're building the hierarchy from a flat data set, we can optimise the queries further and flatten everything into one query. We can also fix the assumption I've made above which is that you're not interested in OEMs (parents) that don't have a system (child) associated with them. You might actually want to show empty OEMs in your menu, in which case the solution above is wrong.

code:
SELECT
    Manufacturer.oem_name,
    System.system_model,
    System.system_type
FROM
    manufacturers as Manufacturer
    LEFT JOIN systems as System on System.system_oem = Manufacturer.oem_name
WHERE
    Manufacturer.oem_type = 'System'
    OR Manufacturer.oem_type = 'Both'
ORDER BY
    system_oem DESC,
    system_model DESC
The SQL is now nicely formatted so you can immediately read everything quickly. I'd encourage you to start doing this because it's just as useful as indenting your code.
We're aliasing our tables; manufacturers becomes Manufacturer for instance. This is just because I work with CakePHP a lot and this is how I normally build my queries as a result.
We're also using a LEFT JOIN which will attach "systems' to "manufacturers" where the system_oem and oem_name match. If you don't want OEMs without children showing up, change this to an INNER JOIN.
The where query stays the same, because your criteria is on the Manufacturer table, and your Systems will be dragged into the results incidentally via the JOIN.

This will spit out something like the following:
pre:
+----------+--------------+-------------+
| oem_name | system_model | system_type |
+----------+--------------+-------------+
| Asus     | 810c         | 1234        |
| Asus     | 1810tz       | 2345        |
| HP       | blah         | blah blah   |
| Dell     | (NULL)       | (NULL)      |
+----------+--------------+-------------+
The join means the OEM_NAME will be duplicated for each row taken from systems. Our menu hierarchy builder, which parses this data, is very careful to build the array considering the oem_name on every loop - it first looks to see if it exists in the $menu array using isset(), and adds it if it doesn't exist.
The extra empty() check on system_model before inserting the children on $menu is because a LEFT JOIN will return rows where system_model and system_type are empty (see row 4 above), and we don't want to add empty children elements to the $menu array. This doesn't apply if we're using an INNER JOIN.

Other contributors could probably tear the (untested) code above apart, but this is hopefully an insight in a few ways to improve things.

ManiacClown
May 30, 2002

Gone, gone, O honky man,
And rise the M.C. Etrigan!

Wow, that looks like it'll be great once I can get it working. It's hanging up on me for some reason. I tweaked it very slightly, renaming $menu to $model_result. Edit: Adding a die() to line 51 says "Unknown column 'Acer' in 'where clause'."

quote:

Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in [FILE LOCATION HERE] at line 55
Line 55 is the last line reproduced here, so ignore the ?> at the end. Here's a Dropbox link to the whole file.
php:
<?
//--create and execute System OEM query; model query is nested
$system_oem_query = "SELECT oem_name FROM manufacturers WHERE oem_type = 'System' OR oem_type = 'Both' ";
$soq_result = mysql_query($system_oem_query);

//Creates array of manufacturers
$manufacturers = array();
while ($soq_row = mysql_fetch_array($soq_result)) {
    $manufacturers[] = $soq_row['oem_name'];
    }

//Fetch system models, leaving out OEMs with no models listed
$system_model_query = "SELECT system_oem, system_model FROM systems WHERE system_oem IN (".implode(',', $manufacturers).") ORDER BY system_oem, system_model";
$smq_result = mysql_query($system_model_query);

//Turn model query into an array of our own design
$model_result = array();
while ( $smq_row = mysql_fetch_array($smq_result) ) {?>

ManiacClown fucked around with this message at 22:51 on Jul 18, 2013

musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.
This should probably be:

php:
<?php

$system_model_query "SELECT system_oem, system_model FROM systems WHERE system_oem IN ('".implode("', '"$manufacturers)."') ORDER BY system_oem, system_model";
That adds single quotes around everything in $manufacturers, the previous query would just have IN(Acer, Dell, Compaq) instead of IN('Acer', 'Dell', 'Compaq').

But you can print out the query and execute it manually in the mysql command line prompt to see the error as well.

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.
Edit: ^^ damnit.

Sorry, the error is in the construction of the SQL statement. If you echo out $system_model_query you should see something like this:
code:
SELECT system_oem, system_model FROM systems WHERE system_oem IN (Acer, HP) ORDER BY system_oem, system_model
The problem is SQL interprets strings not wrapped in quotes as either keywords or column names. Acer and HP are supposed to be literal strings, but in this case they're being looked for as columns. Try searching for an OEM called table and you'll get an even more generic SQL error because "table" is a keyword. This isn't an issue for numerical values because numbers are always numbers.

To fix it, you can amend the implode like so:
php:
<?
$system_model_query = "SELECT system_oem, system_model FROM systems WHERE system_oem IN ('".implode("','", $manufacturers)."') ORDER BY system_oem, system_model";
?>
Notice I've added some single quotes around the brackets and implode. These will turn your search criteria into literal strings, like the following:
code:
SELECT system_oem, system_model FROM systems WHERE system_oem IN ('Acer','HP') ORDER BY system_oem, system_model
Aside from fixing the bug, debugging this issue can be made a lot easier. Before you write too much code and can't go back, take a look at this simple PDO wrapper class: http://www.imavex.com/php-pdo-wrapper-class/
The purpose of this wrapper is to make your life as simple as possible when working with PDO. You don't have to fiddle with complicated datatypes but you still get the power of binding, which is essential for an element of security because it'll do escaping for you. For instance:
php:
<?
// connect
$db = new db("mysql:host=127.0.0.1;port=3306;dbname=myDatabase", "MyUsername", "MyPassword");

$bind= array('criteria1'=>'Asus', 'criteria2'=>'HP'));
$sql = "SELECT system_oem, system_model FROM systems WHERE system_oem IN (:criteria1, :criteria2) ORDER BY system_oem, system_model";
$results = $db->run($sql, $bind);

foreach ($results as $row)
{
    print_r($row);
}
?>
This actually shows off a weakness of PDO, where it can't handle passing an array of items (there are workarounds), so we've had to use "criteria1" and "criteria2" which is ugly as hell, but in almost every other situation this is a great solution.

You can also use this libraries setErrorCallbackFunction() to specify a callback function for error reporting. This would let you specify what happens when PDO hits an error, like so:
php:
<?
function myLovelyErrorHandler( $error )
{
   die('SQL Error:'.$error);
}

$db->setErrorCallbackFunction("myLovelyErrorHandler");
?>
This avoids all that annoying error checking after every statement.

When you have your buggy SQL statement in hand, bring it straight into an SQL IDE like SQLYog and start playing with it. Yog makes a lot of things very obvious (syntax errors, keywords conflicts), and you can retry your queries over and over until you get what you're after. It also have a beautifier - just hit F12 while in the query window.

Finally, your database should probably be using numerical IDs (auto increment primary keys) for relationships between tables; this is all to do with data normalisation which you'll want to read up on.

Someone else might also be able to point you to a PDO wrapper that has more bells and whistles; this one was literally the first result on Google.

v1nce fucked around with this message at 04:11 on Jul 19, 2013

substitute
Aug 30, 2003

you for my mum
Try this PDO wrapper. I've been using it for the last month and it shortcuts a lot of things.

https://github.com/mikehenrty/thin-pdo-wrapper

examples:

php:
<?
// get first result matching parameters
$params = array(
    'col1' => $foo
    ,'col2' => $bar
);
$result = $db->selectFirst('table_name', $params);

if($result) {
    echo '<p>'. result['some_column'] .'<br>'. result['another_column'] .'</p>';
}
?>
php:
<?
// custom query
$sql = "SELECT some_column FROM table_name WHERE col1 LIKE :col1 OR col2=:col2 ORDER BY col3 DESC";
$params = array(
    'col1' => $foo.'%'
    ,'col2' => $bar
);
$result = $db->query($sql, $params);

if($result) {
    foreach($result as $row) {
        echo $row['some_column'] .'<br>';
    }
}
?>

substitute fucked around with this message at 15:00 on Jul 19, 2013

Adbot
ADBOT LOVES YOU

ManiacClown
May 30, 2002

Gone, gone, O honky man,
And rise the M.C. Etrigan!

See, this is what I love about SA. Since I registered it's had intelligent discussion framed in a manner that fits my personality, but after getting out of college (so long, long ago now) I've found that it's got an insanely broad knowledge base that can help me with drat near anything. Thank you all for your help so far.

That said, I've fixed the query with the above suggestions. Now it's giving me an undefined index error in line 60. The other code is still the same and the file has been updated in Dropbox.
php:
<?
$parent['name'] = $smq_row['oem_name'];?>

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