adding URI to laravel response - laravel

I am building an API and I have few models which have a relationship with each other:
Asset
Location
User
I am able to get objects via api by accessing /asset/5 or /location/15
This is all fine and good, now I have started to include some relations with it.. so if asset 5 is related to location 15.. the return from /asset/5 now includes (using WITH) the location info with it.
example:
/asset/5
{
"id": 5,
--> "uri": http: //localhost/api/asset/5, <-- how do i generate/append this
"name": null,
"location": {
"id": 15,
"name": "jimUser",
--> "uri": "http://localhost/api/location/5" <-- how do i generate/append this
}
}
(the URI is not part of my schema.. I want to have it added to the response.)
all of the location info is now returned with the asset. exactly what am looking for..
What I am trying to do is find a way to populate those URI fields with a link that is direct to that entity. so on the /asset/ return that contains the related location info I want to be able to provide a link that goes directly to that location.
I am unable to find a way to generate the URI for either the main response (in this case it is asset) or for a relation (in this case it is location)
I am new to Laravel and am trying to basically mirror an application that has this same type of reponse.
Any help is appreciated.
Thanks
I tried working with $request, $router and many others.

Create an accessor for your uri attribute and set it to be appended automatically to the JSON response:
// Location.php
class Location
{
protected $appends = ['uri'];
...
public function getUriAttribute()
{
return '/api/locations/' . $this->id;
}
}

Related

Can I get the model or model name from a strapi request context?

I am building a policy in a Strapi instance. I want it to be a global policy that I can apply anywhere in the app, but I'll need to evaluate the model specific to the endpoint being requested. For example if I put this policy on a "restaurants" endpoint, I want to be able to make a query on the "restaurant" model.
The request of course would be something to the effect of "POST /restaurants/1234" And I know I could do a string split on the forward slash and drop the "s" from the end of restaurants. But I want to know is there a better supported way of converting the restaurants url into the actual serviceable model name?
I solved it by parsing the route handler. Not sure if this is a cleaner way.
module.exports = async (ctx, config, { strapi }) => {
let handler = ctx.state.route.handler;
let modelName = handler.substring(0, handler.lastIndexOf("."));
const entities = await strapi.db.query(modelName).findMany({
where: {
owner: ctx.state.user.id,
},
});
};

How to create routes configuration itself dynamically

