I am using Laravel 5. I have two tables named cars and providers. There is a foreign key in cars table named provider_id of provider table.
My database schema as follows-
Schema::create('cars', function(Blueprint $table)
{
$table->increments('id');
$table->integer('provider_id')->unsigned();
$table->foreign('provider_id')->references('id')->on('providers')->onDelete('restrict');
});
Schema::create('providers', function(Blueprint $table) {
$table->increments('id');
$table->string('company_name');
});
Now, I want to fetch cars information as well as provider info of that particular id.
Take a look at this
Inside your Car model, create a provider method:
public function provider()
{
return this->belongsTo(\App\Provider);
}
Then, you can do something like:
$car = \App\Car::find(id);
And access the provider this way:
$car->provider();
Also, inside your provider model, add this:
public function cars()
{
return $this->hasMany(\App\Car);
}
And you'll be able to access all cars from a particular provider.
Related
I am planning to use AWS Amplify as a backend for a mobile application. The App consists of two User Types (UserTypeA,UserTypeB). They have some common data points and some unique one's too.
UserTypeA(id, email, firstName, lastName, profilePicture, someUniquePropertyForUserTypeA)
UserTypeB(id, email, firstName, lastName, profilePicture, someUniquePropertyForUserTypeB)
What would be a scalable approach to achieve this? I am also using AWS Amplify authentication so I can save the common data as CustomAttributes offered by Cognito, but then how would I save the uniqueProperties for the two user types. Will this approach scale?
This is a social app and is heavily reliant on other users' profile data as well (which will be queried most of the time).
Check out the patterns that are recommended by AppSync (The graphQL service that is behind Amplify when adding graphQL API). It is described in detail here: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html
The main idea is to have multiple user pools defined in Cognito and then you can use the different groups in the resolvers. For example:
// This checks if the user is part of the Admin group and makes the call
#foreach($group in $context.identity.claims.get("cognito:groups"))
#if($group == "Admin")
#set($inCognitoGroup = true)
#end
#end
#if($inCognitoGroup)
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
},
"attributeValues" : {
"owner" : $util.dynamodb.toDynamoDBJson($context.identity.username)
#foreach( $entry in $context.arguments.entrySet() )
,"${entry.key}" : $util.dynamodb.toDynamoDBJson($entry.value)
#end
}
}
#else
$utils.unauthorized()
#end
or using the #directives on the graphQL schema, such as:
type Query {
posts:[Post!]!
#aws_auth(cognito_groups: ["Bloggers", "Readers"])
}
type Mutation {
addPost(id:ID!, title:String!):Post!
#aws_auth(cognito_groups: ["Bloggers"])
}
...
This is a Database design problem. To solve this, you can try creating a relation that has the common attributes in it, that is, User with attributes, (ID, email, firstName, lastName, profilePicture, someUniquePropertyForUserTypeA).
After that, create sub-classed based relations, that is UserTypeA, and UserTypeB.
These relations will have a unique ID, and have a foreign key relation with the parent (User). How? The first major relation would be 'User'. The 2 sub classed relations would be 'UserTypeA', and 'UserTypeB'.
The 'User' has an attribute 'ID'.
So the two sub classes have an attribute, 'User_ID', which is a foregin relation to 'User'.'ID'.
Now just autogen another ID column for UserTypeA and UserTypeB.
This way, you have a central table which has a unique ID for all users, and then you have a unique ID in each of the sub class relations, which together with User_ID forms a composite key.
I'm trying to use AWS CDK to create a user with minimal permissions through a custom policy, but I'm stuck with tagging that user and creating its access keys.
Below there's my code:
public class Sample extends App {
public static void main(final String[] args) {
App app = new App();
new UserStack(app, "user-stack");
app.run();
}
public static class UserStack extends Stack {
// Not able to add Tag and Create Access Key
public UserStack(final App parent, final String name) {
super(parent, name);
PolicyStatement statement = new PolicyStatement(PolicyStatementEffect.Allow);
statement.addResource("*");
statement.addAction("lambda:UpdateFunctionCode");
User user = new User(this, "LambdaDeployer", UserProps.builder().withUserName("lambda-deployer").withPath("/").build());
user.addToPolicy(statement);
Tag tag = new Tag("Project", "devops");
// how to tag the user ??
new CfnOutput(this, "LambdaDeployerOutputAccessKey", CfnOutputProps.builder().withValue("AWS::IAM::AccessKey").build());
new CfnOutput(this, "LambdaDeployerOutputSecretAccessKey", CfnOutputProps.builder().withValue("AWS::IAM::SecretAccessKey").build());
}
}
}
You'll probably have to use a Custom Resource in order to call the TagUser API, since adding tags to a User is not available natively in CloudFormation.
You can use a new feature in the CDK to help you author your Custom Resource: https://github.com/awslabs/aws-cdk/pull/1850
Does AppSync support nested single mutation?
I want to call a single mutation which will insert records into two tables, eg: User and Roles tables in DynamoDB.
Something like this for example:
createUser(
input: {
Name: "John"
Email: "user#domain.com"
LinesRoles: [
{ Name: "Role 1" }
{ Name: "Role 2" }
]
}) {
Id
Name
LinesRoles {
Id
Name
}
}
Do I need to create two resolvers in AppSync for User and Roles to insert the records in both tables?
I can think of three ways to achieve this:
Use a BatchPutItem to save records into two tables at once. However, you won’t be able to use any ConditionExpression
Use a pipeline resolver with two AppSync functions where one function makes a PutItem to the Roles table and the other to the User table. However, you need to be ok with potentially inconsistent scenarios where the record has been inserted in one table but not in the other.
Use a Lambda resolver that does the write to 2 tables inside a DynamoDB transaction.
I have users table and subscriptions table.
subscriptions table it has a foreign key column user_id and other column status of type enum and has set of values ('canceled','active','skipped','unpaid','pastdue','expired')
In model, I defined their relation like,
public function subscription()
{
return $this->hasMany(Subscription::class);
}
Now I am implementing a filter functionality
in this function in my dataTable class
public function query(User $model)
{
if ($this->_filters['subscription_status']) {
$status = $this->_filters['subscription_status'];
$model = $model->whereHas('subscription', function($query) use ($status) {
$query->where('status', $status);
});
}
Now when I tried to get the list of user with subscription status canceled
the result, I got a list of users with status active and cancelled why the code above doesn't work?
You should use with not has. You can see the different.
get the list of users with subscription status canceled
$model = $model->with(['subscription' => function ($query) use ($status) {
$query->where('status', status);
}])
get the list of users has subscription status canceled
$model = $model->whereHas('subscription', function($query) use ($status) {
$query->where('status', $status);
});
I created the schema and resources (the DynamoDB tables), and I also attached the needed resolvers. Here is the screenshot of the User table with some sample data.
Sample data
For the first user, there are only id and username. Other fields are empty. When I query this user in AppSync console, there will be some error.
Query Error
Here is the query I used:
query getUser{
getUser(id:"5d0a2154-b828-4bcb-a34a-07503fe4b458"){
id
username
userProfile{
id
lastName
firstName
}
school{
id
schoolName
schoolAddress
}
role{
name
}
studentCourseSessions{
id
notes
}
programs{
name
courses{
name
}
}
}
}
And here is the VTL for the getUser query
Seems like, if a field is empty, there will be an error. I want, if the field is not filled, it should return "null". It can still return error but I need the "null" as well.
I am new to AppSync and DynamoDB.