getContent() not paging - only returns latest results - bolt-cms

Within an extension (JSON access), I'm calling getContent() with:
$items = $this->app['storage']->getContent($contenttype, $options);
$response = $this->app->json($items);
return $response;
The options array is:
[
'limit' => 5,
'page' => 3
]
But getContent only returns the latest 5 results, not calculating the offset from the page variable. Is there another setting that I have to change to get it to recognise the paging?

Calling getContent you need to specify that you want paging turned on, here's some adding 'paging'=>true to the options should work correctly.

Related

Pass dynamic variable in matching or innerJoinWith in cakephp3

I am passing static value to my following query, then it works well. If I change it dynamic, then it doesn't.
//works well
$users = $this->Users->find('all')
->where(['Users.role' => $role])
->innerJoinWith('UserDetail',function($query){
return $query->where(['UserDetail.state' => "chandigarh"]);
})->toArray();
// don't work
$state="chandigarh";
$users = $this->Users->find('all')
->where(['Users.role' => $role])
->innerJoinWith('UserDetail',function($query){
return $query->where(['UserDetail.state' => "$state"]);
})->toArray();
How can I pass my $state variable dynamic to this?
This is how PHP works, it's not really a CakePHP related problem
That variable is not available inside the scope of the anonymous function $query
see example 3 here: http://php.net/manual/en/functions.anonymous.php
You should inherit the variable from the parent scope by using the USE contruct like this:
$state="chandigarh";
$users = $this->Users->find('all')
->where(['Users.role' => $role])
->innerJoinWith('UserDetail',function($query) use ($state) {
return $query->where(['UserDetail.state' => $state]);
})->toArray();
you should remove "" that cover "$state" that should be: $query->where(['UserDetail.state' => $state]) not $query->where(['UserDetail.state' => "$state"])

GetStream Laravel - Cannot batchadd to notification

I can't seem to use the batcher to copy an activity to notifications. I read from the docs
that there is a 100 limit to the TO field for copying activities, so i tried out using the batcher. but it does'nt seem to work. did I miss out something on the docs or on my code? if so, how do I get over the 100 limit?
$evtConvMention = array();
$evtConvMention[] = "event:{$event->id}";
$evtConvMention[] = "notification:1";
$evtConvMention[] = "notification:2";
$batcher = FeedManager::getClient()->batcher();
$batcher->addToMany([
"actor" => "App\User:{$user->id}",
"verb" => "eventpost",
"object" => "App\EventConversation:{$post->id}",
"foreign_id" => "App\EventConversation:{$post->id}"
], $evtConvMention);
The addToMany() call will have a similar limit. While I look into the PHP library a little more, it might be easier to use the To field in the activity payload itself.
$feed = FeedManager::getClient()->feed("event", $event->id);
$now = new \DateTime("now", new \DateTimeZone('Pacific/Nauru'));
$data = [
"actor" => "App\User:{$user->id}",
"verb" => "eventpost",
"object" => "App\EventConversation:{$post->id}",
"foreign_id" => "App\EventConversation:{$post->id}",
"time" => $now
];
$feed->addActivity($data);
We also HIGHLY recommend sending your own foreign_id and time fields in the payload as well (I've added an idea for the $now value in the code above, otherwise every feed will get its own unique record, which are a limited resource on your account.
If you have more than 100 notification feeds to write this into, it might be better to have the notification feeds for those users 'follow' the event feed. Then you don't need to use the to field at all.

How to get all all key values of an array in laravel?

I am not getting all the key values of and array using foreach, its giving only first key value.
$order_id = DB::table('order')->where('delivery_boy_id', $delivery_boy_id)->where('is_accept', 1)->whereRaw('delivery_completed_at < time_of_assignment')->get();
When i run this code i get two key value
array:2 [0 => {#325
+"id": 37
+"order_id": 8261
+"delivery_boy_id": 8}1 => {#326
+"id": 38
+"order_id": 8261
+"delivery_boy_id": 8]
After using this json response i am getting the response of only one key value
foreach($order_id as $value){ $values = $value) };
$this->response['items'] = $order_id;
return json_encode($this->response);
check this
$order_id = DB::table('order')->where('delivery_boy_id', $delivery_boy_id)->where('is_accept', 1)->whereRaw('delivery_completed_at < time_of_assignment')->get();
// return $order_id;(returns json array)
$data = [];
foreach($order_id as $order)
{
var_dump($order);
//in first loop first array will come
//second loop second array
$data[]=[
'id' => $order['id'],
'..' => '..'
];
}
return $data;
}
Dd means dump and die so it stops execution. If you dd in a for each loop, you will only get the current value in the loop (I.e the first one) because it will halt execution and you will never reach the second loop through. Use var_dump to allow execution to continue and dump variables.
If you simply want to return the Json to the user, you can just return the result of your query as laravel handles serialisation for you. You don't need to loop over the result. See the docs:
https://laravel.com/docs/5.1/eloquent-serialization
You are overwriting $values in your loop. So every time it passes through the for each loop, it overwrites $values with the current $value so it will only ever contain 1 object. You don't need to do the serialisation manually, use the laravel helper methods
Also in your code snippet you are looping over $order, but the result of your query is assigned to $order_id? I'm assuming that's due to abbreviating your code

Can indexby be used on associations directly in the query?

