Cannot refresh row as parent is missing. Zend Framework - zend-framework

i am getting the error "Cannot refresh row as parent is missing" when I try to save. Here is my code
abstract class Webapp_Model_Resource_Db_Table_Abstract
extends Zend_Db_Table_Abstract
{
/**
* Save a row to the database
*
*
* #param array $info The data to insert/update
* #param Zend_DB_Table_Row $row Optional The row to use
* #return mixed The primary key
*/
public function saveRow($info, $row = null)
{
if (null === $row) {
$row = $this->createRow();
}
$columns = $this->info('cols');
foreach ($columns as $column) {
if (array_key_exists($column, $info)) {
$row->$column = $info[$column];
}
}
return $row->save();
}
}
when I call the saveRow() method, I pass in the $_POST values ($form->getValues())
I have reused this class with my other modules in the same application but now I am getting this error and I am not sure why. My table is pretty straight forward:
CREATE TABLE `news` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`headline` varchar(100) DEFAULT NULL,
`snippet` varchar(500) DEFAULT NULL,
`full_text` text,
`author` varchar(100) DEFAULT NULL,
`publish_from` date DEFAULT NULL COMMENT 'Publish date',
`publish_to` date DEFAULT NULL COMMENT 'Take it down or mark as draft after this date',
`datecreated` timestamp NULL DEFAULT NULL COMMENT 'First created on',
`revised` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp for the last time it was revised',
`draft` tinyint(1) DEFAULT '0' COMMENT 'Should not be published',
`departments_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=214 DEFAULT CHARSET=utf8 COMMENT='Stores news articles';
Anyone know what I am doing wrong?
::::::::::::::ADDTION:::::::::::::
public function saveNews($post,$defaults = array())
{
//get the form
$form = $this->getForm('article' . ucfirst($validator));
//validate
if(!$form->isValid($post)) {
return false;
}
//get fitered values
$data = $form->getValues();
//apply defaults
foreach($defaults as $col => $value) {
$data[$col] = $value;
}
//get the article if it exists
$article = array_key_exists('id', $data) ?
$this->getNewsById($data['id']) : null;
return $this->saveRow($data, $article);
}

When you pass an empty value for the primary key, Zend seems to return this value instead of the inserted auto-increment value - even though a new row is created properly with an auto-increment value, the inserted value will not be returned.
Maybe your problem is related to this. If so, try unsetting the id field prior to saving.

You have to tell DbTable that there is a Auto Incrementing Primary Key by setting $_sequence either to true or the Sequence Name.
15.5.4.1. Using a Table with an Auto-incrementing Key

Check your $info array. Probably you have some empty value for your primary key there.
So array_key_exists($column, $info) returns true and you assign an empty primary key to your row. And this causes the error as the row with this key does not exist.
try
if (array_key_exists($column, $info) and $column != 'YOUR_PRIMARY_KEY_NAME')
{
$row->$column = $info[$column];
}

In my case the problem was missing AUTO_INCREMENT.

Could you post the function:
$this->getNewsById($id)
There is your problem...

Related

Selecting Postgres UUID's on Laravel

I have a table on Postgres that auto generates UUIDs, when I dd Customer::all(); on Laravel I get an array with "cs_id" => "d0402be5-e1ba-4cb2-a80c-5340b406e2c3" which is fine. When I loop or select one record with the only the cs_id the data it retuns 0,2,5 for the three records currently on the table which is incorrect data.
EDIT:
CREATE TABLE customers
(
cs_id character varying(255) NOT NULL DEFAULT gen_random_uuid(),
CONSTRAINT cs_customers_pkey PRIMARY KEY (cs_id),
}
On laravel
$customerData = Customer::where('cs_id','d0402be5-e1ba-4cb2-a80c-5340b406e2c3')->first();
dd($customerData['cs_id']);
For some reason Eloquent messes up there.
just add a getter and use it whenever you need the cs_id
public function getGuid()
{
return $this->attributes['cs_id'];
}
To use uuids auto-generated by the database, define your model as follows:
class Customer extends Model
{
// rename the id column (optional)
protected $primaryKey = 'cs_id';
// tell Eloquent that your id is not an integer
protected $keyType = 'string';
// do NOT set $incrementing to false
}
Then you can use all Eloquent's methods as you would with classic ids:
$customerData = Customer::findOrFail('d0402be5-e1ba-4cb2-a80c-5340b406e2c3');
Use Customer::findOrFail('d0402be5-e1ba-4cb2-a80c-5340b406e2c3');
to get the record matching that pk.
I'm assuming on top you have use App\Customer;

Eloquent default attribute values: $attributes or DB column default value?

What's the proper way to implement default values for Eloquent models?
I've configured my database tables using Laravel's migrations. Some columns have default values specified. When using these tables in conjunction with Eloquent models, different things happen depending on the selected database driver:
In MySQL, when creating a new model and saving it, a DB row is inserted having the column's default value for every attribute that was not explicitly specified. This is what I would like to happen.
In Postgres and SQLite however, this is not the case. A PDOException is thrown:
[PDOException]
SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column
"some_column" violates not-null constraint
DETAIL: Failing row contains (1, 2, 3, 4, 5, 6, null, null, null, null, null, null, 7, 8, null, 9, null, null, 10, 11, 12, null).
It is clear to me that the column is not nullable and that null values are not accepted. I would expect however that the default value was inserted instead of an error being raised.
I would suggest that you create your own parent model that extends Eloquent directly, and have all of your models extend this custom parent.
In the custom parent, override the performInsert() method to remove null values just before inserting. Be sure to copy the entire method from the Eloquent source code so you don't lose any important steps in the process:
class MyModelParent extends Illuminate\Database\Eloquent\Model
{
/**
* Perform a model insert operation.
*
* #param \Illuminate\Database\Eloquent\Builder $query
* #return bool
*/
protected function performInsert(Builder $query)
{
if ($this->fireModelEvent('creating') === false) {
return false;
}
... // Be sure to copy all of it!
// This is the change you'll make. Before, it was just:
// $attributes = $this->attributes;
$attributes = array_filter($this->attributes, function($val){
return $val !== null;
});
... // Be sure to copy all of it!
return true;
}
}
performUpdate() should handle this issue fine, since it uses getDirty() to get the list of fields instead of accessing the property directly.
And while you're at it, you should consider submitting a patch to Laravel that would make the core Postgres-safe.
SQL NOT NULL Constraint
The NOT NULL constraint enforces a column to NOT accept NULL values.
you are adding a null value on NOT NULL column
it seems
http://www.w3schools.com/sql/sql_notnull.asp

Where relation value higher than entity value with Eloquent

I have two entities; Part and PartStock. There is a one-to-one relationship between them:
Part model:
public function partStock()
{
return $this->hasOne('App\PartStock');
}
PartStock model:
public function part()
{
return $this->belongsTo('App\Part');
}
How can I write a global scope for Part that has a where filter for values on the PartStock relation and Part entity itself?
So basically:
$query->where('PartStock.count', '>', 'Part.reorder');
parts table:
`id` int(10)
`category_id` int(10)
`description` varchar(255)
`value` varchar(255)
`reorder` int(10)
part_stock table:
`id` int(10)
`part_id` int(10)
`count` int(11)
I can not wrap my head around if it is even possible:
// here I have part reorder, but not the partstock count
$query->where(???, '>', 'reorder');
// here I have partstock count, but not the part reorder
$query->whereHas('partStock', function($q) {
$q->where('count', '>', ???);
});
Can I in a way combine this two scopes?
See Eloquent: Querying Relations.
Part::whereHas('PartStock', function ($query) {
$query->whereRaw('PartStock.count > Part.reorder');
})->get();

Match Dates and Count in Entity Framework

I have two tables:
create table dbo.Dates (
Id int not null
constraint Dates_Id_PK primary key clustered (Id),
[DateValue] date not null
}
create table dbo.Posts (
Id int identity not null
constraint Posts_Id_PK primary key clustered (Id),
Created datetime not null,
Title nvarchar (200) not null
)
For these tables I have Date and Post entities.
How can I get a table that has the column DateValue from Dates and the number of Posts with that date.
I need to match the datetime Created value to the date DateValue.
Thank you,
Miguel
I assume your Posts have dates with times, so you'll have to truncate them to the date part (as in the Date property of a DateTime):
from d in context.Dates
select new {
Date = d.DateValue,
NrOfPosts = (from p in context.Posts
where EntityFunctions.TruncateTime(t.Created) == d.DateValue
select p).Count()
}
you can use anonymous types. try the following snippet.
DateTime dateToMatch = GetDateToMatch();
using(YourEntities context = new YourEntities())
{
var result = context.Dates.Where(d => d.DateValue == dateToMatch)
.Select(d => new { Date = d.DateValue, PostCount = d.Posts.Count() });
}

How can I receive bytea data from PostgreSQL through Zend_Db_Select?

I wrote a website with Zend Framework + Postgres. In PostgreSQL there is this table:
create table images(
id serial,
title TEXT DEFAULT '',
thumbnail bytea NOT NULL,
original bytea NOT NULL,
PRIMARY KEY(id)
);
Where I'm planning to store image data.
But when I try to receive anything from the table (select thumbnail from images where id = $id):
$table = $mapper->getDbTable();
$select = $table->select();
$select->from($table,array('thumbnail'));
$select->where('id = ?',$id);
$res = $table->fetchRow($select);
die(print_r($res['thumbnail']));
I receive something like:
Resource id #12_
but not the containing data.
How could I (using Zend_Db_Select) receive this data, but not a Resource id #129?
Sorry for my bad english ...
if the problem remains, replace this line:
die(print_r($res['thumbnail']));
by this:
die(fpassthru($res['thumbnail']))
$stream = $res['thumbnail'];
#unlink($pathFile);
touch($pathFile);
while (($buffer = (fgets($stream, 8192))) !== false) {
file_put_contents($pathFile, $buffer, FILE_APPEND);
}