手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜Qcloud , 注册 | 登陆
浏览模式: 标准 | 列表Tag:yii

yii2终于有自己的队列了!!!

当然 ,之前yii2有一个queue,这个queu简单到只有一个run/job,其他都没有。这回终于来一个完善的了。说实话,有时候用laravel,就是因为想用他的queue。现在终于不用纠结了!

再细看一下他的composer.json。。。还是逃不脱SF的大坑!不过总算是有队列了,管它呢。这年头,所有框架最后都会被SF大一统么?

先到这里看一下教程:https://github.com/yiisoft/yii2-queue/blob/master/docs/guide/README.md

然后再回到:https://github.com/yiisoft/yii2-queue ,下载代码吧,真正使用也简单,php composer.phar require --prefer-dist yiisoft/yii2-queue,就完事了!

不过这个玩意,估计在windows下面是无效的,常用方法有:

PHP代码
  1. // Push a job into queue and get massage ID.  
  2. $id = Yii::$app->queue->push(new SomeJob());  
  3.   
  4. // The job is waiting for execute.  
  5. Yii::$app->queue->isWaiting($id);  
  6.   
  7. // Worker gets the job from queue, and executing it.  
  8. Yii::$app->queue->isReserved($id);  
  9.   
  10. // Worker has executed the job.  
  11. Yii::$app->queue->isDone($id);  

 

估计以后的项目,默认就直接引用:yiisoft/yii2 , yiisoft/yii2-queue了!

 

Tags: yii, queue

值得收藏的yii2的doc中关于db Query的说明

 
Yii2的DB操作与1有很大的区别。所以下面这段还是值得收藏的
虽然第一句让我很简单,但没关系,大部分内容还是照用的,原文地址来自:https://github.com/yiisoft/yii2/blob/master/docs/guide/db-query-builder.md
 
为什么就没有cdbcriteria了呢?哎。。。
 

Note: This section is under development.

Yii provides a basic database access layer as described in the Database basics section. The database access layer provides a low-level way to interact with the database. While useful in some situations, it can be tedious and error-prone to write raw SQLs. An alternative approach is to use the Query Builder. The Query Builder provides an object-oriented vehicle for generating queries to be executed.

A typical usage of the query builder looks like the following:

$rows = (new \yii\db\Query())     ->select('id, name')     ->from('user')     ->limit(10)     ->all();  // which is equivalent to the following code:  $query = (new \yii\db\Query())     ->select('id, name')     ->from('user')     ->limit(10);  // Create a command. You can get the actual SQL using $command->sql $command = $query->createCommand();  // Execute the command: $rows = $command->queryAll();

Query Methods

As you can see, [[yii\db\Query]] is the main player that you need to deal with. Behind the scene, Query is actually only responsible for representing various query information. The actual query building logic is done by [[yii\db\QueryBuilder]] when you call the createCommand() method, and the query execution is done by [[yii\db\Command]].

For convenience, [[yii\db\Query]] provides a set of commonly used query methods that will build the query, execute it, and return the result. For example,

  • [[yii\db\Query::all()|all()]]: builds the query, executes it and returns all results as an array.
  • [[yii\db\Query::one()|one()]]: returns the first row of the result.
  • [[yii\db\Query::column()|column()]]: returns the first column of the result.
  • [[yii\db\Query::scalar()|scalar()]]: returns the first column in the first row of the result.
  • [[yii\db\Query::exists()|exists()]]: returns a value indicating whether the query results in anything.
  • [[yii\db\Query::count()|count()]]: returns the result of a COUNT query. Other similar methods include sum($q),average($q)max($q)min($q), which support the so-called aggregational data query. $q parameter is mandatory for these methods and can be either the column name or expression.

Building Query

In the following, we will explain how to build various clauses in a SQL statement. For simplicity, we use $query to represent a [[yii\db\Query]] object.

SELECT

In order to form a basic SELECT query, you need to specify what columns to select and from what table:

$query->select('id, name')     ->from('user');

Select options can be specified as a comma-separated string, as in the above, or as an array. The array syntax is especially useful when forming the selection dynamically:

$query->select(['id', 'name'])     ->from('user');

Info: You should always use the array format if your SELECT clause contains SQL expressions. This is because a SQL expression like CONCAT(first_name, last_name) AS full_name may contain commas. If you list it together with other columns in a string, the expression may be split into several parts by commas, which is not what you want to see.

