Muhammed Sami
Muhammed Sami

Reputation: 110

Can anyone tell the difference between find and findOne in yii2?

I've searched too much but stil do not understand the problem with the code above.

        $this->_entity_model = $entity_class_name::findOne(['service_request ' => $this->id]);
        $t = $entity_class_name::find()->where(['service_request ' => $this->id])->one();


        var_dump(isset($this->_entity_model));
        var_dump(isset($t));
        exit;

as you can see I've two queries, one with find and the other one with findOne. Problem is : the first var_dump return false! the second true ? I do not figure out how this can be possible ?

with the first query I get

'Key "service_request " is not a column name and can not be used as a filter'.

But the second is returning well(true) the result.

$this->id is 127

Update :

 $this->_entity_model = $entity_class_name::find()->where(['service_request' => $this->id])->one();

I now can use this but i get error below: Invalid argument supplied for foreach()

my rules

<?php

namespace app\models;

use app\components\Defaults;
 use Yii;

class IndividualTrader extends Entreprise
{ 
   const PROCESSING_IFU = 'processing_ifu';

public static function model($className = __CLASS__)
{
    return parent::model($className);
}

public function rules()
{
    return array_merge(parent::rules(),
        [
            [['service_request','integer']],
            [['emplois_generes','ca'], 'required', 'on' => self::SCENARIO_FORM],
            [['identifiant_fiscal'], 'required', 'on' => self::PROCESSING_IFU],
            [['activite'], 'required', 'on' => self::SCENARIO_ACTIVITY],
            [['forme_juridique'], 'default', 'value' => FormeJuridique::PP],
            [['emplois_generes'], 'number', 'min' => 0],

            [['objet_social'], 'default', 'value' => ''],
          //  [['identifiant_fiscal, activite, ville_taxe_professionnelle'], 'required', 'on' => 'fisc'],
            [['raison_sociale', 'identifiant_fiscal', 'registre_commerce'], 'unique'],
            /*[['has_nationalite'],'safe','on'=>self::SCENARIO_GUIDE],*/
            [['registre_commerce_declare', 'date_rc'], 'validateRequiredRegistrationData', 'registration_attribute' => 'has_already_registered_rccm', 'validate_if_value' => 1, 'on' => self::SCENARIO_FORM],
            [['telephone'], 'ext.LPNValidator.LPNValidator', 'defaultCountry' => Defaults::COUNTRY_PHONE_CODE, 'on' => self::SCENARIO_CONTACT],
            [['prenom_contact', 'nom_contact', 'telephone', 'email'], 'required', 'on' => self::SCENARIO_CONTACT],
            [['activite'], 'required', 'on' => self::SCENARIO_FORM],
            [['activite_secondaire'], 'compare', 'compareAttribute' => 'activite', 'operator' => '!=', 'message' => Yii::t('app', "{compareAttribute} and {attribute} must not be equal"), 'on' => self::SCENARIO_FORM],
            [['trade_name,company_name'], 'safe', 'on' => TradeNameSearch::SCENARIO_TRADE_NAME_SEARCH]
        ]
    );
}

public function init()
{
    parent::init();
    // initialize attributes with default values
    $this->debut_activite = date('d-m-Y');
    $this->forme_juridique = FormeJuridique::PP;
    $this->date_fin_activite = '31-12';
    $this->duree_activite = 99;
}

public function isCitizen()
{
    return $this->has_nationalite == 1;
}

public function isForeign()
{
    return isset($this->has_nationalite) && $this->has_nationalite == 0;
}

public function hasRegisteredRccm()
{
    return $this->has_already_registered_rccm == 0;
}

public function needsToProveAddress()
{
    return $this->has_director_different_address == 1;
}

public function getTotalSalaries()
{
    return intval($this->emplois_generes) + intval($this->emplois_etrangers);
}

public function isActivityAuthorizationRequired()
{
    return isset($this->is_activity_auth_needed) && $this->is_activity_auth_needed == 1;
}

public function isSpecialActivity()
{
    return (isset($this->is_activity_auth_needed) && $this->is_activity_auth_needed == 1) || (isset($this->is_import) && $this->is_import == 1);
}

public function hasCNI()
{
    return !isset($this->ppCommercant, $this->ppCommercant->type_piece_identite) ? false : ($this->ppCommercant->type_piece_identite == TypePieceIdentite::CNI);
}

public function getPrimaryAddress()
{
    $adres = (new Adresse())->findByAttributes(array('entreprise' => $this->id, 'type_adresse' => TypeAdresse::PRIMARY_ADDRESS));
    return ($adres->same_address_pp == 0) ? $this->getSecondaryAddress() : $adres;
}

public function getSecondaryAddress()
{
    return (new Adresse())->findByAttributes(array('entreprise' => $this->id, 'type_adresse' => TypeAdresse::SECONDARY_ADDRESS));
}

public function getInlinePrimaryAddress()
{
    $address = $this->getPrimaryAddress();
    return !isset($address) ? '' : $address->getInlineAdresse();
}


public function isPP()
{
    return true;
}

public function getRccmViewName()
{
    return '_pp';
}

/**
 * @param $name
 * @param string $operator
 * @return CDbCriteria
 */

public function getFullNameCriteria($name, $service_request_alias, $operator = 'AND')
{
    $criteria = new CDbCriteria;
    //    $criteria->select = "(select CONCAT(pp.nom , CONCAT('|', CONCAT(pp.prenom ,CONCAT('|',ent.nom_commercial)))) from tbl_personne_physique pp, tbl_entreprise ent where pp.id = ent.pp_commercant and ent.service_request = ".$t.".id) as full_name";
    $full_name = "(select CONCAT(pp.nom , '|' , pp.prenom, '|' ,ent.nom_commercial) from tbl_personne_physique pp, tbl_entreprise ent where pp.id = ent.pp_commercant and ent.service_request = " . $service_request_alias . ".id)";
    $criteria->compare($full_name, $name, true, $operator);
    return $criteria;

}
}

