Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
$contracts = ...;
$services = ...;
foreach ($contracts as &$contract) {
$contract['xxx'] = 'yyy'; // тут меняется $contracts
$contractServices = array_filter($services, function($v) use ($contract){
return $v['id'] == $contract['contractId'];
});
$contract['mmm'] = 'nnn'; // а здесь $contract уже живёт своей жизнью, $contracts не меняется
}
for($i=0;$i<count($obj_array);++$i)
$obj_array[$i].onevent = function () use($i) { /*echo $i...*/}
/**
* Метод возвращает набор лямбда-функций
* для удобного доступа к выражениями Doctrine DQL.
*
* @example
*
* <code>
* $query_builder = $this->createSelect();
*
* // импортируем все лямбда-функции в текущую область видимости
* extract($this->getExpressions());
*
* $query_builder->where
* (
* // построим WHERE с помощью лямбда-функций
* $andx
* (
* $eq($alias('user'), ':user'),
* $eq($alias('type'), ':type'),
* $in($alias('status'), array(':active', ':disabled'))
* )
* );
* </code>
*
* @return array
*/
public function getExpressions()
{
if (!empty (static::$expressions))
{
return static::$expressions;
}
$expr_builder = $this->getExpressionBuilder();
// :TRICKY: Imenem 22.03.12
//
// Эта лямбда-функция создает прокси
// к методу объекта ExpressionsBuilder.
// После ее вызова с указанием имени метода
// будет создана лямбда-функция,
// которая вызывает одноименный метод ExpressionsBuilder,
// передавая ему полученные параметры.
$expr_proxy = function($method) use ($expr_builder)
{
return function() use ($method, $expr_builder)
{
return call_user_func_array(array($expr_builder, $method), func_get_args());
};
};
$alias = static::$alias;
static::$expressions = array
(
'alias' => function($field) use ($alias)
{
return $alias . '.' . $field;
},
'andx' => $expr_proxy('andx'),
'orx' => $expr_proxy('orx'),
'eq' => $expr_proxy('eq'),
'neq' => $expr_proxy('neq'),
'gte' => $expr_proxy('gte'),
'lte' => $expr_proxy('lte'),
'in' => $expr_proxy('in'),
'notIn' => $expr_proxy('notIn'),
'between' => $expr_proxy('between'),
'not' => $expr_proxy('not'),
'exists' => $expr_proxy('exists')
);
return static::$expressions;
}
/**
* Метод возвращает актуальные на текущий день
* запланированные платежи по уровню баланса
*
* @param DateTime $date Метка времени запуска
* @param int $offset Индекс первого элемента, который должен попасть в выборку
* @param int $limit Максимальное кол-во элементов в выборке
*
* @return Acme\SomeBundle\Entity\ScheduleItem[] Массив запланированных задач
*/
public function findActualBalanceSchedules(DateTime $date = null, $offset = null, $limit = null)
{
extract($this->getExpressions());
$pt_repo = $this->getRepo('PaymentTask');
// получим лямбду, которая добавляет
// алиас сущности PaymentTask к имени поля
$pt_alias = $pt_repo->getExpressions()['alias'];
// создадим подзапрос, который выберет
// для каждой ScheduleItem все PaymentTask,
// которые были созданы не позднее суток назад,
// и не были до конца выполнены
$created_payment_tasks = $pt_repo
->createSelect()
->select($pt_alias('id'))
->andWhere
(
$gte($pt_alias('started'), ':started'),
$in($pt_alias('status'), PaymentTask::getActiveStatusSet())
);
return $this
->createActualSelect(ScheduleItem::TYPE_BALANCE, $offset, $limit)
->andWhere
(
// выберем все запланированные задачи по балансу,
// для которых не существует неоконченных платежных задач
$not($exists($created_payment_tasks))
)
// выберем задачи, созданные не позднее суток назад
->setParameter('started', (new DateTime)->sub(new DateInterval('P1D')))
->getQuery()
->getResult();
} public function getActualScheduleItems(DateTime $date = null, DateTimeZone $time_zone = null)
{
$data_loader = function($offset, $limit) use ($date, $time_zone)
{
return $this->getRepo()->findActualPeriodicalSchedules($date, $time_zone, $offset, $limit);
};
return $this->createPortionIterator($data_loader);
}
если проектировать не предполагая использование замыканий, то задачу можно решить и без нихДа, вот только зачем отвергать решения, которые позволяют решить задачу лучше и проще? Здесь как раз замыкания вполне соответствуют KISS. В любой точке, в которой возможна передача коллбэка, можно, а зачастую и нужно, использовать замыкание, чтобы не плодить методы/наследники-адаптеры.
public function getActualScheduleItems(DateTime $date = null, DateTimeZone $time_zone = null)
{
$repo = $this->getRepo();
$data_loader = function($offset, $limit) use ($repo, $date, $time_zone)
{
return $repo->findActualPeriodicalSchedules($date, $time_zone, $offset, $limit);
};
return $this->createPortionIterator($data_loader);
}$expr
->if(function(){ return $this->v == 4;})
->then(function(){$this->v = 42;})
->else(function(){})
->elseif(function(){})
->end()
->while(function(){$this->v >=42})
->do(function(){
$this->v --;
})
->end()
<?php
$array = range(0, 100000);
$result = array_map(function($element) { return $element+1; },$array);
<?php
$array = range(0, 100000);
function test($element) { return $element+1;}
array_map('test',$array);
$name = Input::get('name', function() use ($db){$config = $db->loadConfig(); return $config['default_name'];});
$name=isset($_GET['name'])?$_GET['name'] :null);
if (is_null($name))
{
$config = $db->loadConfig();
$name = $config['default_name'];
}
$config = $db->loadConfig();
$default_name = $config['default_name'];
$name=isset($_GET['name'])?$_GET['name'] :$default_name);
Применение замыканий в PHP