Doctrine_Record_Exception “Couldn't call Doctr

2019-09-16 20:05发布

问题:

I'm having this issue and I can't find what is wrong. I'm trying to update object before execute the form save method and I do as follow (I wrote the whole class just in case):

class SdrivingMaquinaForm extends BaseSdrivingMaquinaForm {

    protected $current_user;

    public function configure() {
        $this->current_user = sfContext::getInstance()->getUser()->getGuardUser();

        unset($this['updated_at'], $this['created_at']);

        $this->widgetSchema['idempresa'] = new sfWidgetFormInputHidden();
        $id_empresa = $this->current_user->getSfGuardUserProfile()->getIdempresa();
        $this->setDefault('idempresa', $id_empresa);

        $this->widgetSchema['no_emisor'] = new sfWidgetFormDoctrineChoice(array('model' => 'SdrivingEmisor', 'add_empty' => 'Seleccione un Emisor', 'table_method' => 'fillChoice'));
        $this->validatorSchema['idempresa'] = new sfValidatorPass();
        $this->validatorSchema['no_emisor'] = new sfValidatorPass();
    }

    protected function doUpdateObject($values) {
        parent::doUpdateObject($values);

        if (isset($this['no_emisor'])) {
            if ($this->isNew()) {
                $sdrivingMaquinaEmisor = new SdrivingMaquinaEmisor();
                $this->getObject()->setSdrivingMaquinaEmisor($sdrivingMaquinaEmisor);
            } else {
                $sdrivingMaquinaEmisor = $this->getObject()->getSdrivingMaquinaEmisor();
            }

            $sdrivingMaquinaEmisor->setIdemisor($this->values['no_emisor']);
        }
    }
}

This is the schema.yml related to that form:

SdrivingMaquina:
  actAs: 
    Timestampable: ~
  columns:
    idmaquina: { type: integer(8), autoincrement: true, notnull: true, primary: true }
    idempresa: { type: integer(4), notnull: true }
    patente: { type: string(12), notnull: true }
  relations:
    Empresa: { local: idempresa, class: SdrivingEmpresa, type: one, foreignType: one, foreignAlias: MaquinaEmpresa, onDelete: CASCADE, onUpdate: CASCADE }
SdrivingMaquinaEmisor:
  actAs: 
    Timestampable: ~
  columns:
    idmaquinaemisor: { type: integer(8), primary: true, autoincrement: true }
    idmaquina: { type: integer(8), notnull: true }
    idemisor: { type: integer(8), notnull: true }
  relations:
    SdrivingEmisor: { onDelete: CASCADE, local: idemisor, foreign: idemisor, type: one }
    SdrivingMaquina: { onDelete: CASCADE, local: idmaquina, foreign: idmaquina, type: one }

As you may notice none relation is many to many. When I send the form I get this error:

Couldn't call Doctrine_Core::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references.

And I couldn't find where the error is so any help will be appreciated. Also I notice this in the stack trace:

at SdrivingMaquinaForm->doUpdateObject(array('idmaquina' => null, 'idempresa' => '1', 'patente' => 'TB58922', 'no_emisor' => '2'))

Why idmaquina is null? There should go the value of the maquina I'm creating in the same moment. Should I change my logic and update the relation values after save the maquina? In that case how I get the id of the newest maquina created?

EDIT template: _form.php

<?php use_stylesheets_for_form($form) ?>
<?php use_javascripts_for_form($form) ?>

<div class="row-fluid">
    <form action="<?php echo url_for('maquina/' . ($form->getObject()->isNew() ? 'create' : 'update') . (!$form->getObject()->isNew() ? '?idmaquina=' . $form->getObject()->getIdmaquina() . '&idempresa=' . $form->getObject()->getIdempresa() : '')) ?>" method="post" <?php $form->isMultipart() and print 'enctype="multipart/form-data" ' ?>>
        <?php if (!$form->getObject()->isNew()): ?>
            <input type="hidden" name="sf_method" value="put" />
        <?php endif; ?>
        <?php echo $form->renderHiddenFields(true) ?>
        <?php echo $form->renderGlobalErrors() ?>

        <div class="span4">
            <label><?php echo $form['patente']->renderLabel() ?></label>
            <?php echo $form['patente'] ?>
            <span class="help-block"><?php echo $form['patente']->renderError() ?></span>
        </div>
        <div class="span4">
            <label><?php echo $form['no_emisor']->renderLabel('Emisor') ?></label>
            <?php echo $form['no_emisor'] ?>
            <span class="help-block"><?php echo $form['no_emisor']->renderError() ?></span>
        </div>
        <div class="clearfix"></div>
        <p class="right-align-text marginTop">
            <button type="button" class="btn" id="cancel-btn"><?php echo __('Cancelar') ?></button>
            <input type="submit" value="<?php echo __('Guardar') ?>" class="btn btn-success" />
        </p>
    </form>

    <?php if ($sf_user->hasFlash('error')): ?>
        <div class="alert alert-error">
            <h4>Error!</h4>
            <?php echo $sf_user->getFlash('error') ?>
        </div>
    <?php endif; ?>
</div>

<script>
    $(function() {
        $('#cancel-btn').click(function() {
            history.go(-1);
            $('#myTab a[href="#<?php echo $sf_user->getFlash('activeTab', 'usuarios'); ?>"]').tab('show');
        });
    });
</script>

Action class: action.class.php

class maquinaActions extends sfActions {

    public function executeIndex(sfWebRequest $request) {
        $this->sdriving_maquinas = Doctrine_Core::getTable('SdrivingMaquina')->createQuery('a')->execute();
    }