Entreprise

use app\components\Utils;
use app\models\_base\BaseEntreprise;
use app\models\PieceJustificative;
use Yii;
use yii\db\ActiveQuery;

class Entreprise extends BaseEntreprise
{
const WORKFLOW_ID = 'swEntreprise';
const STATUS_DRAFT = 'draft';
const STATUS_DRAFT_CORRECTION = 'draft_correction';
const STATUS_REVISION = 'revision';
const STATUS_REVISION_RETURNED = 'revision_returned';
const STATUS_TRAITEMENT = 'traitement';

// Workflow.
const STATUS_CORRECTION = 'correction';
const STATUS_RETRAIT = 'retrait';
const STATUS_PAIEMENT = 'paiement';
const STATUS_FINISHED = 'finished';
const STATUS_REJECTED = 'rejected';
const STATUS_ROLE_RC = 'role_rc';
const STATUS_ROLE_IF = 'role_if';
const STATUS_ROLE_PATENTE = 'role_patente';
const STATUS_ROLE_CAISSE = 'role_caisse';
const STATUS_VALID = 'valid';
const STATUS_RETURNED = 'returned';
const INSTRUCTION_PENDING = 0;
const INSTRUCTION_VALID = 1;
const INSTRUCTION_REJECTED = 2;
const REGISTRATION_RCCM = "RCCM";
const REGISTRATION_CC = "CC";
const RCCM = "RCCM";
const DGT = "DGT";
const CNSS = "CNSS";
const CARTE = "CARTE";
const ANNONCE = "ANNONCE";
const CNPS = "CNPS";
const DGI_IF = "IFU";
const DGI_TP = "TP";
const AL  ='AL';
const IMPORT = "IMPORT";
// SCENARIOS
const SCENARIO_GUIDE = 'guide';
const SCENARIO_FORM = 'form';
const SCENARIO_CONTACT = 'contact';
const SCENARIO_ACTIVITY_FORM = 'activity_form';
const SCENARIO_ACTIVITY = 'activite';
//DETERMINANTS
const EXPORT = "EXPORT";
const POUVOIR = "POUVOIR";
const MARIE = "MARIE";
const NATIONALITE = "NATIONALITE";
const CNI = "CNI";
const CASIER = "CASIER";
const HONNEUR = "HONNEUR";
const ASSOCIE_PP = "ASSOCIE_PP";
const ASSOCIE_PM = "ASSOCIE_PM";
const AGREMENT = "AGREMENT";
const PLUS = "+";
const MINUS = "-";
const DUREE_ACTIVITE = 99;
const DUREE_IF = 10;
const ONLINE = 1;
const OFFLINE = 2;
const COMMERCANT = 1;
const ENTREPRENANT = 3;
//PARAMS
const SOCIETE = 2;
private static $_role;
public $delai = 0;
/**
 * @var $keyword string
 * @var $name string
 * @var $service string
 */
public $keyword;
public $name;
public $service;
public $inscription;
private $_role_by_status = null;
private $_determinants;
private $_types_pieces;
private $_types_pieces_originaux;
private $_pieces_originaux;
private $_pieces_tobecertified;
private $_formulaires_tobesigned;
private $_is_PP;
private $_deletable;
private $_is_Entreprenant;

public static function model($className = __CLASS__)
{
    return parent::model($className);
}

public function rules()
{
    return array_merge(parent::rules(), [
        [['name', 'service','keyword', 'inscription'], 'safe'],
        //array('cc_titulaire, cc_titulaire_rpt, cc_suppleant, cc_suppleant_rpt', 'length', 'max' => 128),
        [['devise_capital','activite', 'mode_exploitation', 'journal_annonce'], 'string', 'max' => 500],
        [['date_fin_activite'], 'string', 'max' => 20],
        [['debut_activite', 'date_rc'], 'date', 'format' => Yii::$app->formatter->dateFormat, 'message' => Yii::t('app', 'The format of {attribute} is invalid.')],
        //array('exploitant_rccm', 'length', 'max' => 100),
        //array('exploitant_name', 'length', 'max' => 250),
        [['debut_activite'], 'date', 'format' => Yii::$app->formatter->dateFormat, 'message' => Yii::t('app', 'The format of {attribute} is invalid.')],
        [['email'], 'email'],
    ]);
}

public static function getCustomStatuslistData()
{
    return array(
        self::getStatusLbl(self::STATUS_DRAFT) => Yii::t('app', "STATUS_DRAFT"),
        self::getStatusLbl(self::STATUS_ROLE_CAISSE) => Yii::t('app', "STATUS_CAISSE"),
        self::getStatusLbl(self::STATUS_REVISION) => Yii::t('app', "STATUS_REVISION_CUSTOM"),
        self::getStatusLbl(self::STATUS_CORRECTION) => Yii::t('app', "STATUS_CORRECTION"),
        self::getStatusLbl(self::STATUS_ROLE_RC) => Yii::t('app', "STATUS_TRAITEMENT_RC"),
        self::getStatusLbl(self::STATUS_ROLE_IF) => Yii::t('app', "STATUS_TRAITEMENT_IF"),
        self::getStatusLbl(self::STATUS_ROLE_PATENTE) => Yii::t('app', "STATUS_TRAITEMENT_TP"),
        self::getStatusLbl(self::STATUS_RETRAIT) => Yii::t('app', "STATUS_RETRAIT_CUSTOM"),
        self::getStatusLbl(self::STATUS_FINISHED) => Yii::t('app', "STATUS_FINISHED"),
    );
}

Thanks for helping.

Upvotes: 0

Views: 1921

Answers (3)

gittinOld
gittinOld

Reputation: 55

Sergio highlights the main difference between using findOne and find().

The gotcha here can be if we've placed a pre-condition on our models 'find()' method.

ie:

/**
 * @inheritdoc
 * @return \common\models\UserQuery the active query used by this AR class.
 */
public static function find()
{
    $query = new \common\models\UserQuery(get_called_class());
    
    return $query->where(['user.deleted_by' => 0]);

}

Now if we use findOne($id) or findOne(['id'=>$id]) in our controller or elsewhere, the query condition will look like 'where user.deleted_by = 0 and id = 1', which may or may not have the desired affect. As Sergio said... we can mimic findOne with find()->andWhere... but not with find()->where(['id' => $id]).

find()->where(['id' => $id]) is explicit in it's where clause and doesn't allow other conditions to be placed into it from somewhere else in the request.

Obviously to get a result without the pre-condition set in the Model::find() method... we can only use find()->where(['id' => $id])

I couldn't see the find() method in your Models, so this may not have been the issue at all... But I just had to mention this little gotcha to remind myself and maybe others that... these two are not quite the same :)

Upvotes: 0

Sergio Codev
Sergio Codev

Reputation: 104

For a better understanding of the differences in these methods, I will give examples to compare how you can get data from the database in both ways:

// find a single customer whose primary key value is 10
$customer = Customer::findOne(10);

// the above code is equivalent to:
$customer = Customer::find()->where(['id' => 10])->one();

// find the customers whose primary key value is 10, 11 or 12.
$customers = Customer::findOne([10, 11, 12]);

// the above code is equivalent to:
$customers = Customer::find()->where(['id' => [10, 11, 12]])->one();

// find the first customer whose age is 30 and whose status is 1
$customer = Customer::findOne(['age' => 30, 'status' => 1]);

// the above code is equivalent to:
$customer = Customer::find()->where(['age' => 30, 'status' => 1])->one();

The implementation of the method in the framework looks like this (in BaseActiveRecord.php):

