Yii2 framework of those grueling pit

That point gossip

Since the last blog, already a year ago. Before Write it, always with a deep sense of guilt. It was torture for a long time, finally, still, hands.

To celebrate one thing : recently I started the gym. Sporty bike 45 minutes a day, swim 45 minutes really is (raw) cool (not) to (such) burst (dead).

Well, nonsense is completed, come to the question.


 

ActiveRecord is written inexplicable?

Ready knowledge

  1. ActiveRecordThe basic usage. If not understood, reference here .

Code site

/**
 * @property integer $id
 * @property string $name
 * @property string $detail
 * @property double $price
 * @property integer $area
 **/
class OcRoom extends ActivieRecord
{
    ...
}

Room $ = :: OcRoom the Find ()       // first remove an object. 
    -> SELECT ([ 'id'])         // remove only the 'id' column 
    -> WHERE ([ 'id' => 20 is ])
     -> One ();
 $ Room -> Save ();               // saved, find other fields in this row are written in the default value.

Summary of issues

The problem with this example is that:

  1. I removed from the database in a row, which is the code $room, but only out of the idfield, and other fields nature is the default.
  2. When my $room->save()time, that's the default field values can also be saved to the database gone. what !?
  3. In other words, when you want to save resources, do not remove all fields must be careful not to save, otherwise, a lot of data will be inexplicable to modify the default value.

Solution

However, we have any solution? It offers several ideas:

  1. Always pay attention to yourself, avoid not completely removed ActiveRecordto save.
  2. Inherited or modification ActiveRecord, so that, when the object find(), and a new field is not completely removed, calling save()method throws an exception.
  3. Inherited or modification ActiveRecord, so that, when the object find(), and a new field is not completely removed, call save()time method, save only taken over a field, other fields are ignored.

 

Your Transaction entered into force yet?

Code site

/**
 * @property integer $id
 * @property string $name
 **/
class OcRoom extends ActiveRecord
{
    public function rules()
    {
        return [['name','string','min'=>2,'max'=>10]];
    }
    ...
}
class OcHouse extends ActiveRecord
{
    public function rules()
    {
        return [['name','string','max'=>10]];
    }
    ...
}

A $ = new new OcRoom ();
 $ A -> name = '';                 // name is an empty string, does not satisfy the rules () conditions.

b $ = new new OcHouse ();
 $ b -> name = 'my room';          // name legally, can be saved.

Transaction $ = Yii :: $ App -> db-> beginTransaction ();
 the try {
     $ A -> the Save ();                // name field is not legitimate, can not be verified by, have returned false in validate () phase, will not be database stored procedure, so it does not throw an exception. 
    b $ -> the Save ();                // name field legitimate, can be stored properly.

    Transaction $ -> the commit ();    // After submitting found $ a failed save, and $ b saved successfully. 
}
 The catch ( Exception  $ E )
{
    Yii::error($e->getTraceAsString(),__METHOD__);
    $transaction->rollBack();
}

conclusion of issue

The problem with this code is that:

  1. We all know that $transaction's the whole raison d'etre is to ensure that the code stored in the database either all succeed, or all three fail.
  2. Obviously, in this case, transactionwe did not achieve the results we want: $abecause validate()never before, so $transation->commit()the time does not complain.

Solution

In $transationthe block, all of save()the return value must be determined, if it is false, directly thrown exception.


 

'Ym-d' not recognized?

Code site

OcRenterBill extends ActiveRecord
{
    public function rules()
    {
        return [
            ['start_time','date','format'=>'Y-m-d'],
        ];
    }
}

A $ = new new OcRenterBill ();
 $ A = '2015-09-12' ;
 $ A -> Save ();                  // being given, say wrong format

conclusion of issue

If at first, Yii framework on the error, this is not too pit. Pit of my development time on a Mac, this work can be completely normal, but after the release of the online environment (Ubuntu), then pop-up "start_time attribute format is invalid" error. And refer to the official documents, we found this format is to allow the official document .

Ah ah ah. All kinds of trial and error, finally found that if changed php:Y-m-d, the world is clean. So, if you encounter this problem, I appreciate it.


 

Memory leak

Code site

public static function actionTest() {
        $total = 10;
        var_dump('开始内存'.memory_get_usage());
        while($total){
            $ret=User::findOne(['id'=>910002]);
            var_dump('end内存'.memory_get_usage());
            unset($ret);
            $total--;
        }
    }

