Helo with mJoin Link

Helo with mJoin Link

rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0

The following example seems to work fine in terms of displaying everything I need, however, in the JSON I see the data for all records in the DB, not just the ones matching the Link(). As the dataset gets bigger, this function is taking forever. How can I fix this?

          ->join(
              Mjoin::inst( 'Booked_Extras' )
                  ->link( 'TripDB.TripID', 'Booked_Extras.TripID' )
                  ->fields(
                      Field::inst( 'Booked_Extras.Name' )
                          ->options( 'Booked_Extras', 'TripID', 'Name' )
                          ->set(false)
                          ->name('Name'),
                      Field::inst( 'Booked_Extras.Price' )
                          ->options( 'Booked_Extras', 'TripID', 'Price' )
                          ->set(false)
                          ->name('Price'),
                      Field::inst( 'Booked_Extras.Qty' )
                          ->options( 'Booked_Extras', 'TripID', 'Qty' )
                          ->set(false)
                          ->name('Qty')
                          )
                  ->where('TripDB.TripID', 'Booked_Extras.TripID', '=')
                )
          ->where('OrderID', '1234-5678', '=')
          ->process( $_POST )
          ->json();

I only want the Extra's for all the Trips of that one Order.

I recently added the ->where('TripDB.TripID', 'Booked_Extras.TripID', '=')
...but it didn't help.

