I'm retrieving data from Database like everyone else, but I'm facing a weird issue.
I'm using the slug in my table to retrieve the element's data but but I display the slug it gives me nulland using the famous dd()famous it shows up here is an example :
dd($element);
Result
dd($snippets->toArray());
Result
Table
Schema::create('elements', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('title');
$table->string('slug')->unique();
$table->text('body');
$table->timestamps();
});
Eloquent
$snippets = Snippet::latest()->with('owner')->get();
Snippet Model
protected $primaryKey = 'slug';
public function owner()
{
return $this->belongsTo(User::class, 'user_id');
}
Is there any one who knows what is going on?
The problem was in the Primary Key Type, by default is set to int and have not set incrementing to false which is causing it to 'cast' it by the keyType. The keyType is set to 'int' unless set otherwise. (int)'es2015' == 0
protected $keyType = 'string';
Thanks everyone for help
Related
Using Lumen 5.5.2 and illuminate/database v5.5.17.
I have 3 models set up, where one belongs to the other 2. So Quote, has an area, and a depot.
The relationship with the depot works as expected, the area returns null.
for example
$quoteModel = new Quote();
$quote = $quoteModel
->with('area')
->with('depot')
->where('id', '=', $id)
->first();
echo 'depot id : ' , $quote->depot->id , "<br>\n";
echo 'area id : ' , $quote->area->id , "<br>\n";
The depot id will be echoed, the area will cause an error because it is not an object.
Passing the models names as an array ->with(['area', 'depot']), or just requesting area (either method) does not fix it.
Quote.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Quote extends EloquentModel {
protected $table = 'quotes';
public function area() {
return $this->belongsTo('\App\Models\Area', 'area_id', 'id');
}
public function depot() {
return $this->belongsTo('\App\Models\Depot', 'depot_id', 'id');
}
}
Area.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Area extends EloquentModel {
protected $table = 'areas';
public $timestamps = false;
public $incrementing = false;
public function quotes() {
return $this->hasMany('\App\Models\Quote', 'area_id', 'id');
}
}
Depot.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Depot extends EloquentModel {
protected $table = 'depots';
public $timestamps = false;
public $incrementing = false;
public function quotes() {
return $this->hasMany('\App\Models\Quote', 'depot_id', 'id');
}
}
If I create a parse error in Area.php the script will fail, proving it is being included.
I have a listener set up so I can log the queries, and they show up just fine.
select * from `quotes` where `id` = 99192 limit 1
select * from `areas` where `areas`.`id` in (072)
select * from `depots` where `depots`.`id` in (07)
If I run the area query manually it returns the row I expect.
I tried changing the name of the area relationship, and it doesn't help.
So the missing piece of the puzzle, was that this project is setup up against a legacy database as part of updating an existing web app.
Turns out that there was some datatype inconsistency; I found this out when I could successfully link another model to area with no issues. The field for the area_id is normally a zero filled int, but for some reason on the quotes table it was a char; so the data looked correct when browsing in adminer, and worked when copied and pasted, but did not match up somewhere in Eloquents internals.
Changing the datatype on the table fixes the issue.
I'm new to Laravel-Mongodb, trying to get result by parameter but it's not working
Model:
use Jenssegers\Mongodb\Model as Eloquent;
class Customer extends Eloquent {
protected $connection = 'mongodb';
protected $collection = 'Customer';
}
Controller:
class AdminController extends Controller
{
public function index() {
return Customer::all();
}
public function show($id) {
return Customer::find($id);
}
}
It's alright for index() but it will return empty for show($id), it will work if using:
return Customer::find(1);
I'm not sure why it's not working with parameter, am I missing something?
You need to add one protected variable in your model like below
protected $primaryKey = “customerId”
You can add your own primary key to this variable but if you won’t add this line in model, model will by default take _id as your primary key and _id is autogenerated mongodb’s unique id.
Thats the reason why you are not able to get record by id.
1 is not a valid ObjectId. Try to find a valid ID with a tool like Robomongo or just list your customers with your index method to find out what the IDs are.
The query should look more like this:
return Customer::find("507f1f77bcf86cd799439011");
You can read more about MongoDBs ObjectId here:
https://docs.mongodb.org/manual/reference/object-id/
I am five days into Laravel and after hours of watching Jeffrey Way I decided to delve into building an app to learn.
I am stuck at the point of working with tables in a hasManyThrough layout and identifying the columns that are the linkage between the tables. Eloquent is trying to use a column called 'id" as primary key that it cannot find. In my tables I am using the naming convention tablename_id like below. In my class function, I nominate the columns to use, but it fails with the error:
QueryException in Connection.php line 620:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'cable_installations.id' in 'on clause' (SQL: select `cable_specifications`.*, `cable_installations`.`cable_specifications_id` from `cable_specifications` inner join `cable_installations` on `cable_installations`.`id` = `cable_specifications`.`cable_installations_id` where `cable_installations`.`cable_specifications_id` is null)
I am trying to retrieve:
A distinct list of cable specifications that are allowed with a selected cable_installation_method
Thanks!
TABLE 1: cable_specifications
cable_specifications_id (REPEATS)
other_columns...
TABLE 2: cable_installation_methods
cable_installation_methods_id (UNIQUE)
other_columns...
TABLE 3: cable_installations (PIVOT)
cable_specifications_id (REPEATS)
cable_installation_methods_id (REPEATS)
My classes are:
use Illuminate\Database\Eloquent\Model as Eloquent;
class CableInstallationMethod extends Eloquent {
protected $table = 'cable_installation_methods';
protected $fillable = [];
public function CableInstallation()
{
return $this->hasMany('CableInstallation');
}
public function CableSpecByInstall()
{
return $this->hasManyThrough('App\CableSpecification', 'App\CableInstallation', 'cable_specifications_id', 'cable_installations_id');
}
}
In my controller, I call this function per below:
public function VoltageDropLoad()
{
$InstallationMethods = CableInstallationMethod::all();
$CableSelected = CableInstallationMethod::where("cable_installation_methods_id", 1)->first();
$CableTypes = $CableSelected->CableSpecByInstall()distinct()->get()->toJson();
return view('pages.voltcalc', compact('InstallationMethods', 'CableTypes', 'CableTypes'));
}
Based on your CableInstallationMethod class, you may have missed defining the primary key field for your models:
use Illuminate\Database\Eloquent\Model as Eloquent;
class CableInstallationMethod extends Eloquent {
protected $table = 'cable_installation_methods';
/* Need to define $primaryKey column here, normally defaults to 'id' */
protected $primaryKey = 'cable_installation_methods_id';
protected $fillable = [];
public function CableInstallation()
{
return $this->hasMany('CableInstallation');
}
public function CableSpecByInstall()
{
return $this->hasManyThrough('App\CableSpecification', 'App\CableInstallation', 'cable_specifications_id', 'cable_installations_id');
}
}
With the primary key set you can also take advantage of using Model::find($id) instead of using Model:where(...)->first()
public function VoltageDropLoad()
{
$InstallationMethods = CableInstallationMethod::all();
$CableSelected = CableInstallationMethod::find(1);
$CableTypes = $CableSelected->CableSpecByInstall()->distinct()->get()->toJson();
return view('pages.voltcalc', compact('InstallationMethods', 'CableTypes', 'CableTypes'));
}
I am using Yii together with PostgreSQL and PostGIS in my application. I have a model "User" with a field "Location". The content of the Location-field makes no sense what so ever to a human, but Postgres can convert the value of the Location-field and turn it into Longitude and Latitude using the ST_asText-method. I have created dummy fields in my model for longitude and latitude. When i save my model, i use the beforeSave and afterSave methods to set location to it's right value.
My problem now is that i want the latitude and longitude dummy fields to be populated upon model creation (with existing objects in the db). I was thinking that there might be something like beforeSelect and afterSelect that i can use to append the query with an extra calculated column, and therefore be able to process the values returned from that extra column after the query has been ran.
Is this possible somehow?
I was able to solve this pretty easy. I was looking for a beforeSelect and afterSelect method in the CActiveRecord class when i should have been looking for beforeFind and afterFind.
Here's how i did it. Any improvement suggestion are welcome :)
public function beforeFind(){
$criteria = new CDbCriteria;
$criteria->select = "*,ST_asText(location) as location";
$this->dbCriteria->mergeWith($criteria);
return parent::beforeFind();
}
public function afterFind(){
$location = str_replace('POINT(','',$this->location);
$location = str_replace(')','',$location);
$location = explode(" ", $location);
$this->lon = $location[0];
$this->lat = $location[1];
return parent::afterFind();
}
I met this problem with Yii2 and here is how I solved it.
Override find() method of AR and define your own ActiveQuery class:
public static function find()
{
$query = new MyActiveQueryClass(get_called_class());
return $query->select('*, ST_AsGeoJSON(location) AS location');
}
In afterFind() you will have geo-json and with that you can get lat/lng:
public function afterFind()
{
parent::afterFind();
$geoJson = json_decode($this->location, true);
$this->lat = $geoJson['coordinates'][0];
$this->lng = $geoJson['coordinates'][1];
}
That is it for Yii2. Remember to convert your lat/lng to correct object before saving. Mine was geography column. Here is a bonus:
public function beforeSave($insert)
{
//create field as expression
if(!empty($this->lat) && !empty($this->lng))
$this->location = new \yii\db\Expression("'POINT({$this->lat} {$this->lng})'");
return parent::beforeSave($insert);
}
when i send a form with a blank field i get an error SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'image' cannot be null. the only way to fix it that i found is to make a default value in the entity file:
* #ORM\Column(type="string", length=100)
*/
protected $image="";
and change the setter like this:
public function setImage($image){
if(!isset($image)) {
//its really empty but it works only in this way
}
else {
$this->image = $image;
}
I think that it is very starnge...
Is there any explanation for this? And is there another way to do it?
}
If the field image is not required, you can set it as nullable so Doctrine will know that and will set the column as being nullable.
This way, constraint won't be violated since the field can be null. To make a field nullable with Doctrine annotation, just add nullable = true in the ORM\Column definition like this:
#ORM\Column(type="string", length=100, nullable=true)
By default, all columns are nullable=false so they will throw a constaint validation exception when trying to persist a null value in it.
Regards,
Matt
The why is partially answered here:
Symfony2 forms interpret blank strings as nulls
This code gets around it because when Symfony sets $image to null and calls $entity->setImage(null), this code will not change the $image member.
public function setImage($image){
if(!isset($image)) {
// $image is null, symfony was trying to set $this->image to null, prevent it
} else {
$this->image = $image;
}
}
This is more explicit (and who wants that weird empty statement anyway?). It expresses your intent, that $this->image cannot be null (which matches the database definition if you don't make it nullable)
public function setImage($image){
if(isset($image)) {
// $image not null, go ahead and use it
$this->image = $image;
}
}
Either way, you need to initialize $this->image otherwise it will default to null.