Memory above code has been growing, according to the original idea of ​​view, the variable is released, it will not increase even if the memory has been growing. Because each time through the loop memory will be released.

The code above analysis of the problem related to the operation of the database, and we know that in many parts of the database can cause a memory leak. So the first shield database-related operations, my handwriting database query operations a native, found that memory is normal, no problem.

$dsn = "mysql:dbname=test;host=localhost";
$db_user = 'root';
$db_pass = 'admin';
//查询
$sql = "select * from buyer";
$res = $pdo->query($sql);
foreach($res as $row) {
    echo $row['username'].'<br/>';
}

This time the answer is almost certain --- yii2 framework to engage in the ghost

Positioning problem since we know it is a problem yii2 framework can further narrow down the problem.

public static function actionTest() {
        $total = 10;
        var_dump('开始内存'.memory_get_usage());
        while($total){
            $ret= new User();
            var_dump('end内存'.memory_get_usage());
            unset($ret);
            $total--;
        }
    }

Memory still continues to grow. This time I tested one other class of yii2 find memory is not increased. This can be associated with a new object in its own internal time yii2 did what, and then cause a memory leak. What is the new method when it is executed. . . Constructor for the __construct. Then I found the object step by step find no place can cause leakage from the model.

This time we might change in thinking, since it is a leak occurs under yii2 framework, it is surely yii2 unique features, what is yii2 unique function, but also in new target will be executed when it?

Behavior (Behavior) found my model classes which really useful behavior

public function behaviors()
    {
        return [
            TimestampBehavior::class,
        ];
    }

But the most common code. We know where the behavior of the last call is yii \ base \ Component-> attachBehaviors finally locate

private function attachBehaviorInternal($name, $behavior)
    {
        if (!($behavior instanceof Behavior)) {
            $behavior = Yii::createObject($behavior);
        }
        if (is_int($name)) {
            $behavior->attach($this);
            $this->_behaviors[] = $behavior;
        } else {
            if (isset($this->_behaviors[$name])) {
                $this->_behaviors[$name]->detach();
            }
            $behavior->attach($this);
            $this->_behaviors[$name] = $behavior;
        }
 
        return $behavior;
    }

We observe this code, he found himself passed into the $ behavior-> attach ($ this); final call is yii \ base \ Behavior-> attach

public function attach($owner)
    {
        $this->owner = $owner;
        foreach ($this->events() as $event => $handler) {
            $owner->on($event, is_string($handler) ? [$this, $handler] : $handler);
        }
    }

conclusion of issue

This time the answer has been pretty clear, Yii2 behavior in order to achieve this function, put itself this pass in order to be able to register an event, a trigger event, the lifting of the event. This leads to a problem of circular references. Resulting in an object refcount has not been recovered is not zero.

Then easier to handle. The inquiry into the original connection try. Sure enough, the rise of memory is very slow, and can say this is a normal phenomenon. Now memory is about 50m, cpu also stable at around 7%. 

After the code is optimized to run another script, about 1 minute of it, the script ran over. The focus is no longer the reported memory errors. So, after still have to consider the issue in depth. Dared to question. If you experience memory errors after this, be sure to check your local code is not a memory leak. Do not think to set php memory. This will only palliative.

to sum up

1, from the development speed, by means of a scaffolding gii, you can quickly generate code, which means that you can build a CRUD system possible without writing a line of code, and integrate jquery and bootstrap, effects, and do not need to write basic style , this is really a great benefit for the design and aesthetic ability is generally poor back-end programmers. However, the rear end of the tendency to separate completely front the front and rear ends of the coupling Yii2 or some heavier.

2, from the readability of code, Yii is not to rigidly follow a design pattern and the code over-design. Basically class in the IDE without the aid of third-party components that can jump to read the source code. Yii Laravel slightly better than on this point.

3, in terms of the open source ecosystem, Yii because few people, a little bit of information on the small side door, Google needs a strong capacity and ability to read English documents.

Admittedly, Yii is an excellent development framework, it is worth learning PHP developers to get started, the process is also a step on the pit growth and accumulation. Finally, I wish PHP little friends are perfectly healthy, successful career.

 

END

Guess you like

Origin www.cnblogs.com/zydj333/p/12038025.html