1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Do you use replace within the datawriter or in model?

Discussion in 'XenForo Development Discussions' started by Marcus, Oct 15, 2012.

?

I put my replace function

  1. in datawriter

    3 vote(s)
    60.0%
  2. in model

    2 vote(s)
    40.0%
  1. Marcus

    Marcus Well-Known Member

    There is no replace - mysql - function in ZEND. Do you do your "replace" stuff in the datawriter (checking for an existing id and updating it if it exists, otherwise create a new entry)? Or do you just use "REPLACE ..." in your model (I do that)? However I would love to hear benefits of using replace in the datawriter, although it is much more code.
     
  2. Robbo

    Robbo Well-Known Member

    What? The datawriter handles all of this? It isn't wrong to use REPLACE in certain situations, but it would be for specific situations which I doubt you actually need.
     
  3. Jeremy P

    Jeremy P Well-Known Member

    Are you reading from the database, or manipulating data retrieved from the database? Model.
    Are you doing any writing to the database? Datawriter.

    There are few exceptions.

    It sounds like you'd want to do something like:
    PHP:
    $dw XenForo_DataWriter::create('XenForo_DataWriter_Whatever');
    $dw->setExistingData($data); // this can either be an array of an entire row, or the value of the primary key (usually id)
    $dw->set('column''newValue');
    $dw->save();
     
    Chris D likes this.
  4. Marcus

    Marcus Well-Known Member

    I use replace when I want to do very easy stuff like:

    table car (car_id, owner_id) where car_id and owner_id are keys.

    If a car has no owner, it is not even in the table. If a car gets an owner, I use REPLACE INTO car (2,5) to insert values (2,5). If the owner changes, I use REPLACE INTO car (2,6) to change values 2,5 to 2,6. Do you have an idea how you would accomplish that in the datawrater?
     
  5. Robbo

    Robbo Well-Known Member

    Like was posted above? It's what datawriters do...
     
    Chris D likes this.
  6. Chris D

    Chris D XenForo Developer Staff Member

    Here's a practical example for you.

    PHP:
    $writer XenForo_DataWriter::create('YourAddOn_DataWriter_YourDataWriter');
     
    $data = array(
        
    'car_id' => $carId,
        
    'owner_id' => $ownerId
    );

    $writer->setExistingData($carId);

    $writer->bulkSet($data);

    $writer->save;
    This creates your DataWriter (this could be your own or an extended XenForo writer depending on its usage) and then defines the data. This assumes you've already got the data in a variable elsewhere in the function. You then tell the DataWriter that the existing record can be found using the $carId variable. Finally, the data is bulkSet (because it is in an array, if you're only updating a single value, you can just use "set") and then saved. Once $writer->save is run, the data is written.
     
    Marcus likes this.
  7. Marcus

    Marcus Well-Known Member

    Thanks! If car_id is NULL and on the same time car_id is primary or part of a unique key, is the datawriter intelligent enough to insert the data?
     
  8. Robbo

    Robbo Well-Known Member

    No. It will throw an exception. You should be doing...

    if ($data['car_id'])
    {
    setExtingData here
    }

    You can see this pretty much in every spot a datawriter is used.
     
    Chris D likes this.
  9. Marcus

    Marcus Well-Known Member

    Let's roundup the datawriter method:

    1. I have to check if car_id exists
    2. If yes, I use setExistingData and save();
    3. If no, I have to tell the datawriter it should create a new entry?

    With replace, I just use $model->setMyreplace($dwData) and its fine. That looks much more elegant to me.
     
  10. Robbo

    Robbo Well-Known Member

    Well it is wrong. Simple. Unless there is a very specific reason to use REPLACE then you are doing it wrong.

    Also you don't tell it to create, if it doesn't received a call from setExistingData it will automatically just create.

    It also handles validation, security, pre and post events and probably most importantly is easily extended with add-ons.
     
    Chris D likes this.
  11. Chris D

    Chris D XenForo Developer Staff Member

    We're missing a load of information that would help us ascertain the best way of doing things, but I can't personally think of many examples where using replace would be better.

    But here's an example based on my notifications add-on.

    I have a list of Notifications...
    http://mysite.com/admin.php?notifications

    I have an action to add new notifications:
    http://mysite.com/admin.php?notifications/add

    And an action to edit existing notifications, e.g. to edit notification with an ID of 1:
    http://mysite.com/admin.php?notifications/1/edit

    Whenever I am adding a new notification or editing an existing one, ultimately I end up at an action called "save", e.g.:
    http://mysite.com/admin.php?notifications/save

    So, in my template where I edit the details of a notification (either new or existing) my form action will look like:
    <form action="{xen:adminlink 'notifications/save', $notification}" method="post"> ... </form>

    If it's an existing notification (i.e. if $notification contains data) the action will be:
    http://mysite.com/admin.php?notifications/1/save

    If it's a new notification (i.e. if $notification contains no data) the action will be:
    http://mysite.com/admin.php?notifications/save

    So... finally my Save action in PHP looks like this:

    PHP:
    public function actionSave()
    {
        
    $notificationId $this->_input->filterSingle('notification_id'XenForo_Input::UINT);
        
    // This pulls the notificationId out of the requested URL, e.g. if it's an existing notification then $notificationId will now contain 1

        
    $data $this->_input->filter(array(
            
    'name' => XenForo_Input::STRING,
            
    'other_data' => XenForo_Input::STRING
        
    ));

        
    $writer XenForo_DataWriter::create('Notifications_DataWriter_Notification');

        if (
    $notificationId)
        {
            
    $writer->setExistingData($notificationId);
        }
        
    // So, if notificationId exists, tell DataWriter to find the existing data.

        
    $writer->bulkSet($data);

        
    $writer->save();

        return 
    $this->responseRedirect(
            
    XenForo_ControllerResponse_Redirect::SUCCESS,
            
    XenForo_Link::buildAdminLink('notifications/edit'$notificationId)
        );
    }
     
    Marcus likes this.

Share This Page