php Restler Routes - php

I am using Restler 2.0 and I'm trying to add a new route based on the CRUD example
$o['GET']['author/:name/:email']=array (
'class_name' => 'Author',
'method_name' => 'getLogin',
'arguments' =>
array (
'name' => 0,
'email' => 1,
),
'defaults' =>
array (
0 => NULL,
1 => NULL,
),
'metadata' =>
array (
),
'method_flag' => 0,
);
when I make the url call in the browser http://[host]/author/[name to pull]/[email to pull]
I get the following error:
{
"error": {
"code": 404,
"message": "Not Found"
}
}
my author code has been updated with the following method
function getLogin($name=NULL,$email=NULL) {
print "in author, getting login";
return $this->dp->getLogin($name,$email);
}
I am stumped.

Luracast Restler Auto Routing
Firstly, routes.php is auto generated when you run Restler in production mode
$r = new Restler(TRUE);
which will be overwritten when we call
$r->refreshCache();
or run it in debug mode, so it should not be hand coded.
Restler 2.0 is using auto mapping which is better explained in the updated CRUD Example.
Corrected version of your method should be
function get($name=NULL,$email=NULL) {
print "in author, getting login";
return $this->dp->getLogin($name,$email);
}
which will map to
GET /author/:email/:password
where as your method is currently mapping to
GET /author/login/:email/:password
Luracast Restler Custom Routing
Also note that you can use PHPDoc comment to create custom mappings and you can add more than one. For example
/*
* #url GET /custom/mapping/:name/:email
* #url GET /another/:name/:email
*/
function get($name=NULL,$email=NULL) {
print "in author, getting login";
return $this->dp->getLogin($name,$email);
}
this will create the following routes, and disable auto routing for that method.
GET /author/custom/mapping/:email/:password
GET /author/another/:email/:password

Related

how to change paginate response?

In Laravel no way to replace the default structure for paginated responses. This is the structure I'm trying to achieve:
return response()->json([
'data' => $items->items()
'meta' => [
'current_page' => $items->currentPage(),
'from' => $items->firstItem(),
'last_page' => $items->lastPage(),
'per_page' => $items->perPage(),
'to' => $items->lastItem(),
'total' => $items->total(),
];
]);
I have solved this issue before with resource collection. This is not supported by Laravel out of the box so it needs a bit of work.
First, you got to override the App\Http\Resources\PaginatedResourceResponse class, which is the default way to present paginated response. Then you can override the default structure of the returned paginated data.
class CustomPaginatedResourceResponse extends PaginatedResourceResponse
{
}
Then pls create a resource collection that uses the custom paginated resource.
class ItemsResource extends ResourceCollection
{
public function toArray($request)
{
}
// Override the toResponse method.
public function toResponse($request)
{
return $this->resource instanceof AbstractPaginator
? (new CustomPaginatedResourceResponse($this))->toResponse($request)
: parent::toResponse($request);
}
}
Finally, you can simply use the ItemsResource in your controller.
return new ItemsResource($items);
This requires understanding of the api resources and the source code. Pls spend some time to read the docs and figure out how the App\Http\Resources\PaginatedResourceResponse is used.

Unable to locate factory with name on production?