    public function executeNew(sfWebRequest $request) {
        $this->getUser()->setFlash('activeTab', 'maquinas');
        $this->form = new SdrivingMaquinaForm();
    }

    public function executeCreate(sfWebRequest $request) {
        $this->forward404Unless($request->isMethod(sfRequest::POST));
        $this->form = new SdrivingMaquinaForm();
        $this->processForm($request, $this->form);
        $this->setTemplate('new');
    }

    public function executeEdit(sfWebRequest $request) {
        $this->forward404Unless($sdriving_maquina = Doctrine_Core::getTable('SdrivingMaquina')->find(array($request->getParameter('idmaquina'), $request->getParameter('idempresa'))), sprintf('Object sdriving_maquina does not exist (%s).', $request->getParameter('idmaquina'), $request->getParameter('idempresa')));
        $this->form = new SdrivingMaquinaForm($sdriving_maquina);
    }

    public function executeUpdate(sfWebRequest $request) {
        $this->forward404Unless($request->isMethod(sfRequest::POST) || $request->isMethod(sfRequest::PUT));
        $this->forward404Unless($sdriving_maquina = Doctrine_Core::getTable('SdrivingMaquina')->find(array($request->getParameter('idmaquina'), $request->getParameter('idempresa'))), sprintf('Object sdriving_maquina does not exist (%s).', $request->getParameter('idmaquina'), $request->getParameter('idempresa')));
        $this->form = new SdrivingMaquinaForm($sdriving_maquina);
        $this->processForm($request, $this->form);
        $this->setTemplate('edit');
    }

    public function executeDelete(sfWebRequest $request) {
        $this->forward404Unless($sdriving_maquina = Doctrine_Core::getTable('SdrivingMaquina')->find(array($request->getParameter('idmaquina'), $request->getParameter('idempresa'))), sprintf('Object sdriving_maquina does not exist (%s).', $request->getParameter('idmaquina'), $request->getParameter('idempresa')));
        $sdriving_maquina->delete();
        $this->getUser()->setFlash('activeTab', 'maquinas');
        $this->redirect('admin/index');
    }

    protected function processForm(sfWebRequest $request, sfForm $form) {
        $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
        if ($form->isValid()) {
//            try {
            $sdriving_maquina = $form->save();

            $this->getUser()->setFlash('activeTab', 'maquinas');
            $this->redirect('admin/index');
//            } catch (Exception $e) {
//                $this->getUser()->setFlash('error', 'Los valores no pueden estar duplicados, verifíquelo e inténtelo nuevamente');
//            }
        }
    }

}

EDIT 2

After test what been told to me here are the results:

originalForm: array(5) { ["idmaquina"]=> string(0) "" ["idempresa"]=> string(1) "1" ["_csrf_token"]=> string(32) "54e5e3984c245e60b17abbf32518d95e" ["patente"]=> string(7) "TB58966" ["no_emisor"]=> string(1) "2" }

Fatal error: Call to a member function getValue() on a non-object in /var/www/html/monitor/apps/frontend/modules/maquina/actions/actions.class.php on line 56

So idmaquina never gets a value

EDIT 3: solution The first thing I do was fix the schema.yml (see this post for best information and not repeat the solution here). Then in SdrivingMaquinaForm.class.php file I change this:

protected function doUpdateObject($values) {
    parent::doUpdateObject($values);

    if (isset($this['no_emisor'])) {
        if ($this->isNew()) {
            $sdrivingMaquinaEmisor = new SdrivingMaquinaEmisor();
            $this->getObject()->setSdrivingMaquinaEmisor($sdrivingMaquinaEmisor);
        } else {
            $sdrivingMaquinaEmisor = $this->getObject()->getSdrivingMaquinaEmisor();
        }

        $sdrivingMaquinaEmisor->setIdemisor($this->values['no_emisor']);
        $this->getObject()->getSdrivingMaquinaEmisor()->setIdemisor($this->values['no_emisor']);
    }
}

protected function updateDefaultsFromObject() {
    parent::updateDefaultsFromObject();
    if (isset($this['no_emisor'])) {
        $this->setDefault('no_emisor', $this->getObject()->getSdrivingMaquinaEmisor()->getIdemisor());
    }
} 

of course also I set idempresa at configure() method as follows:

$this->widgetSchema['idempresa'] = new sfWidgetFormInputHidden();
$id_empresa = $this->current_user->getSfGuardUserProfile()->getIdempresa();
$this->setDefault('idempresa', $id_empresa);

That was all, after fix the schema and add the code things works as I want

回答1:

I may be wrong but I think you should add the widget and validator for idmaquina field in your form configure() function.

$this->widgetSchema['idmaquina'] = new sfWidgetFormInputHidden();
$this->validatorSchema['idmaquina'] = new sfValidatorChoice(array('choices' => array($this->getObject()->get('idmaquina')), 'empty_value' => $this->getObject()->get('idmaquina'), 'required' => false));

Since you havent created it in your overloaded form, its never saving its value into the form, and when you send the form, idmaquina will be null. You can easily debug it with a simple var_dump of the form field idmaquina.

After changing your form, go to command line and in your symfony project folder, clear symfony cache with: symfony cc

Please add the following code and check for its value:

In doUpdateObject:

doUpdateObject($values){
    echo "values: "; var_dump($values); echo "<br />";
    ///...
}

In processForm:

protected function processForm(sfWebRequest $request, sfForm $form) {
    $originalForm = $request->getParameter($form->getName()), 
    $request->getFiles($form->getName());
    echo "originalForm: "; var_dump($originalForm); echo "<br />";
    echo "idmaquina: " . $originalForm['idmaquina']->getValue(); echo "<br />";
    //...
}

You need to make sure that you are setting and sending the value of idmaquina in your form.