When specifying columns, you may include the table prefixes or column aliases, e.g., user.iduser.id AS user_id. If you are using array to specify the columns, you may also use the array keys to specify the column aliases, e.g.,['user_id' => 'user.id', 'user_name' => 'user.name'].

Starting from version 2.0.1, you may also select sub-queries as columns. For example,

$subQuery = (new Query)->select('COUNT(*)')->from('user'); $query = (new Query)->select(['id', 'count' => $subQuery])->from('post'); // $query represents the following SQL: // SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`

To select distinct rows, you may call distinct(), like the following:

$query->select('user_id')->distinct()->from('post');

FROM

To specify which table(s) to select data from, call from():

$query->select('*')->from('user');

You may specify multiple tables using a comma-separated string or an array. Table names can contain schema prefixes (e.g. 'public.user') and/or table aliases (e.g. 'user u'). The method will automatically quote the table names unless it contains some parenthesis (which means the table is given as a sub-query or DB expression). For example,

$query->select('u.*, p.*')->from(['user u', 'post p']);

When the tables are specified as an array, you may also use the array keys as the table aliases (if a table does not need alias, do not use a string key). For example,

$query->select('u.*, p.*')->from(['u' => 'user', 'p' => 'post']);

You may specify a sub-query using a Query object. In this case, the corresponding array key will be used as the alias for the sub-query.

$subQuery = (new Query())->select('id')->from('user')->where('status=1'); $query->select('*')->from(['u' => $subQuery]);

WHERE

Usually data is selected based upon certain criteria. Query Builder has some useful methods to specify these, the most powerful of which being where. It can be used in multiple ways.

The simplest way to apply a condition is to use a string:

$query->where('status=:status', [':status' => $status]);

When using strings, make sure you're binding the query parameters, not creating a query by string concatenation. The above approach is safe to use, the following is not:

$query->where("status=$status"); // Dangerous!

Instead of binding the status value immediately, you can do so using params or addParams:

$query->where('status=:status'); $query->addParams([':status' => $status]);

Multiple conditions can simultaneously be set in where using the hash format:

$query->where([     'status' => 10,     'type' => 2,     'id' => [4, 8, 15, 16, 23, 42], ]);

That code will generate the following SQL:

WHERE (`status` = 10) AND (`type` = 2) AND (`id` IN (4, 8, 15, 16, 23, 42))

NULL is a special value in databases, and is handled smartly by the Query Builder. This code:

$query->where(['status' => null]);

results in this WHERE clause:

WHERE (`status` IS NULL)

You can also create sub-queries with Query objects like the following,

$userQuery = (new Query)->select('id')->from('user'); $query->where(['id' => $userQuery]);

which will generate the following SQL:

WHERE `id` IN (SELECT `id` FROM `user`)

Another way to use the method is the operand format which is [operator, operand1, operand2, ...].

Operator can be one of the following (see also [[yii\db\QueryInterface::where()]]):

  • and: the operands should be concatenated together using AND. For example, ['and', 'id=1', 'id=2'] will generate id=1 AND id=2. If an operand is an array, it will be converted into a string using the rules described here. For example, ['and', 'type=1', ['or', 'id=1', 'id=2']] will generate type=1 AND (id=1 OR id=2). The method will NOT do any quoting or escaping.

  • or: similar to the and operator except that the operands are concatenated using OR.

  • between: operand 1 should be the column name, and operand 2 and 3 should be the starting and ending values of the range that the column is in. For example, ['between', 'id', 1, 10] will generate id BETWEEN 1 AND 10.

  • not between: similar to between except the BETWEEN is replaced with NOT BETWEEN in the generated condition.

  • in: operand 1 should be a column or DB expression. Operand 2 can be either an array or a Query object. It will generate an IN condition. If Operand 2 is an array, it will represent the range of the values that the column or DB expression should be; If Operand 2 is a Query object, a sub-query will be generated and used as the range of the column or DB expression. For example, ['in', 'id', [1, 2, 3]] will generate id IN (1, 2, 3). The method will properly quote the column name and escape values in the range. The in operator also supports composite columns. In this case, operand 1 should be an array of the columns, while operand 2 should be an array of arrays or a Query object representing the range of the columns.

  • not in: similar to the in operator except that IN is replaced with NOT IN in the generated condition.

  • like: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing the values that the column or DB expression should be like. For example, ['like', 'name', 'tester'] will generatename LIKE '%tester%'. When the value range is given as an array, multiple LIKE predicates will be generated and concatenated using AND. For example, ['like', 'name', ['test', 'sample']] will generate name LIKE '%test%' AND name LIKE '%sample%'. You may also provide an optional third operand to specify how to escape special characters in the values. The operand should be an array of mappings from the special characters to their escaped counterparts. If this operand is not provided, a default escape mapping will be used. You may use falseor an empty array to indicate the values are already escaped and no escape should be applied. Note that when using an escape mapping (or the third operand is not provided), the values will be automatically enclosed within a pair of percentage characters.

    Note: When using PostgreSQL you may also use ilike instead of like for case-insensitive matching.

  • or like: similar to the like operator except that OR is used to concatenate the LIKE predicates when operand 2 is an array.

  • not like: similar to the like operator except that LIKE is replaced with NOT LIKE in the generated condition.

  • or not like: similar to the not like operator except that OR is used to concatenate the NOT LIKE predicates.

  • exists: requires one operand which must be an instance of [[yii\db\Query]] representing the sub-query. It will build a EXISTS (sub-query) expression.

  • not exists: similar to the exists operator and builds a NOT EXISTS (sub-query) expression.

