based on the tutorial for validation in silex i've created a constraint:
$constraint = new Assert\Collection([
'token' => [
new Assert\NotBlank(),
new Assert\Length(['min' => Constant::TOKEN_LENGTH, 'max' => Constant::TOKEN_LENGTH]),
],
'languageCode' => [
new Assert\NotBlank(),
new Assert\Choice(['choices' => [Constant::LANGUAGE_CODE_DE, Constant::LANGUAGE_CODE_EN]])
],
'startDate' => [
new Assert\NotBlank(),
new Assert\Date()
],
'endDate' => [
new Assert\NotBlank(),
new Assert\Date()
],
'duration' => [
new Assert\GreaterThanOrEqual(['value' => 1])
],
]);
which should match the following structures (here from json):
{
"token": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"languageCode": "DE",
"startDate": "2016-01-01",
"endDate": "2016-01-05",
"duration": 1
}
and
{
"token": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"languageCode": "DE",
"startDate": "2016-01-01",
"endDate": "2016-01-05"
}
While first example is validated as expected, the second (with the optional duration) will respond in a strange behavior: the constraints from "endDate" where used:
object(Symfony\Component\Validator\ConstraintViolationList)[154]
private 'violations' =>
array (size=1)
0 =>
object(Symfony\Component\Validator\ConstraintViolation)[158]
private 'message' => string 'This field is missing.' (length=22)
private 'messageTemplate' => string 'This field is missing.' (length=22)
private 'parameters' =>
array (size=1)
'{{ field }}' => string '"duration"' (length=10)
private 'plural' => null
private 'root' =>
array (size=4)
'token' => string 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' (length=64)
'languageCode' => string 'DE' (length=2)
'startDate' => string '2016-01-01' (length=10)
'endDate' => string '2016-01-05' (length=10)
private 'propertyPath' => string '[duration]' (length=10)
private 'invalidValue' => null
private 'constraint' =>
object(Symfony\Component\Validator\Constraints\Date)[136]
public 'message' => string 'This value is not a valid date.' (length=31)
public 'payload' => null
public 'groups' =>
array (size=1)
0 => string 'Default' (length=7)
private 'code' => string '2fa2158c-2a7f-484b-98aa-975522539ff8' (length=36)
private 'cause' => null
I don't see the any reason for that....
try to add parameter allowMissingFields
$constraint = new Assert\Collection([
'allowMissingFields' => true,
'fields' => [asserts...]
]);
Related
First I get the translator by his id using this line of code
$translator = Translator::where('id', $translator_id)->first();
Then I send a notification to him by this code:
$response = Http::withHeaders([
'Authorization' => 'key=myKey',
'Content-Type' => 'application/json'
])->post('https://fcm.googleapis.com/fcm/send', [
"notification" => [
"title" => "title",
"body" => "body",
],
"data" => [
"title" => "title",
"body" => "body",
],
"to" => $token,
]);
Everything works fine but my problem is that when I return the TranslatorResource I want to add the notification response to it, so I do this in my controller
$resource = new TranslatorResource($translator);
$resource->notif = $response;
return $resource;
And in TranslatorResource I have this code:
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'phone' => $this->phone,
'cv' => $this->cv,
'specialization' => $this->specialization,
'tr_languages' => $this->tr_languages,
'all_languages' => $this->all_languages,
'isVerified' => $this->isVerified == 0 ? false : true,
'isActive' => $this->isActive == 0 ? false : true,
'completed_orders' => $this->completed_orders,
'canceled_orders' => $this->canceled_orders,
'rejected_orders' => $this->rejected_orders,
'current_orders' => $this->current_orders,
'isTranslator' => true,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
But I only get the data specified in the resource, the notif key isn't added, anyone know how to add this data to my resource when I return it ?
You can use additional method provided by laravel.
return (new TranslatorResource($translator))->additional(['notif ' => $response]);
Reference: Eloquent: API Resources
You can look for the section Adding Meta Data When Constructing Resources.
I have the following model:
abstract class ApiObjectModel extends Model
{
protected $appends = ['unique', 'created_by', 'updated_by'];
protected $hidden = ['deleted_at', 'head', 'create_id', 'update_id', 'createdByUser', 'updatedByUser'];
protected $casts = [
'created_at' => 'datetime:Y-m-d h:m',
'updated_at' => 'datetime:Y-m-d h:m',
];
/*
* other stuff
*/
public function getCreatedAtAttribute($value)
{
return Carbon::parse($value)->diffForHumans();
}
public function getUpdatedAtAttribute($value)
{
return Carbon::parse($value)->diffForHumans();
}
}
and this class:
class Ticket extends ApiObjectModel
{
protected $table = 'Ticket';
protected $fillable = ['Title', 'Description'];
}
I am running the following Test:
/** #test **/
public function updating_an_object_changes_the_update_at_time()
{
$response = $this->post('api/ticket', $this->basic_data());
//prüft Json
$response->assertJsonFragment([
'created_at' => $this->createtime,
'updated_at' => $this->createtime,
'created_by' => User::first()->name,
'updated_by' => User::first()->name,
]);
Carbon::setTestNow(Carbon::getTestNow()->addMinutes(30));
$response = $this->put('api/ticket/1', [
'Title' => 'Update'
]);
$response->assertJsonFragment([
'created_at' => $this->createtime,
'updated_at' => Carbon::getTestNow()->addMinutes(30)->diffForHumans(),
'created_by' => User::first()->name,
'updated_by' => User::first()->name,
]);
}
The Test fails because the created_at and the updated_at values are switched.
In my Controller, after doing some debug work, I found out the following result basically one line after the other:
dump(Ticket::findOrFail($id))
Result:
...
#attributes: array:8 [
"id" => 1
"Title" => "Update"
"Description" => "Change Description"
"create_id" => 1
"update_id" => 1
"created_at" => "2030-02-10 12:00:00"
"updated_at" => "2030-02-10 12:30:00"
"deleted_at" => null
]
...
dd(Ticket::findOrFail($id)->toArray())
Result:
array:8 [
"id" => 1
"Title" => "Update"
"Description" => "Change Description"
"created_at" => "30 minutes ago"
"updated_at" => "1 second ago"
"unique" => 1
"created_by" => "Test User 1"
"updated_by" => "Test User 1"
]
Can somebody help me understand and debug this?
(Laravel Framework 6.1.0)
nevermind... I was confusing the difftohuman() values from Carbon and set up the tests wrong.
This just passed:
/** #test **/
public function updating_an_object_changes_the_update_at_time()
{
$response = $this->post('api/ticket', $this->basic_data());
//prüft Json
$response->assertJsonFragment([
'created_at' => $this->createtime,
'updated_at' => $this->createtime,
'created_by' => User::first()->name,
'updated_by' => User::first()->name,
]);
Carbon::setTestNow(Carbon::getTestNow()->addMinutes(30));
$response = $this->put('api/ticket/1', [
'Title' => 'Update'
]);
$response->assertJsonFragment([
// following two lines got changed:
'created_at' => Carbon::now()->subMinutes(30)->diffForHumans(),
'updated_at' => Carbon::now()->diffForHumans(),
'created_by' => User::first()->name,
'updated_by' => User::first()->name,
]);
}
If you have other ideas how to spend your thoughts in circles... let me know
When I use the following PostResource, and Post Test, my tests succeed:
PostResource.php
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
'slug' => $this->slug,
];
}
PostController.php
public function show(Post $post)
{
return new PostResource($post);
}
ReadPostTest.php
/** #test */
public function a_user_can_read_a_single_post()
{
$post = factory(Post::class)->create([
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
]);
//dd($post);
$response = $this->json('GET', '/posts/' . $post->id)
->assertStatus(200)
->assertJsonFragment([ 'data' => [
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
]]);
}
When I add created_at and updated_at to my tests and resource I get a failure. The test bellow show when I didn't add .000000Z.
phpunit
There was 1 failure:
1) Tests\Feature\ReadPostsTest::a_user_can_read_a_single_post
Unable to find JSON:
[{
"data": {
"title": "A new post",
"content": "Some content",
"slug": "a-new-post",
"created_at": "2018-12-06 21:13:26",
"updated_at": "2018-12-06 21:13:26"
}
}]
within response JSON:
[{
"data": {
"id": 1,
"title": "A new post",
"content": "Some content",
"slug": "a-new-post",
"created_at": "2018-12-06T21:13:26.000000Z",
"updated_at": "2018-12-06T21:13:26.000000Z"
}
}].
Failed asserting that an array has the subset Array &0 (
'data' => Array &1 (
'title' => 'A new post'
'content' => 'Some content'
'slug' => 'a-new-post'
'created_at' => '2018-12-06 21:13:26'
'updated_at' => '2018-12-06 21:13:26'
)
).
--- Expected
+++ Actual
## ##
'title' => 'A new post',
'content' => 'Some content',
'slug' => 'a-new-post',
- 'created_at' => '2018-12-06 21:13:26',
- 'updated_at' => '2018-12-06 21:13:26',
+ 'created_at' => '2018-12-06T21:13:26.000000Z',
+ 'updated_at' => '2018-12-06T21:13:26.000000Z',
),
)
I tried adding 000000Z that and got the same problems.
There was 1 failure:
1) Tests\Feature\ReadPostsTest::a_user_can_read_a_single_post
Unable to find JSON fragment:
[{"data":{"content":"Some content","created_at":"2019-12-20 21:42:33.000000Z","id":1,"slug":"a-new-post","title":"A new post","updated_at":"2019-12-20 21:42:33.000000Z"}}]
within
[{"data":{"content":"Some content","created_at":"2019-12-20T21:42:33.000000Z","id":1,"slug":"a-new-post","title":"A new post","updated_at":"2019-12-20T21:42:33.000000Z"}}].
Failed asserting that false is true.
It seems like my created_at and up_dated at timestamps are messed up for a reason that I have no idea why? 2019-12-20T21:42:33.000000ZThat's probably what's getting my tests to fail. How do I fix this?
Use carbon on your post model factory and then use $post->created_at and $post->updated_at in the json assertion:
public function a_user_can_read_a_single_post()
{
$post = factory(Post::class)->create([
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => Carbon::now()->timestamp,
"created_at" => Carbon::now()->timestamp
]);
//dd($post);
$response = $this->json('GET', '/posts/' . $post->id)
->assertStatus(200)
->assertJsonFragment([ 'data' => [
'id' => 1,
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => $post->updated_at,
"created_at" => $post->created_at
]]);
}
For some reason a string of timestamps doesn't work. Hopefully someone else can comment as to why.
You probably want to use Carbon's setTestNow() to fix what 'now' means during the test.
Written with the assumption you are using Laravel.
// Immutable, so you don't go insane.
$now = \Carbon\CarbonImmutable::now()->micro(0);
// Fix Carbon's 'now' to that time
\Illuminate\Support\Carbon::setTestNow($now)
// \Carbon\CarbonImmutable::setTestNow($now);
// Your tests here
// u = microseconds, but it's not set to '000000' in 'now', if you forget `->micro(0)`.
// The 'Y-m-d\TH:i:s.u\Z' format works with Laravel 6.20.19 in march 2021, but YMMV.
// ->assertJSon(['created_at' => $now->utc()->format('Y-m-d\TH:i:s.000000\Z'),])
// Release Carbon's 'now' time to follow your clock again.
\Illuminate\Support\Carbon::setTestNow(null)
// \Carbon\CarbonImmutable::setTestNow(null);
It looks like you're struggling with the timestamps format. I had the same issue and solved it through the JSON serialization, found in the Carbon documentation. In your case, it must look like this:
public function a_user_can_read_a_single_post()
{
$post = factory(Post::class)->create([
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => Carbon::now()->timestamp,
"created_at" => Carbon::now()->timestamp
]);
$response = $this->json('GET', '/posts/' . $post->id)
->assertStatus(200)
->assertJsonFragment([ 'data' => [
'id' => 1,
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => $post->updated_at->jsonSerialize(),
"created_at" => $post->created_at->jsonSerialize()
]]);
}
It may be a little late, but hopefully helps to others.
Good luck buddy.
It works for me when I do this (Note: I put the date with ones to simplify the process):
use Carbon\Carbon;
class ExampleTest extends TestCase
{
protected function setUp(): void
{
Carbon::setTestNow(Carbon::create(1111, 1, 11, 11));
}
/** #test */
public function your_awesome_test()
{
$this->postJson(route('route.name'),[
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
])->assertJsonFragment([
'data' => [
'id' => 1,
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => Carbon::setTestNow(),
"created_at" => Carbon::setTestNow()
]
];
}
}
i'm newbie so I hope you can help me.
I have yii2 and i need to implement elasticSearch(ES).
All set up.
I made standart model and standart CRUD. Just a few changes to implement ES like
use yii\elasticsearch\ActiveRecord;
But I have a problem with getting _id in my view/index.php
to get _id in view.php i made
$model->_id = $model->primaryKey;
But how I can fix it with DataProvider in index.php?
my attributes
public function attributes()
{
return [
'_id',
'first_name',
'last_name',
'email',
'created',
'brand',
'product',
'qty',
'sum'
];
}
My rules
public function rules()
{
return [
[['first_name', 'last_name', 'email', 'created',
'brand', 'product', 'qty', 'sum'
],
'safe'],
[['qty'], 'integer'],
[['sum'], 'double'],
['email', 'email'],
];
}
I think it should work like with MongoDB, but it doesn't.
if I want to delete or view or update the data being on index.php I can se only such links w/o id
http://yii2.dev/index.php?r=elastic%2Fdelete&id=
Pls help
P.S.
Here is a var_dump
array (size=5)
0 =>
object(frontend\models\Elastic)[67]
private '_id' (yii\elasticsearch\ActiveRecord) => string 'AVreA6SUvBgWLKxTzUZn' (length=20)
private '_score' (yii\elasticsearch\ActiveRecord) => float 1
private '_version' (yii\elasticsearch\ActiveRecord) => null
private '_highlight' (yii\elasticsearch\ActiveRecord) => null
private '_attributes' (yii\db\BaseActiveRecord) =>
array (size=8)
'created' => string '2017-03-12' (length=10)
'first_name' => string 'Luka' (length=4)
'last_name' => string 'Signori' (length=7)
'email' => string 'l.signori#gmail.com' (length=19)
'brand' => string 'Apple' (length=5)
'product' => string 'iPad' (length=4)
'qty' => string '35' (length=2)
'sum' => string '600.00' (length=6)
private '_oldAttributes' (yii\db\BaseActiveRecord) =>
array (size=8)
'created' => string '2017-03-12' (length=10)
'first_name' => string 'Luka' (length=4)
'last_name' => string 'Signori' (length=7)
'email' => string 'l.signori#gmail.com' (length=19)
'brand' => string 'Apple' (length=5)
'product' => string 'iPad' (length=4)
'qty' => string '35' (length=2)
'sum' => string '600.00' (length=6)
private '_related' (yii\db\BaseActiveRecord) =>
array (size=0)
empty
private '_errors' (yii\base\Model) => null
private '_validators' (yii\base\Model) => null
private '_scenario' (yii\base\Model) => string 'default' (length=7)
private '_events' (yii\base\Component) =>
array (size=0)
empty
private '_behaviors' (yii\base\Component) =>
array (size=0)
empty
you can set.good luck
$dataProvider = new ActiveDataProvider([
'query' => $query,
'key' => ['your primaryKey']
'sort' => [
'defaultOrder' => ['datetime'=>SORT_DESC]
],
]);
My code:
Generating data data provider
$result = Yii::$app->db->createCommand($sql)->queryAll();
$data_provider = new \yii\data\ArrayDataProvider([
'allModels' => $result,
'key' => 'part_id',
'pagination' => [
'pageSize' => 15,
],
]);
View:
ListView::widget([
'dataProvider' => $data_provider,
'layout' => '{items}',
'options' => [
'class' => 'list-view',
'id' => 'search_results'
],
'itemView' => '_result',
]);
And _result :
DetailView::widget([
'model' => $model,
'attributes' => [
'part_id',
],
])
Result:
Part Id 1
Part Id 1
Part Id 1
[...]
Why???
If I do var_dump($data_provider) in View I get:
object(yii\data\ArrayDataProvider)[105]
public 'key' => string 'part_id' (length=7)
public 'allModels' =>
array (size=100)
0 =>
array (size=7)
'part_id' => string '1' (length=1)
[...]
1 =>
array (size=7)
'part_id' => string '2' (length=1)
[...]
2 =>
array (size=7)
'part_id' => string '3' (length=1)
[...]
[...]
What am I doing wrong?