Eloquent relationship returns null, but a similar one is fine - lumen

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.

Related

Jenssegers Laravel-Mongodb return null if get by parameter

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/

Laravel 5.0 hasManyThrough column not found issue

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'));
}

cakephp and mongodb - relationships

i have a question on mongodb, model cakephp and relationships.
I'd create the following relations:
User -> hasMany -> City
City -> belongsTo -> User
In MongoDB, I have two tables:
users
cities (with key user_id)
In cakephp, I have 2 model:
User.php
class User extends Model {
public $name = 'User';
public $actsAs = array('Containable');
public $hasMany = array ('City');
..
}
and:
City.php
class City extends Model {
public $name = 'City';
public $actsAs = array('Containable');
public $belongsTo = array('User');
..
}
In my controller I use :
$user = $this->User->find('all');
but it doesn't work. In sql dump, cakephp uses a find only on tbl users.
Why? Where I wrong?
I normally place recursive to -1 and containable in app model, so it applies to all models you create unless you override specifically.
class AppModel extends Model {
public $actsAs = array('Containable');
public $recursive = -1;
}
Your relationships are fine, although I usually add className and foreignKey just to be safe and clear. In your controller you should do something like this:
$users = $this->User->find('all', array(
'contain' => array(
'City'
)
));
Recursive will prevent any associated records being included by default, this is good as sometimes you do not need the recursive data and extra data will help slow down your application.
Next adding contain into your find call may seem like a chore but it will be clear and concise what you are querying, any 3rd party developer will understand exactly what you are doing if they know how to use Cake. Hope this helps.

Zend duplicated rows on mysql insert

For some reason, when I do an mysql db insert from Zend, my row is dulpicated. I've tried a direct insert via phpmyadmin and it works perfect, so its not a mysql server problem.
This is the code I use:
<?php
class Model_Team extends Zend_Db_Table_Abstract {
protected $_name = 'team';
public function createUser($data) {
$user = $this->createRow();
$user->name = $data['name'];
$user->title = $data['title'];
$id = $user->save();
return $id;
}
}
?>
Thanks in advance.
EDIT:
I've found that this duplication only occurs when i call the form via AJAX (modal box), although the form post is normal, not an ajax request)
I don't know why your code is double pumping the database on save but it should'nt matter as you're using the Row object and save(). (save() inserts or updates)
You may want to restructure your createUser() function so that it can't create a new row if the row already exists.
<?php
class Model_Team extends Zend_Db_Table_Abstract {
protected $_name = 'team';
public function createUser(array $data) {
$user = $this->createRow();
//test if user has id in the array
if (array_key_exists('id', $data)){
$user->id = $data['id'];
}
$user->name = $data['name'];
$user->title = $data['title'];
$user->save();
//no need to create a new variable to return the user row
return $user;
}
}
This method will create and update a user row.
To help you further I'll need to see the controller code most of my double pumps have happened there.
Instead of using createRow() have you tried using insert()?
/**
* Insert array of data as new row into database
* #param array $data associative array of column => value pairs.
* #return int Primary Key of inserted row
*/
public function createUser($data)
{
return $this->insert($data);
}
Also - could we see the ajax code? It may be that the form is being posted as well?

Using Image Content Objects from tt_content in Extbase

I want to write an Extbase Backend module which needs a list of all Objects generated from tt_content with CType = 'image'.
Now I started defining a simple model
class Tx_Myextension_Domain_Model_Content extends Tx_Extbase_DomainObject_AbstractEntity
{
/**
* #var string
*/
protected $header;
/**
* #return the $header
*/
public function getHeader()
{
return $this->header;
}
/**
* #param string $header
*/
public function setHeader($header)
{
$this->header = $header;
}
}
and a Repository
class Tx_Myextension_Domain_Repository_ContentRepository extends Tx_Extbase_Persistence_Repository
{
public function initializeObject()
{
$querySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$querySettings->setRespectStoragePage(FALSE);
$this->setDefaultQuerySettings($querySettings);
}
}
As far as I know the initializeObject method is a way to get all content elements, no matter which pid they have.
At last I tried to map my Content Class on tt_content:
plugin.tx_myextension {
persistence {
classes {
Tx_Myextension_Domain_Model_Content {
mapping {
tableName = tt_content
recordType = Tx_Myextension_Domain_Model_Content
columns {
header.mapOnProperty = header
}
}
}
}
}
}
module.tx_myextension {
persistence < plugin.tx_myextension.persistence
}
No I want to use the Repo. e.g. countAll. Unfortunately it always returns 0. Looking for the MySQL query discovers the problem:
SELECT COUNT(*)
FROM tt_content
WHERE (tt_content.CType='Tx_Myextension_Domain_Model_Content')
AND tt_content.deleted=0 AND tt_content.hidden=0
AND (tt_content.starttime<=1313073660)
AND (tt_content.endtime=0 OR tt_content.endtime>1313073660)
AND tt_content.sys_language_uid IN (0,-1)
AND tt_content.pid IN (0)
Typo 3 or Extbase or something different added all these where clauses to the query. I just want to get rid of the CType and pid clauses. As I said, I thought that the method used in the Repo leads to ignoring the pid, which is obviously not the case.
Can somebody help me? All I want is an array of Image Content Elements. Thank you in advance.
Late answer: You'll most likely want to call
query->getQuerySettings()
->setRespectEnableFields(FALSE)
->setRespectSysLanguage(FALSE);
for your query. You can disable it for all queries in your repository's initializeObject method:
$querySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$querySettings
->setRespectStoragePage(FALSE)
->setRespectEnableFields(FALSE)
->setRespectSysLanguage(FALSE);
$this->setDefaultQuerySettings($querySettings);
See: TYPO 3 API docs
Try to remove the Node "recordType" from your Persistence Definition.