I'm probably missing something simple here but how do I get the primary key for a table using Laravel/Eloquent? When I execute the following I'm getting an Incorrect Syntax error while it works when executing directly on the database.
$primarykey = DB::table('table')->whereRaw('SHOW KEYS FROM table WHERE Key_name = "PRIMARY"')->get();
I tried it with following code and it worked.
$primarykey = DB::select('SHOW KEYS FROM users WHERE Key_name = "PRIMARY"');
I had used select of DB without get method because it returns array like this
[
{#3558
+"Table": "users",
+"Non_unique": 0,
+"Key_name": "PRIMARY",
+"Seq_in_index": 1,
+"Column_name": "id",
+"Collation": "A",
+"Cardinality": 1,
+"Sub_part": null,
+"Packed": null,
+"Null": "",
+"Index_type": "BTREE",
+"Comment": "",
+"Index_comment": "",
},
]
So please try and let me know if you find any issue in it.
Thanks
Related
I running into what I assume is so simple I am just overthinking it. I am running the following commands in my Tinker session and it is working as expected:
$game = Games::find(1);
[!] Aliasing 'Games' to 'App\Models\Games' for this Tinker session.
=> App\Models\Games {#4386
id: 1,
user_id: 1,
title: "Test Game",
description: "This is a test of the game function",
max_players: 8,
deck: "default",
type: "Golf",
privacy: "Public",
current_player: null,
status: "pending",
deleted_at: null,
created_at: "2020-12-18 22:02:17",
updated_at: "2020-12-18 22:02:17",
}
>>> $game->players()->get();
=> Illuminate\Database\Eloquent\Collection {#4322
all: [
App\Models\User {#4384
id: 1,
name: "mark",
email: "test#test.com",
username: "user",
role: null,
email_verified_at: null,
created_at: "2020-12-18 22:02:08",
updated_at: "2020-12-18 22:02:08",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4168
games_id: 1,
user_id: 1,
},
},
],
}
I have essentially placed that exact same code in my controller to pull a list of players in a game:
$game = Games::find($game);
$players = $game->players()->get();
and I am getting this when I hit the route:
Method Illuminate\Database\Eloquent\Collection::players does not exist.
I am confused why this wouldnt work in the controller if it works just fine in Tinker.
Thanks for the help!
The normal usage for find() is to pass an id, and it will return a model instance for that id. However, if you pass in an array, or an object that implements \Illuminate\Contracts\Support\Arrayable, it will return a Collection of all the found instances.
Your controller code is this:
$game = Games::find($game);
If the $game value passed into find() here is an array, it will return a Collection of all the models found using the ids in the array.
Another sneaky issue here is if the $game value passed into find() here is a model instance. In this case, this statement will return a Collection, because models implement the Arrayable contract mentioned above.
So, when you call find() and pass in a model, it will call toArray() on that model, attempt to find records for every value returned in the array, and return a Collection of all the records found.
In either case, $game is now a Collection, and you'll get an error when you attempt to call $game->players(), since the players() method does not exist on collections.
$game = Games::find($game);
If you pass a single id to find, it will return a Game model or null. But if you pass an array of ids (even if it's an array of length 1) or a Model (for some reason), it will return a Collection or null.
In your tinker session, try this and you'll have the same error thrown.
$game = Games::find(1);
$game = Games::find($game);
// or
$game = Games::find([1]);
$players = $game->players()->get();
I am trying to serialize Foreign keys inline with Django rest_framework. Foreign keys are used to link lookup tables as per a normal DB normalisation setup.
An example of my model with the lookup:
class OrderStatus(models.Model):
StatusId = models.PositiveSmallIntegerField(primary_key=True)
StatusDescription = models.CharField(max_length=50)
class Order(models.Model):
OrderId = models.AutoField(primary_key=True)
OrderDate = models.DateTimeField(auto_now_add=True)
Status = models.ForeignKey(OrderStatus, on_delete=models.CASCADE)
My serializers:
class OrderStatusSerializer(serializers.ModelSerializer):
class Meta:
model = OrderStatus
fields = ['StatusId', 'StatusDescription']
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ('OrderId', 'OrderDate', 'Status')
What I obtain when I call the REST API is the following:
{
"type": "Order",
"id": "1",
"attributes": {
"OrderId": 1,
"OrderDate": "2020-05-19T08:23:54"
},
"relationships": {
"Status": {
"data": {
"type": "OrderStatus",
"id": "1"
}
}
}
}
I would like to have the Status inline in the "attributes", either as a simple id or even as a JSON object with the two values inline. Both are good options, as long as it's not in that "relationships" field.
I tried to add the following to OrderSerializer:
Status = serializers.PrimaryKeyRelatedField(queryset=OrderStatus.objects.all())
No difference.
I tried the following:
Status = OrderStatusSerializer(many=False)
No difference.
I tried all the other options in
https://github.com/encode/django-rest-framework/blob/master/docs/api-guide/relations.md
including the SlugField to include the description instead that the ID, with no result.
It seems that what I change has no effect on the serialization.
As per my own comment, the issue was caused by rest_framework_json_api.renderers.JSONRenderer.
By switching it back to rest_framework.renderers.JSONRenderer the expected documented behaviour has been re-established.
I want to dynamically expand records because the entrys i get are not fixed.
This is working but it's fixed and i have to say which elements should be expanded.
let
Quelle = Sage.Contents(),
records = Quelle{[Name="Kontakte"]}[Data],
#"SelectItems" = Table.SelectColumns(records,{"$items"}),
#"$items1" = #"SelectItems"{0}[#"$items"],
#"ToTable" = Table.FromList(#"$items1", Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"ExpandedColumn" = Table.ExpandRecordColumn(#"ToTable", "Column1", {"id", "displayed_as", "$path"}, {"Column1.id", "Column1.displayed_as", "Column1.$path"})
in
#"ExpandedColumn"
Webservice Response:
{
"$total":3,"$page":1,"$next":null,"$back":null,"$itemsPerPage":20,
"$items":[
{"id":"1","displayed_as":"Test","$path":"/contacts/Test"},
{"id":"2","displayed_as":"Test2","$path":"/contacts/Test2"},
{"id":"3","displayed_as":"Test3","$path":"/contacts/Test3"}
]}
"$items" are dynamically. It depends on how much informations are behind the contacts.
"id", "displayed_as", "$path"
could also be
"id", "displayed_as", "$path", "city", "zip", "street", "number"
or
"id", "displayed_as", "$path", "city", "zip", "street", "number", "phone", "mobile"
You just need to add two variables and edit the expand line:
SelectAllColumns = Table.ColumnNames(#"$items1"), //Create a list with the columns names
SelectAllColumns2 = List.Transform(SelectAllColumns, each "a."&_), //Create a second list with columns names changed like a.columnname
#"ExpandedColumn" = Table.ExpandRecordColumn(#"ToTable", "Column1", SelectAllColumns, SelectAllColumns2) //Replace these lists inside your last line
I think the final result will be something like:
let
Quelle = Sage.Contents(),
records = Quelle{[Name="Kontakte"]}[Data],
#"SelectItems" = Table.SelectColumns(records,{"$items"}),
#"$items1" = #"SelectItems"{0}[#"$items"],
SelectAllColumns = Table.ColumnNames(#"$items1"),
SelectAllColumns2 = List.Transform(SelectAllColumns, each "a."&_),
#"ToTable" = Table.FromList(#"$items1", Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"ExpandedColumn" = Table.ExpandRecordColumn(#"ToTable", "Column1", SelectAllColumns, SelectAllColumns2)
in
#"ExpandedColumn"
Assuming that the previous step in M was named Removed Other Columns, and that the column to expand is named Data, then I replace the static line of #"Expanded Data" with the following code:
#"Expanded Data" =Table.ExpandTableColumn(#"Removed Other Columns", "Data", List.Union(List.Transform(#"Removed Other Columns"[Data], each Table.ColumnNames(_))))
It dynamically adapt to any column names.
Why does firstOrFail() cause the results of this eloquent query to change?
>>> Organization::find('300048');
=> Models\Organization {#889
id: 300048,
token: "redacted",
name: "DAYJK4EGPE",
domain: null,
created_at: "2017-05-19 17:42:55",
updated_at: "2017-05-19 17:42:56",
stripe_customer_id: "redacted",
referral_snippet: null,
primary_business: null,
}
>>> Organization::find('300048')->firstOrFail();
=> Models\Organization {#897
id: 300033,
token: "redacted",
name: "123456",
domain: "google.com",
created_at: "2017-05-17 13:24:23",
updated_at: "2017-05-24 15:50:25",
stripe_customer_id: "redacted",
referral_snippet: null,
primary_business: null,
}
>>>
The model with id 300033 is the first in my database, but I expected it to still return the organization with id 300048, since that was the only result in the collection firstOrFail() is being called on.
You've figured it out yourself, but essentially firstOrFail is going to grab the first record when you use a where, if you don't use a where clause it will just get the first record in the DB.
As you've figured out, you need findOrFail in order to find the first record with that ID, or fail.
You should use use Organization::findOrFail('300048');.
See the Laravel docs for more information on throwing exceptions.
$city = City::with('station')->where('name',$town)->first();
$townID = 1;
$townComments = TownComment::where('town_id',$townID)->get();
$city->town_comments = $townComments;
When I do this, the result for the town_comments only shows boolean for the timestamps, incrementing and exists.
What am I doing wrong here?
here is how it looks like:
{
id: "1",
name: "tokyo",
similar_stations: {
timestamps: false,
incrementing: true,
exists: true
}
}
It's being displayed like that because $townComments is an object automatically encoded to JSON, I forgot the reference where I read it but this is the solution.
$city->town_comments = $townComments->toArray();