Additionally you can specify anything as operator:

$query->select('id')     ->from('user')     ->where(['>=', 'id', 10]);

It will result in:

SELECT id FROM user WHERE id >= 10;

If you are building parts of condition dynamically it's very convenient to use andWhere() and orWhere():

$status = 10; $search = 'yii';  $query->where(['status' => $status]); if (!empty($search)) {     $query->andWhere(['like', 'title', $search]); }

In case $search isn't empty the following SQL will be generated:

WHERE (`status` = 10) AND (`title` LIKE '%yii%')

Building Filter Conditions

When building filter conditions based on user inputs, you usually want to specially handle "empty inputs" by ignoring them in the filters. For example, you have an HTML form that takes username and email inputs. If the user only enters something in the username input, you may want to build a query that only tries to match the entered username. You may use the filterWhere() method to achieve this goal:

// $username and $email are from user inputs $query->filterWhere([     'username' => $username,     'email' => $email, ]);

The filterWhere() method is very similar to where(). The main difference is that filterWhere() will remove empty values from the provided condition. So if $email is "empty", the resulting query will be ...WHERE username=:username; and if both $username and $email are "empty", the query will have no WHERE part.

A value is empty if it is null, an empty string, a string consisting of whitespaces, or an empty array.

You may also use andFilterWhere() and orFilterWhere() to append more filter conditions.

ORDER BY

For ordering results orderBy and addOrderBy could be used:

$query->orderBy([     'id' => SORT_ASC,     'name' => SORT_DESC, ]);

Here we are ordering by id ascending and then by name descending.

GROUP BY and HAVING

In order to add GROUP BY to generated SQL you can use the following:

$query->groupBy('id, status');

If you want to add another field after using groupBy:

$query->addGroupBy(['created_at', 'updated_at']);

To add a HAVING condition the corresponding having method and its andHaving and orHaving can be used. Parameters for these are similar to the ones for where methods group:

$query->having(['status' => $status]);

LIMIT and OFFSET

To limit result to 10 rows limit can be used:

$query->limit(10);

To skip 100 fist rows use:

$query->offset(100);

JOIN

The JOIN clauses are generated in the Query Builder by using the applicable join method:

  • innerJoin()
  • leftJoin()
  • rightJoin()

This left join selects data from two related tables in one query:

$query->select(['user.name AS author', 'post.title as title'])     ->from('user')     ->leftJoin('post', 'post.user_id = user.id');

In the code, the leftJoin() method's first parameter specifies the table to join to. The second parameter defines the join condition.

If your database application supports other join types, you can use those via the generic join method:

$query->join('FULL OUTER JOIN', 'post', 'post.user_id = user.id');

The first argument is the join type to perform. The second is the table to join to, and the third is the condition.

Like FROM, you may also join with sub-queries. To do so, specify the sub-query as an array which must contain one element. The array value must be a Query object representing the sub-query, while the array key is the alias for the sub-query. For example,

$query->leftJoin(['u' => $subQuery], 'u.id=author_id');

UNION

UNION in SQL adds results of one query to results of another query. Columns returned by both queries should match. In Yii in order to build it you can first form two query objects and then use union method:

$query = new Query(); $query->select("id, category_id as type, name")->from('post')->limit(10);  $anotherQuery = new Query(); $anotherQuery->select('id, type, name')->from('user')->limit(10);  $query->union($anotherQuery);

Batch Query

When working with large amount of data, methods such as [[yii\db\Query::all()]] are not suitable because they require loading all data into the memory. To keep the memory requirement low, Yii provides the so-called batch query support. A batch query makes uses of data cursor and fetches data in batches.

