I using Phalcon PHP as PHP MVC Framework with MongoDB.
I can find object according with some criteria:
$user = User::findFirst(array(array('username' => $login, 'email'=> $login)));
As you can note, this request will return me the record according logical AND operator between conditions. I need to form request that will return result according with OR operator between conditions.
The problem also is that I'm using MongoDB, so, as I can suppose, I can't write PHQL request manually.
Just a matter of mangling PHP arrays
$user = User::findFirst( array(
'$or' => array(
array( 'username' => $login),
array( 'email' => $login)
)
));
So not only do I show the answer but also how my totals non PHP mind solves this problem:
$result = '{ "$or": [ { "username": "login" }, { "email": "login" } ] }';
echo var_dump( json_decode( $result ) );
$test = array(
'$or' => array(
array( 'username' => 'login'), array( 'email' => 'login')
)
);
echo json_encode( $test ) ."\n"
So in just a few lines we converted and proved. So since you knew the JSON from either the manual page or reading another question on SO, just convert it. And it's one of the reasons I submit the valid JSON in responses here, is so that the logic can be translated into just about any language implementation.
You can pass column names as string in first param:
$user = User::findFirst('username = "'.$login.'" OR email = "'.$login.'"');
$result = '{ "$or": [ { "username": "login" }, { "email": "login" } ] }';
User::findFirst(array(json_decode($query,true)));
$result is the exact json which can be used to trigger queries in mongodb command line
json_decode with 2nd parameter true will output the array style format of JSON
Related
I want to send request via post method with API, and when sending values, sometimes I need to send two values instead of one, and for this I need to loop it. The solution to this is, before sending the request, I save it to the array in the loop and try to complete the process by making json_encode.
My explanation may not be fully explanatory, so I will explain through the codes.
The request I want to throw is normally like this:
CURLOPT_POSTFIELDS =>'
[
{
"items":
[
{
"name":"string",
"sku":"string",
}
],
}
]'
But some times the items value needs to have two instead of one. For example:
CURLOPT_POSTFIELDS =>'
[
{
"items":
[
{
"name":"string",
"sku":"string",
},
{
"name":"string",
"sku":"string",
}
],
}
]'
So before i make this request i am saving these values to array in a foreach loop.
$data =array();
foreach ($request->orderItems as $orderItemId) {
$order_item = OrderItem::where('orderItemId',$orderItemId)->first();
$data[] = array(
"sku"=> $order_item->sku,
"name"=> $order_item->name,
)
}
And if I'm going to send more than one value, my final code looks like this.
CURLOPT_POSTFIELDS =>'
[
{
"items": '.json_encode($data).',
}
]'
Here is where the problem starts and when i try to send this request i get this error:
Array to string conversion
What should I do exactly? Where am I missing?
You might be missing the Content-Type header for your cURL call.
CURLOPT_HTTPHEADER => [
'Content-Type' => 'application/json',
],
Try to encode all the content in CURLOPT_POSTFIELDS like this way
$array = [
array(
"name" => "string",
"sku" => "string",
),
array(
"name" => "string",
"sku" => "string",
)
];
$final = json_encode([["items" => $array]]);
//now use this variable directly in CURLOPT_POSTFIELDS
CURLOPT_POSTFIELDS => $final
may it helps ....
So first here's what I'm trying to do :
I got a datatable with some custom inputs. Users can select skills (php, mysql etc) and the standard text input. Users can select multiple skills. When multiple skills are selected it's supposed to be kind of an AND AND query. So both skills must be available.
The standard text input in datatables would contain information such as the name of a customer, their email or job function.
For example I check PHP and Javascript, in my text search I put Google.
Which would mean I'm looking for a document which has both PHP and Javascript in the tags (Or any of their aliases eg: Javascript => js), and has google in any other field thats listed (Customer, function, sender name, sender email or subject).
But it should also be able to search for documents just matching the skills or only for the text input.
I have been trying to build arrays with all query options and merge those depending on input to the function but so far nothing has been working.
the match filter must be an expression in an object
So below is an example of a document I got in Mongo
{
"_id": {
"$oid": "superfancyID"
},
"parsed": {
"tags": [
"sql",
"php"
],
"customer": "CustomerName",
"function": "functionName",
"mail_properties": {
"senderName": "SenderName",
"senderEmail": "example#example.com",
"subject": "FW: Test email",
}
}
}
Here is some code I got to try and build my query
public function handler(int $skip, int $limit, array $filters, string $filterString = '') {
# $filters are skills
# $filterString is a string of everything else you put in the search field of the datatable
/** #var \MongoDB\Collection $collection */
$collection = $this->emailRepository->getCollection();
/** #var array $regex */
$regex = [];
if(!empty($filterString))
{
$strings = explode(' ', $filterString);
foreach($strings as $item)
{
$regex[] = new Regex($item, 'i');
}
}
#This function basically does the same as above.
#The only change is that this also goes over any aliases for skills. (Javascript => js)
/** #var array $aliasRegex */
$aliasRegex = $this->createAliasRegex($filters);
$skillsFilters = [];
#This is where I attempt to create a part of the query for just the skills.
if(!empty($aliasRegex)) {
$skillsFilters = [
'$and' => [
'$or' => [
['parsed.tags' => [
'$in' => $aliasRegex
]]
]
]
];
}
$stringFilters = [];
#This is where I try and build the rest of the query.
if(!empty($regex)) {
$stringFilters = ['$or' =>
['parsed.function' => [
'$in' => $regex
]],
['parsed.mail_properties.subject' => [
'$in' => $regex
]],
['parsed.customer' => [
'$in' => $regex
]]
];
}
$documents = $collection->aggregate([
[
'$match' => [
array_merge($stringFilters, $aliasFilters)
]
]
,[
'$limit' => $limit,
],[
'$skip' => $skip
]
]);
This is basically all I got, I tried checking my arrays and moving around some parts but nothing has been working for me. I always been getting back the error
the match filter must be an expression in an object
I am building a Facebook bot using api.ai and I have gotten to a point where I need to send responses using Facebook generic template. I fetch the list of items to listed from the database and put them in an array and assign to a variable. My problem is that the data is actually returned as shown by Ngrok but it not shown on Facebook as a generic template. Nothing shows. Here is my code.
while($result = mysqli_fetch_assoc($res)){
$array[] = array(
"title"=> $result['title'],
"image_url"=> $result['img_url'],
"subtitle"=> "See all our colors",
"buttons"=>[
[
"type"=>"postback",
"title"=>$result['title'],
"payload"=>$result['payload_id']
]
]
);
}
if ($intentName == "sex"){
$data =json_encode([
'speech' => "Hi ".$firstname,
'displayText' => "test",
'source' => "source",
'data' => ["facebook" => [
"attachment"=>[
"type"=>"template",
"payload"=>[
"template_type"=>"generic",
"elements"=>[
//One attachment
$array
//First attachment ends
]
]
] ]
]
]);
echo $data;
}
I solved it. It should have been:
"elements"=> $array
After doing a query, how can I create and echo a formatted JSON like this:
{
"results": [
{
"user_id": "1",
"name": "Apple",
"address": "7538 N LA CHOLLA BLVD",
"city": "Palo Alto",
"state": "CA",
"latlon": [
-111.012654,
32.339807
],
},
{
"user_id": "2",
"name": "Microsoft",
"address": "75 S BWY STE 400",
"city": "Palo Alto",
"state": "CA",
"latlon": [
-73.764497,
41.031858
],
},
],
"meta": {
"page": 1,
"per_page": 10,
"count": 493,
"total_pages": 50
}
}
This is my current query:
public function getAgenciesJson() {
$agencies = DB::table('users')->where('type','a')->orWhere('type','l');
}
Haven't figured out how to output JSON like that, considering I have a "latlon" field like [-111.012654,32.339807], also a "results" tag and a "meta" tag.
Thanks in advance
What you need is something called a transformer (or presenter) to convert your raw model into a format that can be sent to your users.
A very popular package is called Fractal (http://fractal.thephpleague.com/) by Phil Sturgeon. There's a Laravel package, that might make it a bit easier to use, called Larasponse (https://github.com/salebab/larasponse).
Phil actually a blog post about this just the other day - https://philsturgeon.uk/api/2015/05/30/serializing-api-output/ - that goes into why you should always have some kind of transformer between your models and what you send to your users.
There's also a guide about using Larasponse and Fractal that might be of use here - http://laravelista.com/laravel-fractal/.
The gist of it boils down to passing the model through another class that will take the models values and build an array/object in a known/fixed format, e.g. (from Phil's blog post)
return [
'id' => (int) $book->id,
'title' => $book->title,
'year' => (int) $book->yr,
'author' => [
'name' => $book->author_name,
'email' => $book->author_email,
],
'links' => [
[
'rel' => 'self',
'uri' => '/books/'.$book->id,
]
]
];
This way you're not exposing your original field names and if at any point your column names should change you only need to update that in 1 place rather than having to get any user of your JSON to update their site/app. It will also allow you to do string manipulation of your latlon column so that you can split it into 2 different values.
Using a slightly modified example from the Fractal documentation. Say you have a transformer for a User
class UserTransformer extends Fractal\TransformerAbstract
{
public function transform(User $user)
{
return [
'id' => (int) $user->id,
'name' => $user->first_name . ' ' . $user->last_name,
];
}
}
You can then use this class to either transform a single item of a collection
$user = User::find(1);
$resource = new Fractal\Resource\Item($user, new UserTransformer);
// Or transform a collection
// $users = User::all();
// $resource = new Fractal\Resource\Collection($users, new UserTransformer);
// Use a manager to convert the data into an array or json
$json = (new League\Fractal\Manager)->createData($resource)->toJson();
Fractal includes a paginator adapter for Laravel that can be used straight away
$paginator = User::paginate();
$users = $paginator->getCollection();
$resource = new Collection($users, new UserTransformer);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
The method exists:
->toJson()
REF: http://laravel.com/docs/4.2/eloquent#converting-to-arrays-or-json
Update your getAgenciesJson to :
public function getAgenciesJson() {
return DB::table('users')->where('type','a')->orWhere('type','l')->toJson();
}
Then you could echo by:
<?= SomeModel::getAgenciesJson(); ?>
To modify the column names you can update your select. Here is an example taken from the Laravel Docs:
$users = DB::table('users')->select('name as user_name')->get();
Here would be a more fully realized version of what you are looking for minus the column aliases since you didn't really mention what they were.
public function getAgenciesJson($page, $per_page = 10) {
$output = [
'results' => [],
'meta' => [],
];
// Get Results
$output['results'] = DB::table('users')->where('type','a')->orWhere('type','l')->take($per_page)->skip($per_page * ($page - 1))->get();
// Set Meta
$output['meta'] = [
'page' => $page,
'per_page' => $per_page,
'count' => DB::select('SELECT FOUND_ROWS()'),
'total_pages' => DB::table('users')->count() / $per_page
];
// Return
return json_encode($output);
}
Your original code didn't attempt to get or handle the pagination information but this example covers that in order to provide the meta data you indicated you wanted returned.
Not sure if you wanted Count to be the number of the current result set or a count of all the records on that table. If you don't want the current set you but rather the entire count you can use DB::table('users')->count() though I would assign it to a variable and use that rather than calling it twice in the meta info.
public function getAgenciesJson() {
$agencies = DB::table('users')->where('type','a')->orWhere('type','l')->get();
return response()->tojson($agencies,200);//for response with status code 200
}
You should call get function to get data in array format and response function will format your output to json. Second paramater signifies which status code you have to assign for your response.
I have created the following table in DynamoDB:
Field1: messageId / Type: String / Example value: 4873dd28-190a-4363-8299-403c535e160f
Field2: microtime / Type: Number / Example value: 14143960092414
Field3: data / Type: nested JSON-Array / Example value: {"foo":"bar","other":{"nested":1}}
I am performing the following request using PHP SDK for DynamoDB to create an entry
$raw = '{"foo":"bar","other":{"nested":1}}';
$result = $client->putItem(array(
'TableName' => 'requests2',
'Item' => array(
'messageId' => array('S' => '4873dd28-190a-4363-8299-403c535e160f'),
'microtime' => array('N' => microtime(true)*10000),
'data' => array('S' => $raw),
)
));
I want then to query the table and filter using variables within the JSON-array data field. Is my above solution to entering the data the right approach? The JSON-array gets stored as string, as to my understanding. Do we need another datatype? Basically, I can already query the table like below to retrieve messages that were added within the last minute:
$iterator = $client->getIterator('Query', array(
'TableName' => 'requests2',
'KeyConditions' => array(
'messageId' => array(
'AttributeValueList' => array(
array('S' => '4873dd28-190a-4363-8299-403c535e160f')
),
'ComparisonOperator' => 'EQ'
),
'microtime' => array(
'AttributeValueList' => array(
array('N' => strtotime("-1 minutes")*10000)
),
'ComparisonOperator' => 'GT'
)
)
));
foreach ($iterator as $item) {
echo $item['messageId']['S']." ";
}
But how can I modify my request to allow querying by ANY value within the data-field? For example, filter by only those who have [data][other][nested]=1
I've spent the past hours on this issue and I can't get it to work... I am very grateful for any tips, thanks in advance!
I know this was posted in 2014, but I was looking exactly for this answer and so I'd like to share the result in my search to anyone that will land on this question in the future.
Best practice is to store a JSON as a string, but use a Marshaler object to turn the JSON into something that DynamoDB can digest, and that you will be able to query too:
Using marshalJSON method you turn a JSON, as you can see described in this amazon link
For the ones that are looking for a quick example, I add here below the key parts of the procedure:
If you have a JSON like the following
{
"id": "5432c69300594",
"name": {
"first": "Jeremy",
"middle": "C",
"last": "Lindblom"
},
"age": 30,
"phone_numbers": [
{
"type": "mobile",
"number": "5555555555",
"preferred": true
},
{
"type": "home",
"number": "5555555556",
"preferred": false
}
]
}
stored in a string variable $json, you can simply do
use AwsDynamoDbDynamoDbClient;
use AwsDynamoDbMarshaler;
$client = DynamoDbClient::factory(/* your config */);
$marshaler = new Marshaler();
$client->putItem([
'TableName' => 'YourTable',
'Item' => $marshaler->marshalJson($json)
]);
I don't think AWS PHP SDK for DynamoDB has yet implemented the support for JSON based document storage. Their recent notification published on their blog on 8th October 2014, mentions about the support of this new feature only in Java, .NET, Ruby and JS SDK.