I create a factory of a model inside an artisan command:
public function handle()
{
if (!$this->isDevelopment()) {
$this->errorMessageSwitchEnvToDev();
return;
}
$userId = $this->ask('Please specifiy user_id you want to add the payouts to.',2148);
$numberOfPayouts = $this->ask('How many payouts you want to generate?', 10);
factory(\App\Payout::class, $numberOfPayouts)->create([
'user_id' => $userId,
]);
}
The artisan works on my local desktop, but it does not work after deployment on my test server.
I get the following error message:
InvalidArgumentException : Unable to locate factory with name [100] [App\Payout].
at /www/htdocs/w0146a6f/dev/dev4.partner.healyworld.net/releases/20201014150056/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:269
265| */
266| protected function getRawAttributes(array $attributes = [])
267| {
268| if (! isset($this->definitions[$this->class][$this->name])) {
> 269| throw new InvalidArgumentException("Unable to locate factory with name [{$this->name}] [{$this->class}].");
270| }
271|
272| $definition = call_user_func(
273| $this->definitions[$this->class][$this->name],
Exception trace:
1 Illuminate\Database\Eloquent\FactoryBuilder::getRawAttributes([])
/www/htdocs/w0146a6f/dev/dev4.partner.healyworld.net/releases/20201014150056/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:292
2 Illuminate\Database\Eloquent\FactoryBuilder::Illuminate\Database\Eloquent\{closure}()
/www/htdocs/w0146a6f/dev/dev4.partner.healyworld.net/releases/20201014150056/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php:122
I do the deployment with envoyer.
My factory is defined in database/factories/PayoutFactory.php
<?php
$factory->define(\App\Payout::class, function (Faker\Generator $faker) {
return [
'user_id' => function () {
return factory(App\User::class)->create()->id;
},
'amount' => $faker->randomFloat(2),
'req_amount' => 0,
'tax_amount' => 0,
'withheld' => 0,
'vat_rate' => $faker->randomNumber(2),
'released_amount' => $faker->randomFloat(2),
'released_amount_local_currency' => $faker->randomFloat(2),
'status' => 'released',
'flag' => 0,
'created_at' => $faker->dateTimeBetween('-6 months', 'now'),
];
});
However, it won't work on production. I already cleared the cache, the routes and called composer dump-autoload, but it still failes with the same issue.
Any suggestions?
I also read all answers of Laravel 5.2: Unable to locate factory with name [default] but none of them worked.
Notice this:
Unable to locate factory with name [100]
It looks like factory() is willing to use states instead of quantity. In this case it's looking for a factory state called (string) "100" instead of (int) 100
Cast your amount variable to be an integer
$numberOfPayouts = (int) $this->ask('How many payouts you want to generate?', 10);
Alternatively, try using ->times($amount) method to be more explicit.

TYPO3 v10 - Getting feUser Object using context API in eID_include

Code that i used and need to update for V10
$this->feUser = EidUtility::initFeUser();
When using the following code (a random) controller, the context gives me the correct login feUser object.
$context = GeneralUtility::makeInstance(Context::class);
$user = $context->getAspect('frontend.user');
DebuggerUtility::var_dump($user);
When using the same code in an eID_include class No userObject is given.
Specificly in the following class
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['FileDumpEID.php']['checkFileAccess']['xxx'] = My\Class\Hooks\FileDumpHook:class
Is there a need of bootstrapping context?
Since the TYPO3\CMS\Frontend\Middleware\EidHandler middleware is executed before the TYPO3\CMS\Frontend\Middleware\FrontendUserAuthenticator middleware in the middlewares order i dont think, that this is possible.
If you need parts of the frontend handling you either can add an own middleware with depend of TYPO3\CMS\Frontend\Middleware\FrontendUserAuthenticator or use an page Object in typoscript.
I had the same problem. You may change the order of Middlewares: https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/RequestHandling/Index.html
I've created a new file RequestMiddlewares.php inside the "Configuration" directory of my extension:
<?php
return [
'frontend' => [
'typo3/cms-frontend/eid' => [
'disabled' => true
],
'typo3/cms-frontend/eid-new' => [
'target' => \TYPO3\CMS\Frontend\Middleware\EidHandler::class,
'after' => [
'typo3/cms-frontend/tsfe',
],
'before' => [
'typo3/cms-frontend/prepare-tsfe-rendering',
]
]
]
];
You have to flush TYPO3 and PHP Cache and check the ordering in "Configuration" backend module (select "HTTP Middlewares (PSR-15)").
With this setup it is possible to get the context property 'frontent.user'
$context = GeneralUtility::makeInstance(Context::class);
if($context->getPropertyFromAspect('frontend.user', 'isLoggedIn')) {

In Laravel 4, How are the merging rulesets implemented?

I'm using the dwightwatson/validating package to create validation rules in the model.
I particularly like the custom rulesets you can create for different routes.
Model
protected $rulesets = [
'set_up_all' => [
'headline' => 'required|max:100',
'description' => 'required'
],
'set_up_property' => [
'pets' => 'required'
],
'set_up_room' => [
'residents_gender' => 'required',
'residents_smoker' => 'required'
],
'set_up_roommate' => [
'personal_gender' => 'required',
'personal_smoker' => 'required'
]
];
Controller
$post = new Post(Input::all());
if($post->isValid('set_up_all', false)) {
return 'It passed validation';
} else {
return 'It failed validation';
}
In the above example, it works well in validating against the set_up_all ruleset. Now I would like to combine several rulesets and validate against all of them together.
According to the documentation, the package offers a way to merge rulesets. I just can't figure out how to integrate the example provided into my current flow.
According to the docs, I need to implement this line:
$mergedRules = $post->mergeRulesets('set_up_all', 'set_up_property_room', 'set_up_property');
This was my attempt, but it didn't work:
if($mergedRules->isValid()) { ...
I get the following error:
Call to a member function isValid() on array
I also tried this, but that didn't work either:
if($post->isValid($mergedRules)) { ...
I get the following error:
array_key_exists(): The first argument should be either a string or an integer
Any suggestions on how I would implement the merging rulesets?
From what I can see - mergeRulesets() returns an array of rules.
So if you do this - it might work:
$post = new Post(Input::all());
$post->setRules($post->mergeRulesets('set_up_all', 'set_up_property_room', 'set_up_property'));
if($post->isValid()) {
///
}
I've released an update version of the package for Laravel 4.2 (0.10.7) which now allows you to pass your rules to the isValid() method to validate against them.
$post->isValid($mergedRules);
The other answers will work, but this syntax is nicer (and won't override the existing rules on the model).

Laravel Unit Testing with MongoDB and Object arrays

Hello I'm pretty new to PHPUnit and Laravel 4.
I've created an REST API and I'm trying to add a new User using laravel (PHPUnit) unit tests, to my test DB. The problem is, that it completely disregards the Object array that I'm trying to add with the user doc creation.
A typical User Doc would look as follows:
{
_id": ObjectId("53021089b4d15220118b4568"),
"oArr": {
"something": {
"somewhere": "5th Avenue",
"ip": "192.168.0.20"
},
"something2": {
"somewhere": "6th Avenue",
"ip": "192.168.0.21"
}
}
"email": "jessica#example.com",
"name": "Jessica Alba",
"password": "$2y$10$RAVzUGLAG.81IOOUum0k0u5vrcY98H.L42FeSJekEywUCV.ycttn6"
}
Now Laravel has it's own Testing class TestCase which your Unit tests extend.
Typical example would be the following:
class AddUserTest extends TestCase {
/**
* A basic functional test example.
*
* #return void
*/
public function testCreateUsers()
{
$post_data = array(
'email' => 'emma#example.com',
'name' => 'Emma Watson',
'password' => 'password',
'oArr' => array(
'something' => array(
'somewhere' => '7th Avenue',
'ip' : => '192.168.0.31'
),
),
);
}
}
Once the user test has run (successfully), the new Emma Watson user (Mongo Doc) look as follows:
{
_id": ObjectId("53021089b4d15220118b4568"),
"email": "emma#example.com",
"name": "Emma Watson",
"password": "$2y$10$asdAzUGLAG.8asvWQOUum0k0u5vrcY98H.LEDeSJekEywUCV.ycttn6"
}
I have no idea how, and couldn't find anyone else with the same problem.
My assumption: The ORM I'm using (https://github.com/jenssegers/Laravel-MongoDB), doesn't cater for Object arrays in Unit Tests.
I have yet to look into how the ORM is handling unit tests, I'm just hoping someone else has had the same problem, and has a more basic solution.
Well, your test returned modified document. Mongodb is automatically appending new _id to every insertion, that is not explicitly marked as update. Also mongo is hashing you password - it is probably done by you package driver. Since mongodb is using nested document, you test probably didn't reach that nested level, and there is no that document.
Completely forgot about this post.
Laravel's Input class handles for JSON input also. So if you're trying to post embedded documents, you might as well do it in an JSON format. The following worked for me.
class AddUserTest extends TestCase {
/**
* A basic functional test example.
*
* #return void
*/
public function testCreateUsers()
{
$post_data = array(
'email' => 'emma#example.com',
'name' => 'Emma Watson',
'password' => 'password',
'oArr' => array(
'something' => array(
'somewhere' => '7th Avenue',
'ip' : => '192.168.0.31'
),
),
);
$post_data = json_encode($post_data);
// Send through the serialized data to the Controller.
}
}

Categories