Answers

  • rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0

    I think I fixed it just by getting rid of the ->options() line. Not sure why I thought I needed that before. It still take a while to load the table though. I hope it doesn't continue to get worse any longer as the Extra's table grows.

  • rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0
    edited June 2016

    Another issue... the above is getOrderTrips.php. I could never get it to work for saving edits to the main non-joined table, so instead I have a separate setOrderTrips.php which is the same without the mjoin's.

    It used to be that when I set it, it would return the main-table, and everything would be fine except the display of the mjoin stuff would disappear. Now all of a sudden, when I add a new Trip to the Order table, and then edit its Tip field, setOrderTrips returns nothing and the row disappears.

    NOTE: I am using in-line edit of the Tip field in the Trip's table of the pending Phone-Order.

    If I simply reload the page, then all the edited trips come back, with the Tip edit that was made and all. Really strange is I can then edit the Tip again, and it works fine (returning data, keeping the row, and only losing the mjoin stuff).

    Obviously I would love it if I could make getOrderTrips.php just always work so that the mjoins don't disappear, but I could never get that to work and setOrderTrips.php has been a fine work around until this strangeness started happening.

  • rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0

    @allen, please come to my rescue ;) How can I use Editor with lots of mjoins properly?

  • allanallan Posts: 61,744Questions: 1Answers: 10,111 Site admin

    Hi,

    You only posted this thread yesterday. I'd appreciate if you could wait at least 24 hours before bumping a thread - there are about 50 support requests per day I need to reply to, so it takes time. If it is urgent for you, priority support is available.

    Good to hear that you got the performance issue fixed at least in part. You are correct that the where() line for the Mjoin isn't going to help since that is what the join is already doing. Beyond that, I would need to be able to profile the PHP with your dataset to be able to understand why it is taking a while.

    I could never get it to work for saving edits to the main non-joined table

    Perhaps you could show me the full PHP and JS code you were using please.

    If I simply reload the page, then all the edited trips come back, with the Tip edit that was made and all.

    I think I would need to be able to debug the page directly to understand what is going wrong here. Although I guess if the previous issue is resolved then this goes away.

    Thanks,
    Allan

  • rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0

    Ok sorry Allen. I will give much longer than 10 hours next time. I apriciate your support on my issues with Editor.

    So here are the 2 issues again:
    1) I didn't even know tables with mjoin could be edited. It has always given me an error that seemed to indicate it was not supposed to work. If I can use a table with an mjoin (with set(false) of course) to edit the root table, that would be awesome as right now whenever I edit using the separate file (same but without mjoins) then a bunch of my data disappears until reload.

    NOTE: In typing the above, I realized that I use a VIEW (TripDB) for the main file, but save to Booked_Trips... so that's why I can't do it... the VIEW. I had to make views because I could never figure out how to link so much stuff together using your PHP library alone. This sort of thing has been a problem for the past 2 years of development using your tools and I still don't understand how to do it right. :(

    2) In one (repeatable) case ever, and a recent bug that didn't exist before: On new phone order, when you just added a single row to the TripDB table, and then you edit the TIP in Booked_Trips using inline edit... instead of just the mjoin data disappearing (as expected) the entire row disappears (the AJAX edit call actually returns an empty dataset). If you then reload the page, the trip re-appears (with the proper edit performed). If you then do the exact same edit of TIP, the problem is gone (the AJAX edit call returns all the Booked_Trips fields, and only the mjoin stuff disappears)

    You are welcome to see it all in action in my backend (you were there once before about 6 months ago, but that old account is deleted by now... we just launched a week ago and much cleaning was done). Please create an account here, and then I will upgrade it to Admin so you can see what I am talking about: https://onewaylimo.com/signup/passenger/

    If this ends up needing a lot of your time, I will contact the client and see if I can get them to pay for some priority support. Let me know.

    Now for the files:

    1) getOrderTrips.php
    2) setOrderTrips.php
    3) VIEW definition for TripDB

  • rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0

    1) getOrderTrips.php

    <?php $siteRoot = substr(__FILE__, 0, -strlen($_SERVER['SCRIPT_NAME']));
          include $siteRoot.'/login/include/datatables/php/lib/DataTables.php';
    
          use DataTables\Editor,
              DataTables\Editor\Field,
              DataTables\Editor\Format,
              DataTables\Editor\Join,
              DataTables\Editor\Mjoin,
              DataTables\Editor\Upload,
              DataTables\Editor\Validate;
    
    if (isset($_REQUEST['user']) && !isset($_REQUEST['order']))
     {$filter = 'userid';
      $select = $_REQUEST['user'];
      $filter2 = 'Status'; 
      $select2 = 'Pending';
     }
    else
     {$filter = 'OrderID'; 
      $select = $_REQUEST['order'];
      $filter2 = 'CostTrip'; 
      $select2 = '0';
     } 
    
          Editor::inst($db, 'TripDB', 'TripID')
              ->field(
                        Field::inst('TripID'),
                        Field::inst('OrderID'),
                        Field::inst('Modified'),
                        Field::inst('Created'),
                        Field::inst('NumPass'),
                        Field::inst('NumBags'),
                        Field::inst('CostTip'),
                        Field::inst('Name'),
                        Field::inst('PickupTime'),
                        Field::inst('PickupLocation'),
                        Field::inst('DropoffLocation'),
                        Field::inst('VehicleType'),
                        Field::inst('CostTrip'),
                        Field::inst('CostExtras'),
                        Field::inst('CostTax'),
                        Field::inst('CostTotal'),
                        Field::inst('Airport'),
                        Field::inst('Airline'),
                        Field::inst('Flight'),
                        Field::inst('FlightTime'),
                        Field::inst('Mileage'),
                        Field::inst('Notes'),
                        Field::inst('Duration'),
                        Field::inst('Tolls'),
                        Field::inst('MapLink'),
                        Field::inst('Status'),
                        Field::inst( 'AffiliateName' ),
                        Field::inst( 'AffiliatePhone' ),
                        Field::inst( 'AffiliateCompany' ),
                        Field::inst( 'AffiliateID' ),
                        Field::inst( 'AffiliateEMail' ),
                        Field::inst( 'AffiliateUser' ),
                        Field::inst( 'FareStatus' ),
                        Field::inst( 'FareModified' ),
                        Field::inst( 'userid' ),
                        Field::inst( 'username' ),
                        Field::inst( 'userfullname' ),
                        Field::inst( 'userphone' ),
                        Field::inst( 'ValueFare' ),
                        Field::inst( 'ValueExtras' ),
                        Field::inst( 'ValueTip' ),
                        Field::inst( 'ValueTax' ),
                        Field::inst( 'ValueTotal' ),
                        Field::inst( 'NumStop' )
                     )
              ->join(
                  Mjoin::inst( 'Booked_Passengers' )
                      ->link( 'TripDB.TripID', 'Booked_Passengers.TripID' )
                      ->fields(
                          Field::inst( 'Booked_Passengers.Name' )
                              ->set(false)
                              ->name('Name'),
                          Field::inst( 'Booked_Passengers.Phone' )
                              ->set(false)
                              ->name('Phone')
                              )
                        )
              ->join(
                  Mjoin::inst( 'Booked_Stops' )
                      ->link( 'TripDB.TripID', 'Booked_Stops.TripID' )
                      ->fields(
                          Field::inst( 'Booked_Stops.Name' )
                              ->set(false)
                              ->name('Name'),
                          Field::inst( 'Booked_Stops.Address' )
                              ->set(false)
                              ->name('Address')
                              )
                        )
              ->join(
                  Mjoin::inst( 'Booked_Extras' )
                      ->link( 'TripDB.TripID', 'Booked_Extras.TripID' )
                      ->fields(
                          Field::inst( 'Booked_Extras.Name' )
                              ->set(false)
                              ->name('Name'),
                          Field::inst( 'Booked_Extras.Price' )
                              ->set(false)
                              ->name('Price'),
                          Field::inst( 'Booked_Extras.Qty' )
                              ->set(false)
                              ->name('Qty')
                              )
                    )
              ->where($filter, $select, '=')
              ->where($filter2, $select2, '!=')
              ->process( $_POST )
              ->json();
    

    2) setOrderTrips.php

    <?php $OrderID = $_REQUEST['order'];
    
          $siteRoot = substr(__FILE__, 0, -strlen($_SERVER['SCRIPT_NAME']));
          include_once $siteRoot.'/login/include/datatables/php/lib/DataTables.php';
    
          use DataTables\Editor,
              DataTables\Editor\Field,
              DataTables\Editor\Format,
              DataTables\Editor\Join,
              DataTables\Editor\Mjoin,
              DataTables\Editor\Upload,
              DataTables\Editor\Validate;
    
          Editor::inst($db, 'Booked_Trips', 'TripID')
              ->field(
                        Field::inst('TripID'),
                        Field::inst('OrderID'),
                        Field::inst('NumPass'),
                        Field::inst('NumBags'),
                        Field::inst('CostTip'),
                        Field::inst('Name'),
                        Field::inst('PickupTime'),
                        Field::inst('PickupLocation'),
                        Field::inst('DropoffLocation'),
                        Field::inst('VehicleType'),
                        Field::inst('CostTrip'),
                        Field::inst('CostExtras'),
                        Field::inst('CostTax'),
                        Field::inst('CostTotal'),
                        Field::inst('Mileage'),
                        Field::inst('Duration'),
                        Field::inst('Tolls'),
                        Field::inst('MapLink'),
                        Field::inst('Status')
                      )
              ->where('OrderID', $OrderID, '=')
              ->process( $_POST )
              ->json();
    
  • rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0

    3) VIEW definition for TripDB

    VIEW `TripDB` AS
    
    select  `O`.`OrderID` AS `OrderID`,
             `T`.`TripID` AS `TripID`,
            `T`.`Created` AS `Created`,
           `T`.`Modified` AS `Modified`,
               `T`.`Name` AS `Name`,
         `T`.`PickupTime` AS `PickupTime`,
    cast((to_days(`T`.`PickupTime`) - to_days(curdate())) as signed) AS `DaysOut`,
     `T`.`PickupLocation` AS `PickupLocation`,
    `T`.`DropoffLocation` AS `DropoffLocation`,
        `T`.`VehicleType` AS `VehicleType`,
            `T`.`NumPass` AS `NumPass`,
            `T`.`NumBags` AS `NumBags`,
           `T`.`CostTrip` AS `CostTrip`,
         `T`.`CostExtras` AS `CostExtras`,
            `T`.`CostTip` AS `CostTip`,
            `T`.`CostTax` AS `CostTax`,
                `O`.`Fee` AS `CostFee`,
          `T`.`CostTotal` AS `CostTotal`,
            `T`.`Mileage` AS `Mileage`,
           `T`.`Duration` AS `Duration`,
              `T`.`Tolls` AS `Tolls`,
            `T`.`MapLink` AS `MapLink`,
             `T`.`Status` AS `Status`,
             `O`.`userid` AS `userid`,
           `U`.`username` AS `username`,
               `U`.`name` AS `userfullname`,
              `U`.`phone` AS `userphone`,
              `U`.`email` AS `useremail`,
               `P`.`Name` AS `PassName`,
              `P`.`Phone` AS `PassPhone`,
    (case when (isnull(`P`.`SMS`) or (`P`.`SMS` = 'No EMail')) then `U`.`email` else `P`.`SMS` end) AS `PassEMail`,
    (case when isnull(`D`.`Name`) then 'Unassigned' else `D`.`Name` end) AS `DriverName`,
    (case when isnull(`D`.`Phone`) then 'Unassigned' else `D`.`Phone` end) AS `DriverPhone`,
    (case when isnull(`C`.`Year`) then 'Unassigned' else `C`.`Year` end) AS `VehicleYear`,
    (case when isnull(`C`.`Make`) then 'Unassigned' else `C`.`Make` end) AS `VehicleMake`,
    (case when isnull(`C`.`Model`) then 'Unassigned' else `C`.`Model` end) AS `VehicleModel`,
    (case when isnull(`C`.`Color`) then 'Unassigned' else `C`.`Color` end) AS `VehicleColor`,
    (case when isnull(`C`.`Plate`) then 'Unassigned' else concat(`C`.`ST`,' ',`C`.`Plate`) end) AS `VehiclePlate`,
    (case when isnull(`A`.`userid`) then 'Unassigned' else (case when (`A`.`userid` = '1') then 'Bronze' else (case when (`A`.`userid` = '2') then 'Silver' else (case when (`A`.`userid` = '3') then 'Gold' else `A`.`userid` end) end) end) end) AS `AffiliateID`,
    (case when isnull(`A`.`Fare`) then 'No Value' else `A`.`Fare` end) AS `ValueFare`,
    (case when isnull(`A`.`Extras`) then 'No Value' else `A`.`Extras` end) AS `ValueExtras`,
    (case when isnull(`A`.`Tip`) then 'No Value' else `A`.`Tip` end) AS `ValueTip`,
    (case when isnull(`A`.`Tax`) then 'No Value' else `A`.`Tax` end) AS `ValueTax`,
    (case when isnull(`A`.`Total`) then 'No Value' else `A`.`Total` end) AS `ValueTotal`,
    (case when isnull(`A`.`Status`) then 'Unassigned' else `A`.`Status` end) AS `FareStatus`,
    (case when isnull(`A`.`Modified`) then '2001-01-01 00:00:01' else `A`.`Modified` end) AS `FareModified`,
    (case when isnull(`F`.`Airport`) then 'Ground' else `F`.`Airport` end) AS `Airport`,
    (case when isnull(`F`.`Airline`) then '' else `F`.`Airline` end) AS `Airline`,
    (case when isnull(`F`.`Flight`) then '' else `F`.`Flight` end) AS `Flight`,
    (case when isnull(`F`.`Time`) then '' else `F`.`Time` end) AS `FlightTime`,
    (case when isnull(`V`.`username`) then 'Unassigned' else `V`.`username` end) AS `AffiliateUser`,
    (case when isnull(`V`.`name`) then '' else `V`.`name` end) AS `AffiliateName`,
    (case when isnull(`V`.`phone`) then '' else `V`.`phone` end) AS `AffiliatePhone`,
    (case when isnull(`V`.`email`) then '' else `V`.`email` end) AS `AffiliateEMail`,`O`.`Notes` AS `Notes`,
    (case when isnull(`R`.`CompanyBrand`) then '' else `R`.`CompanyBrand` end) AS `AffiliateCompany`,
      count(`S`.`TripID`) AS `NumStop`,
           `A`.`DriverID` AS `DriverID`,
          `A`.`VehicleID` AS `VehicleID`
    
    from ((((((((((`Booked_Trips` `T` left join `Booked_Orders` `O` on((`T`.`OrderID` = `O`.`OrderID`)))
                                      left join `Booked_Passengers` `P` on((`T`.`TripID` = `P`.`TripID`)))
                                      left join `Booked_Flights` `F` on((`T`.`TripID` = `F`.`TripID`)))
                                      left join `Booked_Stops` `S` on((`T`.`TripID` = `S`.`TripID`)))
                                      left join `Affiliate_Trips` `A` on((`A`.`TripID` = `T`.`TripID`)))
                                      left join `Users` `U` on((`O`.`userid` = `U`.`userid`)))
                                      left join `Users` `V` on((`V`.`userid` = `A`.`userid`)))
                                      left join `Affiliate_Settings` `R` on((`R`.`userid` = `A`.`userid`)))
                                      left join `Affiliate_Drivers` `D` on((`D`.`ID` = `A`.`DriverID`)))
                                      left join `Affiliate_Vehicles` `C` on((`C`.`ID` = `A`.`VehicleID`)))
    
    group by `T`.`TripID`;
    
  • allanallan Posts: 61,744Questions: 1Answers: 10,111 Site admin

    1) I didn't even know tables with mjoin could be edited

    They can and they can't. I wouldn't recommend it! It is possible with the PHP libraries to edit a many joined table, but you need to submit the values for the whole row in a single field. This is not something that the GUI supports without a specific and custom developed field type plug-in. If you don't do that there is significant risk of the data being destroyed. For this reason you won't find any examples of it on this site.

    then a bunch of my data disappears until reload.

    If the data is originally coming from the view, which I hadn't realised before, then you would need to query the view to get the full data for the row again. Perhaps the easiest way of doing that would be to use ajax.reload() inside a submitComplete event handler.

    I had to make views because I could never figure out how to link so much stuff together using your PHP library alone. This sort of thing has been a problem for the past 2 years of development using your tools and I still don't understand how to do it right.

    I'm sorry to hear that the pre-built libraries don't do everything you need. They never will provide the full flexibility of SQL - that simply isn't a goal of those libraries. They are designed to make 80% of use cases as easy as possible. The remaining 20% (roughly) would require some custom code, possibly not using the pre-built libraries at all any instead using your own code for your specific use case.

    For example using a VIEW to get the data as you want it is a very good way of populating the table.

    using inline edit... instead of just the mjoin data disappearing (as expected) the entire row disappears

    It sounds like you have updated form 1.4 or earlier to 1.5 and not taken account of the fact that only the field value that was changed is now submitted. There is upgrade documentation about that available here. My guess is that if you use submit: 'allIfChanged' it will restore what you expect.

    Allan

  • rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0

    There is still some strange issue. I have added submit: 'allIfChanged';

        // Activate an inline edit on click of a table cell
        $('#tblOrderTrips').on( 'click', 'tbody td:not(:first-child)', function (e)
         {editOrderTrips.inline(this, {submitOnBlur: true, submit: 'allIfChanged'});
         }                      );
    

    ...and now the row doesn't disappear, however, the field I change still renders wrong...

          'ajax': {'url': '/api/tables/getOrderTrips.php?region='+userRegion+'&order='+$('#selOrder').val(),
                   'complete': function() {CalculateTotals()}
                  },
    'rowCallback': function() {CalculateTotals()},
           'dom': '<"pull-right"T>rt',
       'columns': [    {'data': null, 'render': function() {return ''}},
                       {'sorting': false, 'data': 'CostTip', 'render': function(data) {if (data == 0)
                                                                                        {return '<center><span style="color: red"><b>CASH</b></span></center>'}
                                                                                       else   
                                                                                        {return '<center><b>$' + data + '</b></center>'}
                                                                                      }
                       },
    
    

    When the trip is added, the value is 0 and displays CASH. If I inline-edit the value and change it to 10.00, I briefly see $10.00 and then it changes back to CASH which is wrong even according to the JSON sent back:

    CostTip: "10.00"
    

    If I then reload the page it is now properly showing $10.00.

    If I then change it to 11.00 it works properly displaying $11.00.

    ...so again, something is different on first edit after adding a new row (by my own sql methods) and calling refresh, then on an editing a row after refreshing the entire page.

       {'ajax': '/api/tables/setOrderTrips.php?region='+userRegion+'&order='+$('#selOrder').val(),
          'table': '#tblOrderTrips',
          'fields': [ {'label': 'Order ID'       , 'name': 'OrderID'   , 'type': 'hidden'},
                      {'label': 'Driver Gratuity', 'name': 'CostTip'   , 'type': 'text'},
                    ]
         }                                          );
    
    

    It's like the row is inline editing properly, but then when it auto-refreshes it is doing it from a different (maybe non-existent) field, instead of the field it just properly edited.

  • allanallan Posts: 61,744Questions: 1Answers: 10,111 Site admin

    At a guess it sounds like the create might not be including the id, or there is an event handler that is otherwise updating the field.

    I've just created an account at the link you gave above with my name and details. Could you upgrade that to admin as you mentioned and let me know how I can see this error in the app so I can debug it? Feel free to PM that info if you'd rather it not be public!

    Allan

  • rpmccormickrpmccormick Posts: 107Questions: 13Answers: 0

    I sent you a PM, and purchased a support contract.

    For others reading this thread, this is my latest idea:
    "A fix might simply be specifying Field for each row instead of letting the code determin field-name automatically.... how do you do that again?"

  • allanallan Posts: 61,744Questions: 1Answers: 10,111 Site admin

    Hi,

    Thanks for the PM - I've replied back there. I'll update this thread when we've resolved the issue in the PM.

    Regards,
    Allan

This discussion has been closed.