Batch query can be used like the following:

use yii\db\Query;  $query = (new Query())     ->from('user')     ->orderBy('id');  foreach ($query->batch() as $users) {     // $users is an array of 100 or fewer rows from the user table }  // or if you want to iterate the row one by one foreach ($query->each() as $user) {     // $user represents one row of data from the user table }

The method [[yii\db\Query::batch()]] and [[yii\db\Query::each()]] return an [[yii\db\BatchQueryResult]] object which implements the Iterator interface and thus can be used in the foreach construct. During the first iteration, a SQL query is made to the database. Data are since then fetched in batches in the iterations. By default, the batch size is 100, meaning 100 rows of data are being fetched in each batch. You can change the batch size by passing the first parameter to the batch() or each() method.

Compared to the [[yii\db\Query::all()]], the batch query only loads 100 rows of data at a time into the memory. If you process the data and then discard it right away, the batch query can help keep the memory usage under a limit.

If you specify the query result to be indexed by some column via [[yii\db\Query::indexBy()]], the batch query will still keep the proper index. For example,

use yii\db\Query;  $query = (new Query())     ->from('user')     ->indexBy('username');  foreach ($query->batch() as $users) {     // $users is indexed by the "username" column }  foreach ($query->each() as $username => $user) { }
 

Tags: yii, yii2

ssdb的Yii cache扩展

google的leveldb越来越被很多人接受。国内的ideawu基于leveldb还写了一个ssdb的前置扩展用来实现了很多功能,比如标准的getset和hget,hset还有zset,zget,也实现了队列。当然pub/sub就没有办法实现了。毕竟它和redis还是有点区别。

基于标准的ssdb的类,写了个小扩展,扩展了Yii的Cache类:

PHP代码
  1. class CSsdbCache extends CCache  
  2. {  
  3.     /** 
  4.      * @var string hostname to use for connecting to the redis server. Defaults to '127.0.0.1'. 
  5.      */  
  6.     public $hostname = '127.0.0.1';  
  7.     /** 
  8.      * @var int the port to use for connecting to the ssdb server. Default port is 8888. 
  9.      */  
  10.     public $port = 8888;  
  11.     /** 
  12.      * @var float 
  13.      */  
  14.     public $timeout = 2000;  
  15.     public $serializer = false;  
  16.     public $_cache;  
  17.     protected $_cachekeys = 'ssdb_cachekey';  
  18.       
  19.     public function init() {  
  20.         parent::init();  
  21.     }  
  22.     /** 
  23.      * @return SSDB 
  24.      */  
  25.     public function getSsdbCache() {  
  26.         if ($this->_cache !== null)  
  27.             return $this->_cache;  
  28.         else {  
  29.             return $this->_cache = new SimpleSSDB($this->hostname, $this->port, $this->timeout);  
  30.         }  
  31.     }  
  32.     public function getkeys() {  
  33.         return $this->getSsdbCache()->hkeys($this->_cachekeys, """"$this->getSsdbCache()->hsize($this->_cachekeys));  
  34.     }  
  35.     /** 
  36.      * Retrieves a value from cache with a specified key. 
  37.      * This is the implementation of the method declared in the parent class. 
  38.      * @param string $key a unique key identifying the cached value 
  39.      * @return string|boolean the value stored in cache, false if the value is not in the cache or expired. 
  40.      */  
  41.     protected function getValue($key) {  
  42.         return unserialize($this->getSsdbCache()->get($key));  
  43.     }  
  44.   
  45.     /** 
  46.      * Stores a value identified by a key in cache. 
  47.      * This is the implementation of the method declared in the parent class. 
  48.      * @param string  $key    the key identifying the value to be cached 
  49.      * @param string  $value  the value to be cached 
  50.      * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. 
  51.      * @return boolean true if the value is successfully stored into cache, false otherwise 
  52.      */  
  53.     protected function setValue($key$value$expire) {  
  54.         $this->getSsdbCache()->hset($this->_cachekeys, $key, 1);  
  55.         if ($expire > 0) {  
  56.             //$expire += time();  
  57.             return $this->getSsdbCache()->setx($key, serialize($value), (int) $expire);  
  58.         }  
  59.         else {  
  60.             return $this->getSsdbCache()->set($key, serialize($value));  
  61.         }  
  62.     }  
  63.     /** 
  64.      * Stores a value identified by a key into cache if the cache does not contain this key. 
  65.      * This is the implementation of the method declared in the parent class. 
  66.      * @param string  $key    the key identifying the value to be cached 
  67.      * @param string  $value  the value to be cached 
  68.      * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. 
  69.      * @return boolean true if the value is successfully stored into cache, false otherwise 
  70.      */  
  71.     protected function addValue($key$value$expire) {  
  72.         return $this->setValue($key$value$expire);  
  73.     }  
  74.     /** 
  75.      * Deletes a value with the specified key from cache 
  76.      * This is the implementation of the method declared in the parent class. 
  77.      * @param string $key the key of the value to be deleted 
  78.      * @return boolean if no error happens during deletion 
  79.      */  
  80.     protected function deleteValue($key) {  
  81.         $this->getSsdbCache()->hdel($this->_cachekeys, $key);  
  82.         return $this->getSsdbCache()->del($key);  
  83.     }  
  84.     /** 
  85.      * @return boolean whether the flush operation was successful. 
  86.      */  
  87.     protected function flushValues() {  
  88.         $this->getSsdbCache()->multi_del($this->getkeys());  
  89.         return $this->getSsdbCache()->hclear($this->_cachekeys);  
  90.     }  
  91. }  

其实代码很简单,不过由于ssdb默认没有serialize功能,所以在存储之前,得先主动的serialize,然后get的时候unserialize。不然就没有办法存储数组了。

由于ssdb没有flush功能。所以利用hget/hset将所有的key存储下来。flush的时候把hget获取的key读出来删除。然后再清掉这个hget的key

最后还有expire。ssdb里的setx第三个参数。。。居然不是expire,而是ttl。开始的时候,一直都当成expire。结果浪费了很长时间

Tags: yii

yiibooster+bsie

对于使用yii框架来说,如果使用bootstrap框架的话,现在有一个比较方便的使用途径:yiibooster。
官网地址是:http://yii-booster.clevertech.biz/
当然,我们都知道bootstrap几乎是不支持IE 6的。所以这时候,为了兼容IE6,还得冒出个:BSIE(鄙视IE),官方地址为:https://github.com/ddouble/bsie

有了这两样东西,开发起来是不是快了很多,至少你不用太关心页面是怎么做的了。而且变形,还没有那么夸张。更为可贵的是,你在手机上也能够正常浏览。
比如:http://photo.pinjian.net。就支持了手机浏览,只是界面难看了点罢了

Tags: yiibooster, bsie, yii

yii with的排序

Yii在自己的AR中实现了relations,于是我们可以利用relations实现一些left join或者其他join能做的事情,常见的大家都懂,什么 belongs_to,has_one,has_many,many_to_many之类的
但用的最多的,一般都是has_one,has_many,毕竟查关联数据这个最方便了。

于是我们就会Table::model()->with('a','b')->findAll($cdbcriteria);
这个时候,如果需要用到a或b的排序,就有点痛苦,直接在$cdbcriteria中写的话,往往会报字段不存在,因此可以尝试这样
1、直接在relations中,在写成a时,直接加入'order'=>'id DESC'之类的内容
2、在with()中写: with(array('a'=>array('order'=>'id DESC'),'b'))

这样是不是就很方便了呢?
当然上面的代码是通过:

PHP代码
  1. public function with()  
  2. {  
  3.     if(func_num_args()>0)  
  4.     {  
  5.         $with=func_get_args();  
  6.         if(is_array($with[0]))  // the parameter is given as an array  
  7.             $with=$with[0];  
  8.         if(!empty($with))  
  9.             $this->getDbCriteria()->mergeWith(array('with'=>$with));  
  10.     }  
  11.     return $this;  
  12. }  

看了这段代码就基本上了解用法了,手册里也说了:
Specifies which related objects should be eagerly loaded. This method takes variable number of parameters. Each parameter specifies the name of a relation or child-relation. For example,

// find all posts together with their author and comments
Post::model()->with('author','comments')->findAll();
// find all posts together with their author and the author's profile
Post::model()->with('author','author.profile')->findAll();
The relations should be declared in relations().

By default, the options specified in relations() will be used to do relational query. In order to customize the options on the fly, we should pass an array parameter to the with() method. The array keys are relation names, and the array values are the corresponding query options. For example,
Post::model()->with(array(
    'author'=>array('select'=>'id, name'),
    'comments'=>array('condition'=>'approved=1', 'order'=>'create_time'),
))->findAll();
所以,有时候看看手册还是很重要的。

Tags: yii, with, cdbcriteria

Records:6912345678910»