In one of my use case, i have all my route information in a json file and i want to read the file and create the routes accordingly.
for example,
if i have declared route like this in my json config file
{
"config": [
{
"routeSrcSystem": "System1",
"routes": [
{
"fromRoute": {
"type": "default",
"typeValue": "direct:CMStart"
},
"toRoute": {
"type": "http"
"typeMethod": "POST",
"typeContent": "application/json",
"typeValue": "http://localhost:8080/v1/System1/inboundMessage"
}
}
]
}
]
}
then i able to create the routes as below dynamically. but here though its dynamic,the route definition is not dynamic because i have used one "from" and one "to" definition but parameter for this definition i am passing dynamically.
public class GenerateRouter extends RouteBuilder {
private RoutesMetadata routesMetadata;
public GenerateRouter(CamelContext context,RoutesMetadata routesMetadata) {
super(context);
this.routesMetadata=routesMetadata;
}
#Override
public void configure() throws Exception {
from(routesMetadata.getFromRoute().getTypeValue())
.setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
.setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
.to(routesMetadata.getToRoute().getTypeValue());
}
}
But i would like to do the route definition itself dynamically. for example, i have route config like this,
{
"config": [
{
"routeSrcSystem": "System1",
"routes": [
{
"fromRoute": {
"type": "default",
"typeValue": "direct:CMStart"
},
"toRoute1": {
"type": "http"
"typeMethod": "POST",
"typeContent": "application/json",
"typeValue": "http://localhost:8080/v1/System1/inboundMessage"
}
"toRoute2": {
"type": "http"
"typeMethod": "POST",
"typeContent": "application/json",
"typeValue": "http://localhost:8080/v1/System2/inboundMessage"
}
}
]
}
]
}
then in my route definition i need to add one more "to" definition dynamically. its just example. it could be more dynamic. for example, configuration can be changed to introduce "process" or "bean" or "class" definition. so based on the config, we need to decide how many "to" to be created and how many "process" to be created and etc. I might need to call the next rest end point after some validation and etc and some times i need to call kafka to put the message in queue. i do see an option to list all routes in a list and execute it but i think we need to have flexibility to add process or to or class definition before we call next end point and this has to be based on configuration.
public class GenerateRouter extends RouteBuilder {
private RoutesMetadata routesMetadata;
public GenerateRouter(CamelContext context,RoutesMetadata routesMetadata) {
super(context);
this.routesMetadata=routesMetadata;
}
#Override
public void configure() throws Exception {
from(routesMetadata.getFromRoute().getTypeValue())
.setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
.setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
.to(routesMetadata.getToRoute().getTypeValue())
.setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
.setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
.to(routesMetadata.getToRoute().getTypeValue());
}
}
I saw some information where route definition itself can be defined dynamically and i am doing research on it. but meantime i would like to post this here to get experts opinion. Also, please suggest whether I am using the camel on right way? because in my use case i am thinking to add "to" definition to which pass the class name dynamically based on configuration file, so that application developer can do their logic for transformation, enrich or manipulation in this class on the fly before deliver to target system. please let me know if we have any better approach. also, let me know whether XML way of doing is good way or defining own config file in json format is a good way to create dynamic route.
i am planning to read the json file and create a router definition as a string dynamically. but i would need to load this string as a definition in context it seems. i think i am missing this part.
.to("class:com.xxx.camel.layoutTransform?method=layout()")
if we provide all these configurations in xml file and if camel supports to create the route definition automatically using this file then we can consider this option as well.
Below is the one of the way from another source to create the router definition using XML file. within the XML, we have router information defined and this xml considered as a string and this string is converted as router-definition object and finally added into context.
<routes
xmlns=\"http://camel.apache.org/schema/spring\">
<route>
<from uri='direct:c'/>
<to uri='mock:d'/>
</route>
</routes>
CamelContext context = new DefaultCamelContext();
context.setTracing(true);
String xmlString = "<routes xmlns=\"http://camel.apache.org/schema/spring\"><route><from uri='direct:c'/><to uri='mock:d'/></route></routes>";
InputStream is = new ByteArrayInputStream(xmlString.getBytes());
RoutesDefinition routes = context.loadRoutesDefinition(is);
context.addRouteDefinitions(routes.getRoutes());
context.start();
ProducerTemplate template = null;
template = context.createProducerTemplate();
template.start();
template.sendBody("direct:c", "HelloC");
Thread.sleep(10000);
context.stop();
I would like to do the similar concept using java dsl definition as a string.
for example, if i have string as below then can this be converted as a router definition?
String dslString = "from("direct:starting").to("seda:end")";
Here is my use case. Sometime, we want to call 2 http services as below
from("direct:start").to(http://localhost:8080/service1).to("http://localhost:8080/service2")
Somtimes we might need to call 3 services as like below
from("direct:start").to(http://localhost:8080/service1).to("http://localhost:8080/service2").to("http://localhost:8080/service3")
sometimes we need to do transformation before we invoke service2 as like below.
from("direct:start").to(http://localhost:8080/service1).to("class:com.xxx.yyy").to("http://localhost:8080/service2").to("http://localhost:8080/service3")
In the even driven architecture, we will have set of routes must be defined for each event types. so the idea is, if we define these routes in a table for each event type, then at the time of service start up all the routes will be loaded in context and will be started. I am able to do the same in XML DSL way but trying to do the same in java DSL.
Thanks in advance!
Camel supports defining all details about routes in a particular XML-based format. This page has links to that (and other) DSLs.
You could definitely come up with your own DSL and build routes dynamically, but that's a lot of work if you want to support all the things a full Camel DSL would support. I would suspect that is not the right solution for whatever your use-case.
If you have certain patterns to your routes, you can create fairly dynamic Camel route-builders that are driven by some configuration. To make this concrete, let's say you have many use cases that follow a very similar pattern... say, consumer data from files in a folder, do a few transformations from a menu of (say) 10-15 transformations, and then sends output to one of many queues.
Since you have various possible combinations, it could make sense to configure those details in file etc. and then build some routes off that. The trade-off is not different from any other place where you have to decide if it is clearer to just code the 10 things you want, or to make something more complex but generic.
Essentially, you would still be creating a DSL or sorts, but one that is closer to your use case.

Google Search Console - get property set name

I work with "Search Console API v3" now.
When I use "webmasters.sites.list" method, I get site URLs and propery sets. Propery set for expample - "sc-set:B9KPftMA4RltK1LS61GR2g".
But I can't find any way to get REAL NAME for property set using API.
I can't show this id "sc-set:B9KPftMA4RltK1LS61GR2g" to client instead normal name.
Example of response:
"siteEntry": [ { "siteUrl": "example.com", "permissionLevel": "siteRestrictedUser" },
{ "siteUrl": "sc-set:2d0rU0BQiIHsmCH-HGZ1KA", "permissionLevel": "siteRestrictedUser" }
]
when you call sites.list it returns a list of site resources which contain
{
"siteUrl": "http://www.daimto.com/",
"permissionLevel": "siteOwner"
},
There is no way to get any additional information about the site than that. What i am not able to understand is why you appear to be getting back some kind of id.

Associate relationship afterwards

Version used: Laravel 5.4
We have a post and that post can have several pictures associated with it. We use a controller to store the post and an other one to store the pictures.
We set the relationship in the models like so:
class Post extends Model
{
public function pictures()
{
return $this->hasMany(Picture::class);
}
}
class Picture extends Model
{
public function post()
{
return $this->belongsTo(Post::class);
}
}
When I go to the form to create a new post, I can add pictures to that post before I actually store the post. Which means that when I store a picture I still don't have a post id to associated it to.
My questions is:
Using only php, is there a clean way to associate the pictures to the post before or afterwards ?
The solution I am currently using is that when I go to the form to create a new post, a blank new post is created before hand and I pass the id on the url. It has to be a better way to do it.
You can try this
First create the form when user access the create post page (as you are already doing).
Suppose this is your function which is showing the create post view
public function showCreatePost()
{
$post = Post::create(['field_name' => '', // put your attributes]);
// pass other data as well if you want.
return view('your_create_view',compact('postId',$postId));
}
change your route of imageupload which will have postid . for example
Route::post('post/image/{postId}','SomeController#somefunction');
create one route for editing the post and use it for editing the post which will have post id.
Route::post('post/edit/{postId}','SomeController#someOtherfunction');
Now use these two routes as form action and you can edit the post and upload the image. route example below
Showing the id in url is not a good idea. so by this way you can try and let me know if you face any problem.

spring data rest hal browser: how to expose resource descriptions and document

I have looked all over the net, trolled through spring-data-rest source code and tried to decipher how the JS for the hal-browser is trying to retrieve 'title' and 'doc' details for a resource. I have also discovered that there are
#RepositoryRestResource(
collectionResourceRel = "roles",
path = "roles",
itemResourceDescription = #Description("This is a test description")
)
Annotations I can put in the #Repostitory, but it doesn't seem to do anything.
Specifically, if you look at this example, how do I get "title|doc" to fill in"
I filed a ticket with spring and haven't heard back.
From what I can see the HAL Browser expects the link to contain the title property. In the example you linked:
{
"motd": "Welcome to the OSDI Example Action Platform OSDI API endpoint!!",
"_links": {
"osdi:people": {
"href": "http://api.opensupporter.org/api/v1/people",
"title": "The collection of people in the system"
}
...
}
The org.springframework.hateoas.Link class does not support that property as of version 0.19.0.RELEASE. No idea about the docs though...

Resources