I was getting the relationship as in laravel 5.3 and was working fine:
//execute the relation of the given model
$data = $model->{$info["relation"]}();
// get the type of the relation
$class = get_class($data);
$dataType = explode("\\", $class);
$relationType = end($dataType);
$options["columns"][$key]["relationType"] = $relationType;
// if its a simple belongs-to statement
if($relationType == "BelongsTo") {
// get all belongs-to query info
$otherTable = $data->getRelated()->getTable();
$foreignKey = $data->getQualifiedForeignKey();
$otherKey = $data->getOtherKey();
// manually join using it
$retrievedRecords->leftJoin($otherTable . ' as ' . $info["relation"], $info["relation"] . '.' . $otherKey, '=', $foreignKey);
} else if($relationType == "HasMany" || $relationType == "HasOne") {
// get all has-many query info
$otherTable = $data->getRelated()->getTable();
$foreignKey = $data->getPlainForeignKey();
$parentKey = $data->getQualifiedParentKeyName();
// manually join using it
$retrievedRecords->leftJoin($otherTable . ' as ' . $info["relation"], $info["relation"] . '.' . $foreignKey, '=', $parentKey);
}
Now i downloaded fresh laravel 5.4 and it gives me error :
Call to undefined method Illuminate\Database\Query\Builder::getOtherKey()
As the getOtherKey() exists in the above code in if() section.
Is there any alternative for that ?
The getOtherKey method has been renamed to getOwnerKey. So you can get the owner key by saying:
$ownerKey = $data->getOwnerKey();
Related
I have this code in controller to update the data from database :
public function update(Request $request, $id)
{
$anodizing = Anodizing::find($id);
$anodizing->date= $request->date;
$anodizing->number= $request->number;
$anodizing->item_total = $request->item_total;
$anodizing->desc= $request->desc;
if ($request->hasFile('picture')) {
$anodizing_image = public_path("uploads/reports/anodizing/{$anodizing->picture}");
if (File::exists($anodizing_image)) {
File::delete($anodizing_image);
};
$file = $request->file('picture');
$extension = $file->getClientOriginalExtension();
$filename = $request->number. '-' . date('YmdHms') . '.' . $extension;
$file->move('uploads/reports/anodizing', $filename);
$anodizing->picture= $filename;
}
$anodizing->save();
$id = $anodizing->id;
foreach ($request->addmore as $key => $value) {
$anodizingdetail = AnodizingDetail::find($value['id']);
$anodizingdetail->aluminium_id= $value['name'];
$anodizingdetail->qty = $value['qty'];
$anodizingdetail->weight= $value['weight'];
$anodizingdetail->save();
}
Basically this update method works perfectly to update or edit existing data, but the problem is, what to do if I want to edit and then insert a new row in the detail form ?
I'm aware of updateorCreate method in laravel, is that the right method ? How to use that ? or I need to use something else ?
as you said, instead of AnodizingDetail::find use findOrNew
docs: https://laravel.com/docs/master/eloquent-relationships#the-create-method
SELECT name
FROM tx_snippethighlightsyntax_domain_model_snippets
WHERE (MATCH(name, description, code, comment) AGAINST ('css'));
This query works in phpMyAdmin with MariaDB. Now my "problem" is to adapt this in TYPO3 with QueryBuilder. I don't see any MATCH or AGAINST operator.
So far, my function start with this:
private $tx = 'tx_snippethighlightsyntax_domain_model_snippets';
public function ftsSearch()
{
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
$ftsQueryBuilder = $connectionPool->getQueryBuilderForTable($this->tx);
$fts = $ftsQueryBuilder
->select($this->tx . '.name')
->from($this->tx)
->where($ftsQueryBuilder->expr()->eq(
MAGIC HAPPENS HERE ?
)
->execute()
->fetchAll();
return $fts;
}
The extension Indexed Search in the TYPO3 core uses MATCH and AGAINST in queries.
The following code taken from IndexSearchRepository should help you building up your query
$searchBoolean = '';
if ($searchData['searchBoolean']) {
$searchBoolean = ' IN BOOLEAN MODE';
}
$queryBuilder->andWhere(
'MATCH (' . $queryBuilder->quoteIdentifier($searchData['fulltextIndex']) . ')'
. ' AGAINST (' . $queryBuilder->createNamedParameter($searchData['searchString'])
. $searchBoolean
. ')'
);
private $tx = 'tx_snippethighlightsyntax_domain_model_snippets';
public function ftsSearch()
{
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
$ftsQueryBuilder = $connectionPool->getQueryBuilderForTable($this->tx);
$fts = $ftsQueryBuilder
->select($this->tx . '.name')
->from($this->tx)
->where('MATCH('
. $this->tx .'.name,'
. $this->tx .'.description,'
. $this->tx .'.code,'
. $this->tx .'.comment)'
. ' AGAINST(' . $ftsQueryBuilder->createNamedParameter('put_search_here')
. ')')
->execute()
->fetchAll();
return $fts;
}
This one works for me. Thank you !
I've searched throughout the internet and mostly answers apply to ZF1.
I'd like to join a subselect query into another select using select objects. It's crucial for me to get whole Select object at the end of multiple such joins.
Code looks like this:
$subSelect = new Select();
$subSelect->from(array('TABLE' => 'SOME_TABLE'));
$subSelect->columns(array('ID'));
$select = new Select();
$select->from(array('SEC_TABLE' => 'SOME_ANOTHER_TABLE'));
$select->join(
array('SUB' => $subSelect),
'SUB.ID = SEC_TABLE.ID',
array(),
$select::JOIN_LEFT
);
It was possible in ZF1 using class Zend_Db_Expr, is there any nice way to this in ZF2?
This is answered here
In ZF2 you can combine two Select object instance using its Select::combine() method.
$select->combine($subSelect);
I tried to use Select::combine() but it is functionality used for things such as UNION or INTERSECT or MINUS - keywords placed between select statements. I need pure JOIN and the problem is that Oracle Adapter in ZF2 overwrites standard approach to processJoins method.
Here is the code from Zend/Db/Sql/Select
protected function processJoins(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
{
if (!$this->joins) {
return null;
}
// process joins
$joinSpecArgArray = array();
foreach ($this->joins as $j => $join) {
$joinSpecArgArray[$j] = array();
$joinName = null;
$joinAs = null;
// type
$joinSpecArgArray[$j][] = strtoupper($join['type']);
// table name
if (is_array($join['name'])) {
$joinName = current($join['name']);
$joinAs = $platform->quoteIdentifier(key($join['name']));
} else {
$joinName = $join['name'];
}
if ($joinName instanceof ExpressionInterface) {
$joinName = $joinName->getExpression();
} elseif ($joinName instanceof TableIdentifier) {
$joinName = $joinName->getTableAndSchema();
$joinName = ($joinName[1] ? $platform->quoteIdentifier($joinName[1]) . $platform->getIdentifierSeparator() : '') . $platform->quoteIdentifier($joinName[0]);
} else {
if ($joinName instanceof Select) {
$joinName = '(' . $this->processSubSelect($joinName, $platform, $driver, $parameterContainer) . ')';
} else {
$joinName = $platform->quoteIdentifier($joinName);
}
}
$joinSpecArgArray[$j][] = (isset($joinAs)) ? $joinName . ' AS ' . $joinAs : $joinName;
// on expression
// note: for Expression objects, pass them to processExpression with a prefix specific to each join (used for named parameters)
$joinSpecArgArray[$j][] = ($join['on'] instanceof ExpressionInterface)
? $this->processExpression($join['on'], $platform, $driver, $this->processInfo['paramPrefix'] . 'join' . ($j+1) . 'part')
: $platform->quoteIdentifierInFragment($join['on'], array('=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>')); // on
if ($joinSpecArgArray[$j][2] instanceof StatementContainerInterface) {
if ($parameterContainer) {
$parameterContainer->merge($joinSpecArgArray[$j][2]->getParameterContainer());
}
$joinSpecArgArray[$j][2] = $joinSpecArgArray[$j][2]->getSql();
}
}
return array($joinSpecArgArray);
}
and here from Zend/Db/Platform/Oracle/Select/SelectDecorator which extends standard Select class and is used for Oracle database:
protected function processJoins(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
{
if (!$this->joins) {
return null;
}
// process joins
$joinSpecArgArray = array();
foreach ($this->joins as $j => $join) {
$joinSpecArgArray[$j] = array();
// type
$joinSpecArgArray[$j][] = strtoupper($join['type']);
// table name
$joinSpecArgArray[$j][] = (is_array($join['name']))
? $platform->quoteIdentifier(current($join['name'])) . ' ' . $platform->quoteIdentifier(key($join['name']))
: $platform->quoteIdentifier($join['name']);
// on expression
$joinSpecArgArray[$j][] = ($join['on'] instanceof ExpressionInterface)
? $this->processExpression($join['on'], $platform, $driver, $this->processInfo['paramPrefix'] . 'join')
: $platform->quoteIdentifierInFragment($join['on'], array('=', 'AND', 'OR', '(', ')', 'BETWEEN')); // on
if ($joinSpecArgArray[$j][2] instanceof StatementContainerInterface) {
if ($parameterContainer) {
$parameterContainer->merge($joinSpecArgArray[$j][2]->getParameterContainer());
}
$joinSpecArgArray[$j][2] = $joinSpecArgArray[$j][2]->getSql();
}
}
return array($joinSpecArgArray);
}
As standard Select class allows you to join another Select ( line : if ($joinName instanceof Select) {), Oracle extended version doesn't.
Is it just a bug in Zend?
Is there any way around it?
It's not in any way connected to Oracle specification, why is it so then?
public function test_passing_string() {
$this - > load - > model(array('registration/Registration_model', 'Jawaban_lab_model'));
$registration = new Registration_model();
$jawaban_lab = new Jawaban_lab_model();
$id = "kuda4";
$jawaban_lab - > load($id); //load jawaban_lab from id
$manualy_written_registration_number = "REG/FM/130102-0001";
echo "registration number from jawaban_lab->registration_number : ".$jawaban_lab - > registration_number
.
"<br> registration number from manualy_written_registration_number : ".$manualy_written_registration_number;
//$registration->load($jawaban_lab->registration_number);
$registration - > load($manualy_written_registration_number);
echo "<br> patient id : ".json_encode($registration - > PatientID);
}
Before go to the question, I will explain my code.
On test_passing_string() function, I call 2 model, and create object for each model there are $registration and $jawaban_lab.
To load data from model I create a load() function. load() has two parameters: column_value and column_name. The default value for column_name is that model's Primary Key.
BUT
The problem comes from
$registration->load($jawaban_lab->registration_number);
I can't retrieve any $registration object data, then I test it by passing the value manually by write this:
$manualy_written_registration_number = "REG/FM/130102-0001";
$registration - > load($manualy_written_registration_number);
And the result appear, doesn't that mean my load() function is fine?
Then I check value inside $jawaban_lab->registration_number by echoing it, surprisingly it display same value as my $manualy_written_registration_number variable.
This is screenshoot in my browser when I run test_passing_string() function:
Using $manualy_written_registration_number value
Using $jawaban_lab->registration_number value
Why can't I use the value from
$jawaban_lab->registration_number even though it has the same value as
my manually writen registraiton number?
public function load($column_value, $column_name = NULL) {
$query = NULL;
if ($column_name != NULL) {
// using custom column.
$query = $this->dbs->get_where($this::DB_TABLE, array(
$column_name => $column_value
));
} else {
// using column primary key .
$query = $this->dbs->get_where($this::DB_TABLE, array(
$this::DB_TABLE_PK => $column_value
));
}
if ($query->row()) {
$this->populate($query->row());
}
}
I use multiple database using CodeIgniter 3, registration_model from SQL server and jawaban_lab from MySQL, jawaban lab have column registration_number to store registration_model primary key
var_dump
First of all thanks to rlanvin and Nirajan N Raju
from rlanvin's comment, i find out the problem is come from codeigniter's query helper, because when i enable codeigniter profiling sql server query return "SELECT CASE WHEN (##OPTIONS | 256) = ##OPTIONS THEN 1 ELSE 0 END AS qi"
so i think codeigniter might be cannot generate query so i create the query manually
i change
public function load($column_value, $column_name = NULL) {
$query = NULL;
if ($column_name != NULL) {
// using custom column.
$query = $this->dbs->get_where($this::DB_TABLE, array(
$column_name => $column_value
));
} else {
// using column primary key .
$query = $this->dbs->get_where($this::DB_TABLE, array(
$this::DB_TABLE_PK => $column_value
));
}
if ($query->row()) {
$this->populate($query->row());
}
}
to this
public function load($column_value, $column_name = NULL) {
$query = NULL;
if ($column_name != NULL) {
$query = $this->dbs->query("SELECT * FROM " . $this::DB_TABLE . " WHERE " . $column_name . " LIKE '" . trim($column_value) . "'");
} else {
$query = $this->dbs->query("SELECT * FROM " . $this::DB_TABLE . " WHERE " . $this::DB_TABLE_PK . " LIKE '" . trim($column_value) . "'");
}
if ($query->row()) {
$this->populate($query->row());
}
}
Softdelete behavior works fine on execute delete statement via the entity manager as the following code:
$entity = $this->em->getRepository('Users')->find(7);
$this->em->remove($entity);
$this->em->flush();
but when execute the same functionality via QueryBuilder hard delete will execute on database
$qb = $this->em->createQueryBuilder();
$qb->delete('Users', 'p');
$qb->where($qb->expr()->eq('p.id', ':id'));
$qb->setParameters(array("id" => 7));
$result = $qb->getQuery()->getResult();
How can I allow softdelete in all cases either via entity manager or query builder
If you use DQL then you have to use a Query Hint. This should do the trick:
$query = $qb->getQuery()
$query->setHint(
\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
'Gedmo\SoftDeleteable\Query\TreeWalker\SoftDeleteableWalker'
);
$result = $query->getResult();
Update:
The docs mention that you have to use a Query Hint but don't provide an example so I pulled the usage from their tests.
Docs: https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/softdeleteable.md
Test Usage: https://github.com/l3pp4rd/DoctrineExtensions/blob/master/tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php
my old solution after previous answer by #Ken Hannel is:
Edit:
/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php
Replace walkDeleteClause function as the following:
public function walkDeleteClause(AST\DeleteClause $deleteClause)
{
$class = $this->em->getClassMetadata($deleteClause->abstractSchemaName);
$tableName = $class->getTableName();
$sql = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform);
$this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable);
$this->rootAliases[] = $deleteClause->aliasIdentificationVariable;
//check if SoftDeleteableListener is attached
foreach ($this->em->getEventManager()->getListeners() as $eventName => $listeners) {
foreach ($listeners as $listener) {
if ($listener instanceof \Gedmo\SoftDeleteable\SoftDeleteableListener) {
$date = date('Y-m-d H:i:s');
$sql = 'UPDATE ' . $this->quoteStrategy->getTableName($class, $this->platform) . " SET deletedAt = ' " . $date . " ' ";
}
}
}
return $sql;
}
but really but I think Ken Hannel way is more professional and up to standard.