Jump to content

codebyren

Members
  • Posts

    156
  • Joined

  • Last visited

Posts posted by codebyren

  1. Hi.

     

    My MySQL server version is 5.5.8.  I've got two tables something like these simplified ones:

     

    authors:

     

    author_id

    name

    1

    Joe Bloggs

    2

    Mary Bloggs

    3

    John Smith

     

    books:

    (in this example, a book will only ever have 1 author):

     

    book_id

    author_id

    title

    price

    discontinued

    1

    3

    Some Book Title

    10.00

    0

    2

    1

    Another Great Book

    15.00

    0

    3

    1

    Not Such A Great Book

    15.00

    1

    4

    1

    Average Book

    8.00

    0

    5

    2

    The Penultimate Book

    15.00

    1

    6

    3

    The Last Book

    27.00

    0

     

    My goal is to join these tables in a query that will:

     

    1.) return a single row per author and

    2.) the row must contain the author's cheapest book that is not discontinued and

    3.) the rows must be sorted by price/author BUT

    4.) if an author's ONLY book is discontinued, this row must appear last in the result set.

     

    The catch for me is that when I include a GROUP BY `author_id` clause, any author that has ANY discontinued book whatsoever is getting pushed to the bottom of the result set.  If they have any non-discontinued books, I need the cheapest one to be included instead (and sorted appropriately).

     

    So far I've tried simple variations of:

     

    SELECT *, MIN(price) AS min_price FROM authors JOIN books ON authors.author_id = books.author_id GROUP BY author_id ORDER BY discontinued ASC, min_price ASC

     

    but as I say, the Joe Bloggs author with both the cheapest book and a separate, discontinued book would be listed last (undesirably) according to my query like the above.

     

    I suspect it has to do with how GROUP BY determines which row to include but I've spent way too much time looking into this already and would appreciate some help.

     

    I'd be happy to generate some dummy data if anyone wants to have a play around but I get the feeling I'm just missing something simple here.

     

    Thanks.

  2. I can't spot anything in the block of code you posted so I suspect that there is an unclosed brace (or something like that) in one of the view files being loaded with:

     

    <?php $this->load->view($templateVar . '/_whatever_'); ?>

     

    Then, when PHP reaches the if statement in question... it's unexpected.

  3. I am able to only pass one criteria when I build a client in c# using Visual Studio.  I wonder if MS has some sort of proprietary method that makes it work vs. PHP?

     

    I'm not really sure.  I recall using a library in Python that could inspect the WSDL, generate a properly constructed object from it and then I'd just  populate whatever properties I needed to (or had to) before making the SOAP call. Maybe c# has a similar implementation.  It might just be that the fields/properties need to be present - regardless of whether they all have a value or not.  I guess this depends on the SOAP server.

     

    Maybe someone else will shed some light on this...

  4. Judging by the WSDL, it looks like there are some required fields where the SearchCriteria array is concerned.  For example, the ExpiryTSA field must apparently occur once, and only once, in the request:

     

    <s:element minOccurs="1" maxOccurs="1" name="ExpiryTSA" type="s:dateTime"/>

     

    If you create an array with all the required fields and add some test values (appropriately cast as integers or strings etc.) then you should get a response.  I also had to guess that they wanted ISO 8601 format for the datetime fields.

     

    Using the following, I can at least get an empty result (hopefully you know better values to enter in each field):

     

    <?php
    $client = new SoapClient('https://servicestest.mcquaig.com/mws.asmx?WSDL');
    $criteria = array(
    'ApplySharing' => true,
    'CGType' => 1,
    'Composites' => 2,
    'Expired' => 123,
    'ExpiryTSA' => date('c'),
    'ExpiryTSZ' => date('c'),
    'FormLangID' => 123,
    'FunctionalArea' => 5,
    'Gender' => 2,
    'Industry' => 2,
    'LastUsedTSA' => date('c'),
    'LastUsedTSZ' => date('c'),
    'NoRelated' => true,
    'ObjectType' => 1,
    'OrgID' => 123,
    'Position' => 3,
    'ProfileType' => 1,
    'Recursive' => true,
    'Status' => 2,
    'Type' => 2,
    'UnitsRemain' => 2,
    'UnitsRemainGT' => true
    );
    $params = array('user' => 'johndoe1', 'password' => 'snowball', 'criteria' => $criteria);
    $result = $client->Find($params);
    print_r($result);
    ?>
    

  5. As xyph suggested, you can add a conditional to check whether $values has any data in it before rendering the row in the table.

     

    Then, as a side note, you should use the fgetcsv function for reading lines in a CSV file.  This is preferable to explode() as it can handle cases where a cell in an apropriately formatted CSV line contains commas.  For example, this line has 4 values but 4 commas too (which explode would return as 5 values):

     

    superman,spiderman,"batman,robin",hulk

     

    In the above, "batman,robin" should be interpreted as one value.  So, working from your initial code:

     

    <?php
        // Not ideal...
        $buffer = fgets($cnx); // get contents of file (name) as variable	
        $values = explode(",", $buffer); //explode "," between the values within the contents
    
        // Better
        $values = fgetcsv($cnx); // parse CSV line into an array
    ?>
    

  6. The $i variable is just a counter for determining which ROW you're on whereas the $j variable you had in your for-loop indicates which CELL you're on.  I didn't mean for you to replace the $j variable with the $i variable.  Also, you shouldn't have placed the while statement snippet I gave you within the in the while statement that was already there.  The logic was just meant to be integrated into it.  Like so:

     

    <?php 	
    $cnx = fopen("data/Book1.csv", "r"); //open example.csv
    echo("<table>\n\t<tbody>\n"); // echo the table
    
    $i = 1;  # counter variable (to note which row we're working with)
    while (!feof ($cnx)) { // while not end of file
    $buffer = fgets($cnx); // get contents of file (name) as variable	
    $values = explode(",", $buffer); //explode "," between the values within the contents
    echo "\t\t<tr>\n";
    for ( $j = 0; $j < count($values); $j++ ) {  //
    	if ($i === 1) {
    	// This is the first row - use <th> cells
    		echo("\t\t\t<th>$values[$j]</th>\n");
    	}
    	else {
    		// This is NOT the first row - use <td> cells
    		echo("\t\t\t<td>$values[$j]</td>\n");
    	}		
    }
    echo"\t\t</tr>\n";
    $i++;  # increment the counter
    };
    
    echo("\t</tbody>\n</table>");
    fclose($cnx); //close filename variable
    ?>
    

     

    Hopefully that makes more sense...

  7. Something like this:

     

    <?php
    $i = 1;  # counter variable (to note which row we're working with)
    while ( ! feof($cnx)) {
        if ($i === 1) {
            // this is the first row - use <th> cells
        }
        else {
            // this is NOT the first row - use <td> cells
        }
        $i++;  # increment the counter
    }
    ?>
    

  8. Check your SQL for fetching the user.  You have a period appended to the username:

     

    $checkuser_query = "SELECT * FROM users WHERE username = '$username.' AND password = '$password'";

     

    So if you enter "admin" as the username, your query is trying to find "admin." (i.e. with a period at the end).

  9. I think you have gotten very confused somewhere. name="answerArray[1]" <------ will not make it an array all you have done here is named it answerArray[1]  so in php if you want to access its data you would need to do this $_POST['answerArray[1]']

     

    Yes it will.  It'll be available as an array in $_POST['answerArray'] - PHP takes care of this.

     

    Then, doubledee, the variables assigned in a foreach statement are in the local scope so it's probably best to consider them temporary (the $key => $value part anyway) and if in doubt, you could use unset() like this:

     

    <?php
    foreach ($array as $key => $value) {
    // Do something
    }
    unset($key, $value);
    ?>
    

     

    Then you won't accidentally use unexpected values or get confused later...

  10. For an email message with so few lines and variables, the simplest way to do this is probably to build the message line by line.  Something like:

     

    <?php
    // The \r\n indicates a new line or else your message will render as a single line
    // The period before the '=' sign on all except the first line says append this value to the current value of $message
    $message = "{$_REQUEST['_title']} \r\n";
    $message .= "--------------------- \r\n";
    $message .= "Forum Name: {$_REQUEST['_forumname']} \r\n";
    $message .= "Real Life Name: {$_REQUEST['irlname']} \r\n";
    $message .= "Age: {$_REQUEST['_age']}  \r\n";
    ?>
    

     

    You could also look into what's known as herdoc syntax which is basically a pre-formatted string that can have variables scattered throughout it.

  11. join adds the tables together and the result is a lot of repeated things that i dont want !

     

    It sounds like you are using SELECT * in your SQL statement and/or have content duplicated across your tables (which ideally you shouldn't).  Why not just select the stuff you want? Then there won't be any repeats. Something like:

     

    SELECT table1.user_id, table1.email, table2.name, table2.address FROM table1 JOIN table2 ON table1.user_id = table2.user_id WHERE table1.user_id = 'whatever'

     

  12. Since your date fields don't seem to have pre-defined keys in the HTML (and consequently the $_POST array), try something like this:

     

    <?php
    // Prepare an array to stash values successfully converted to timestamps
    $timestamps = array();
    
    // Loop through post values and try convert each non-array value to a timestamp
    foreach ($_POST as $key => $value) 
    {
    if ( ! is_array($value))
    {
    	$time = strtotime($value);  # returns FALSE on failure
    	if ($time) $timestamps[] = $time;		
    }
    }
    ?>
    

  13. You could try something as simple as a dynamic PHP file which is served with Javascript headers that your users can add to their website.  Something like:

     

    <?php
    $daily_quote = get_daily_quote();  # assume this is a simple string
    header('Content-type: application/javascript');
    ?>
    // The output of this page should be treated as javascript by the user's browser
    (function (quote){alert(quote)})(<?php echo $daily_quote; ?>);
    

     

    Your users then just need to hotlink the JavaScript file (really PHP) hosted on your server:

    <script type="text/javascript" src="//yourserver.com/daily_quote_javascript.php"></script>

     

    When the code above is interpreted by the browser, the anonymous function will just alert the quote for the day (which was determined dynamically via PHP).  You'd obviously want your function to do something more advanced like wrap the quote in appropriate HTML and add it to the page but that's up to you.

     

    There are more advanced ways to approach this so if you bump into any walls or limitations with this approach, you could look into JSONP.

  14. Since the xpath method of the SimpleXMLElement returns an array of objects (which is good in case there's more than one match for the xpath provided), you'll need to iterate over the results or at least determine how many there are first:

     

    <?php
    
    if ( ! $myDataOjects) die('No results found.');
    
    if (count($myDataOjects) > 1) {
    // There's more than one result with data=Kanden so we "foreach it".
    foreach($myDataOjects as $obj) {
    	echo "The ruler of this element is {$obj->ruler}";
    }
    }
    else {
    // Only one result so we can access it by the '0' key of the result array
    echo "The ruler of Kanden is {$myDataObjects[0]->ruler}";
    }
    ?>
    

     

    And also how would I make it possible so that other people without server access, can grab data from this page and use it in their own scripts?

     

    I don't really understand the question.  Where does this XML file reside? And are you processing it on a different server? And which server do "other people" not have access to?

  15. Your function doesn't return TRUE or FALSE in all cases. In particular:

     

    <?php
    if ($regenFromPostPW == $user_data->password)
    {
        // Your code here returns TRUE
    }
    else
    {
        $this->increase_login_attempt($user_data->user_id);
    
        // No return value here so you're probably ending up with NULL.
    }
    ?>
    

  16. Well, unless you have defined a "cookie" function, I don't believe CodeIgniter has one for you. So cookie('xtrcook') may fail anyway.

     

    You probably want something like this:

     

    <?php
    $cookie = trim($this->input->cookie('xtrcook'));
    
    // Or with the cookie helper functions (not really necessary)
    // $cookie = trim(get_cookie('xtrcook'));
    
    if ( ! $cookie || ! is_numeric($cookie)) {
    die('bad cookie');
    }
    ?>
    

     

    Otherwise, as creata.physics said, what is the exact error you are getting?

  17. You want the CURLOPT_RETURNTRANSFER setting.  This will capture the response to your cURL post in a variable and then you can do what you want with it (i.e. output it or not).

     

    <?php
    // Your current cURL initialization and settings stay as you have them
    
    // Tell cURL you want to capture the response (not render it to the browser)
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  
    
    // Then assign the cURL response to a variable
    $output = curl_exec($ch);
    
    // Then close the cURL connection as usual
    curl_close($ch);
    
    // Do whatever you want with the $output variable.
    ?>
    

  18. I'm not sure this will help since I'd also expect the error to be logged in the framework or server logs as you mentioned, but...

     

    The error handler for ajax calls made via jQuery should have access to many details about the error on the client side.  You could gather whatever you want from this and then post it to a custom URL (again via AJAX) that will log the data for your review at a later stage.  I don't know all that much about the properties of the jqXHR object (assuming jquery version 1.5+) but something like this might work:

     

    $.ajax({
    
        // Set usual parameters here
        // ...
    
        // Handle any errors
        error: function(jqXHR, textStatus, errorThrown)
        {
            var my_error = 'Error: ' + textStatus + ', HTTP code:' + jqXHR.status + ', Response text: ' + jqXHR.responseText;
            // Maybe add some other interesting info like jqXHR.getResponseHeader('content-type')
    
            // Do a follow-up ajax post to log these details server-side and hope it works.
        }    
    });
    

     

    There's more info about the jqXHR object .

     

    It's a bit of a round-about way of getting the error but it will hopefully provide you with more info than you have now...

  19. Are you wrapping the $description in <pre> tags when you render it?  If not, I don't believe the newlines will be honoured (from a presentation perspective) even if they do happen to make it through your filter function.

     

    Then, I haven't looked through your function but you may want to have a look at implementing htmlpurifier to handle this for you.  When I looked into doing this sort of thing a few years back it turned into a massive task and you never quite filter out everything you think you are.  May as well try a tool developed for the task.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.