   /**
     * {@inheritdoc}
     * @return static|null ActiveRecord instance matching the condition, or `null` if nothing matches.
     */
    public static function findOne($condition)
    {
        return static::findByCondition($condition)->one();
    }

And method findByCondition:

    protected static function findByCondition($condition)
    {
        $query = static::find();

        if (!ArrayHelper::isAssociative($condition)) {
            // query by primary key
            $primaryKey = static::primaryKey();
            if (isset($primaryKey[0])) {
                // if condition is scalar, search for a single primary key, if it is array, search for multiple primary key values
                $condition = [$primaryKey[0] => is_array($condition) ? array_values($condition) : $condition];
            } else {
                throw new InvalidConfigException('"' . get_called_class() . '" must have a primary key.');
            }
        }

        return $query->andWhere($condition);
    }

Note that this method returns return $query->andWhere($condition);

This is the one difference.

In order for both options to return the same thing, the code needs to be changed like this:

$this->_entity_model = $entity_class_name::findOne(['service_request' => $this->id]);

//But where condition is similar andWhere in this case $t = $entity_class_name::find()->andWhere(['service_request' => $this->id])->one();

var_dump(isset($this->_entity_model));
var_dump(isset($t));
exit;

P.S.:'Key "service_request " is not a column name and can not be used as a filter'.

This is because a space is set in the column name "service_request ". Needed "service_request"

Upvotes: 1

Martin Dimitrov
Martin Dimitrov

Reputation: 1304

There is one main difference:

Model::findOne() is equal to Model::find()->one().

In your case, you should try with:

$this->_entity_model = $entity_class_name::findOne(['service_request ' => $this->id]);
$t = $entity_class_name::find()->where(['service_request ' => $this->id])->one();


var_dump(isset($this->_entity_model));
var_dump(isset($t));
exit;

What probably happens is, there is no such record in the DB. Your first query sees that and returns null, but your second one returns an ActiveRecord object. One possible mistake I see is the extra space after service_request. Try deleting it, thus making the query:

$this->_entity_model = $entity_class_name::findOne(['service_request' => $this->id]);

Upvotes: 1

Related Questions