I have a number of situations where I need to cross-reference various records by ID, and find it's easiest to do so when the array is indexed by that ID. For example, Divisions hasMany Teams, Divisions hasMany Games, and Games belongTo HomeTeam and AwayTeam. When I want to read all of the teams and games in a division, I do something like this:
$division = $this->Divisions->get($id, [
'contain' => ['Teams', 'Games']
]);
I don't do
$division = $this->Divisions->get($id, [
'contain' => ['Teams', 'Games' => ['HomeTeam', 'AwayTeam']]
]);
because it seems that would increase memory requirements, especially when I'm further containing other models (People, etc.) in the Teams. So, instead I do
$division->teams = collection($division->teams)->indexBy('id')->toArray();
after the get to reindex that array, and then when I'm iterating through $division->games, to get the home team record I use $division->teams[$game->home_team_id]. This is all well and good (except that it sets the teams property as being dirty, a minor inconvenience).
But it seems that the queryBuilder functionality of the ORM is pretty magical, and I know that I can do
$teams = $this->Divisions->Teams->find()
->where(['division_id' => $id])
->indexBy('id')
->toArray();
to get an array of teams indexed how I want, so I'm wondering if there's some way to include indexBy on the associations. I tried
$division = $this->Divisions->get($id, [
'contain' => [
'Teams' => [
'queryBuilder' => function (Query $q) {
return $q->indexBy('id');
},
],
'Games',
]
]);
but, unsurprisingly, this didn't work. Any ideas?
Just for the record, guess you know this already, indexBy() doesn't belong to the query, but to the result set, so being able to call it requires the query to be executed first. It's not possible to use this for an association query builder, as it must return a query, not a result set.
While it would be possible to use result formatters for the associations and modify the result set accordingly, the problem is that the result set will hold all team results for all divisions, and when the team entities are being distributed on the various division entities that they belong to, the arrays will be "reindexed", respectively, the arrays will be populated without respect to the indices of the result set, so long story short, that won't work.
Global result formatter
However, a result formatter for the main query should work fine, and as you probably already figured, you can simply reset the dirty state afterwards in case it causes any problems, something like
$division = $this->Divisions
->find()
->contain([
'Teams'
])
->where([
'Divisions.id' => $id
])
->formatResults(function($results) {
/* #var $results \Cake\Datasource\ResultSetInterface|\Cake\Collection\CollectionInterface */
return $results
->map(function ($row) {
if (isset($row['teams'])) {
$row['teams'] = collection($row['teams'])->indexBy('id')->toArray();
}
if ($row instanceof EntityInterface) {
$row->dirty('teams', false);
}
return $row;
});
})
->firstOrFail();
Custom association and association specific result formatters
Another option would be to use a custom association class, which overrides ExternalAssociationTrait::_buildResultMap(), so that it respects the indices of the result set, as this is where the problem starts.
By default the associated entities are fetched from the result set and appended to a new array, which is later assigned to the respective association property on the entity the results belong to. So this is where the the keys from the possible custom indexed result set are being lost.
Here's an example, the change is really small, but I'm not sure about possible side effects!
src/Model/Association/IndexAwareHasMany.php
namespace App\Model\Association;
use Cake\ORM\Association\HasMany;
class IndexAwareHasMany extends HasMany
{
protected function _buildResultMap($fetchQuery, $options)
{
$resultMap = [];
$key = (array)$options['foreignKey'];
// grab the index here
foreach ($fetchQuery->all() as $index => $result) {
$values = [];
foreach ($key as $k) {
$values[] = $result[$k];
}
// and make use of it here
$resultMap[implode(';', $values)][$index] = $result;
}
return $resultMap;
}
}
Original: https://github.com/cakephp/...ORM/Association/ExternalAssociationTrait.php#L109
Now you must of course make use of the new association, to simplify it for this example, let's just override the table class' default hasMany() method
public function hasMany($associated, array $options = [])
{
$options += ['sourceTable' => $this];
$association = new \App\Model\Association\IndexAwareHasMany($associated, $options);
return $this->_associations->add($association->name(), $association);
}
And now, finally, you could use a result formatter for the association:
$division = $this->Divisions->get($id, [
'contain' => [
'Teams' => [
'queryBuilder' => function (Query $query) {
return $query
->formatResults(function($results) {
/* #var $results \Cake\Datasource\ResultSetInterface|\Cake\Collection\CollectionInterface */
return $results->indexBy('id');
});
}
],
'Games',
]
]);

Calling same model function with different parameters not returning values

Soooo....long time reader first time poster. For the first time, can't find the answer!
I've got a model that returns an array of results (working). Then I loop through the results with a foreach and append the array with additional values from a second function in my model. Problem is that only the first of my several function calls return any results. The function get_offering_total() only returns the value for the first listed call (cash). This is returning the correct value, but any subsequent attempts to use the same function returns nothing. A var_dump shows that the array is structured correctly on the output, but the values are all null. Is there an issue with calling the same model method with different parameters? Something needs to be cleared/reset?
Here's the code...
//$data['offerings'] stores the results from my first query
foreach( $data['offerings'] as $key => $value ) {
//Set filters
$cash_filter = array( 'method' => '5' );
$checks_filter = array( 'method' => '6' );
//Get totals
$data['offerings'][$key]['cash'] =
$this->model_records->get_offering_total( $value['offering_id'], $cash_filter);
$data['offerings'][$key]['checks'] =
$this->model_records->get_offering_total( $value['offering_id'], $checks_filter);
...other stuff...
}
Thanks for your help!
Here's a simple test to see if all the code you wrote is correct. Surround everything in your function (in the model) within a try/catch block, and see if it throws any kind of exception. You'd be surprised how many exceptions get thrown but PHP doesn't show them because you have error reporting off in your PHP config. You can do the same for the two lines on which you call the method in your controller and see if they are all good.
PHP Exceptions Reference