I've got 2 different databases and need a leftjoin to the second one.
It's on Laravel 8. It's a MariaDB and the sql_erp it's on MSSQL.
Who can help me?
My received fault-message is:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'sql_erp.artikel_stamm' doesn't exist (SQL: select * from `aa_bom` left join `sql_erp`.`ARTIKEL_STAMM` on `bom`.`art_nr` = `Artikel_Stamm`.`ARTNR` where `_x_zu_aa_doc_steps` = 1 order by `pos` asc limit 99)
in my controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Arbeitsanw\aa_doc_steps;
use App\Models\Arbeitsanw\aa_doc_header;
use App\Models\Arbeitsanw\aa_bom;
use App\Models\Arbeitsanw\ERP\Artikel_Stamm;
use Illuminate\Support\Facades\DB;
public function loadstep($id)
{
$aa_doc_steps = aa_doc_steps::find($id);
//Stkl laden
$aa_doc_step_id=$id;
$aa_stkl_artikels = aa_bom::where('_x_zu_aa_doc_steps', '=', $aa_doc_step_id)
->leftJoin('sql_erp.ARTIKEL_STAMM', 'bom.art_nr', '=', 'Artikel_Stamm.ARTNR')
->orderBy('pos', 'asc')
->take(99)
->get();
return view('aa_edit_arbeitsschritt', compact('aa_doc_steps', 'aa_stkl_artikels'));
}
my model
<?php
namespace App\Models\Arbeitsanw\ERP;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Http\Controllers\aa_stkl_form_controller;
class Artikel_Stamm extends Model
{
use HasFactory;
protected $connection = 'sql_erp';
protected $table = 'ARTIKEL_STAMM';
}
You can use the Laravel Eloquent Left join structure as an example
$ c = Customer :: leftJoin ('orders', function ($ join) (
$ join-> on ('customers.id', '=', 'orders.customer_id');
})
-> whereNull ('orders.customer_id')
-> first ();
You can look at this code structure. Also, you need to define $ fillable = ['table_column', 'table_column'] in the Model file.
Related
In CakePHP 2 I could do something like this:
$name = $this->User->field('name', ['email' => 'user#example.com']);
In CakePHP 3 you have to do something like this to achieve the same thing:
$users = TableRegistry::get('Users');
$query = $users->find()
->select('name')
->where(['email' => 'user#example.com']);
$name = $query->isEmpty() ? null : $query->first()->name;
Is there a simpler way to perform these kinds of operations? I'm not very familiar with the new ORM.
Edit: I have added an example of a class which adds this behavior for Cake 3:
https://stackoverflow.com/a/42136955/851885
It's possible to add this functionality to any Table via a custom behavior.
Save as src/Model/Behavior/EnhancedFinderBehavior.php
<?php
namespace App\Model\Behavior;
use Cake\ORM\Behavior;
/**
* EnhancedFinder behavior
*
* Behavior providing additional methods for retrieving data.
*/
class EnhancedFinderBehavior extends Behavior
{
/**
* Retrieve a single field value
*
* #param string $fieldName The name of the table field to retrieve.
* #param array $conditions An array of conditions for the find.
* #return mixed The value of the specified field from the first row of the result set.
*/
public function field($fieldName, array $conditions)
{
$field = $this->_table->getAlias() . '.' . $fieldName;
$query = $this->_table->find()->select($field)->where($conditions);
if ($query->isEmpty()) {
return null;
}
return $query->first()->{$fieldName};
}
}
Note: for CakePHP versions prior to 3.4, change the code to $this->_table->alias(), which was deprecated in favour of getAlias() in later versions.
Usage
Add the behavior to your class:
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
class UsersTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('EnhancedFinder');
}
}
Now you can use the finder like Cake 2:
$name = $this->User->field('name', ['id' => 1]);
This might be simpler than yours
$users = TableRegistry::get('Users');
$name = $users->get(1)->name;
Make sure that when you use the get function, the parameter should be a primary key in the table.
No, there is not in CakePHP 3.x.
If you want that method back implement it either in a behavior or as a finder using a trait and use it with your table objects.
So I have SQLite database using Slick and I want to add and remove tables from it.
Here is what I have now:
Here is the database element class:
class Data(tag: Tag)
extends Table[(Int, String)](tag, "myDB") {
// This is the primary key column:
def id = column[Int]("ID", O.PrimaryKey)
def name = column[String]("NAME")
// Every table needs a * projection with the same type as the table's type parameter
def * : ProvenShape[(Int, String)] = (id, name)
}
I need to be able to create multiple tables using the class above. Something like this:
def addTable(name:String){
db withSession { implicit session =>
val newTable = TableQuery[Data]
newTable.ddl.create
}
}
Problem is that I cant create new table because one already exists with name "myDB". I tried to add a parameter for the name of the Table in the class Data like so:
class Data(tag: Tag,tableName:String)
But then I couldn't create a table at all and got an error
unspecified value parameter tableName
And how can I query a specific table from the database given the table name?
I tried to Implement this using Map with table name pointing to a table, but it doesnt work because the Map is not saved anywhere and is reset everytime the program starts.
This is what I had for querying a table:
def getDataFromTable(tableName:String)
{
var res = ""
db withSession { implicit session =>
tables(tableName) foreach{
case (id,name)=>
res += id + " " + name + " "
}
}
res
}
Any help is appreciated!
Thanks!
Definition
class Data(tag: Tag, tableName: String)
extends Table[(Int, String)](tag, tableName){
...
Usage
(new TableQuery(Data(_,"table_1"))).ddl.create
(new TableQuery(Data(_,"table_2"))).ddl.create
...
CakePHP version is 2.x. I have a Three Model
1) room_categories(id,title)
2) room_capacities(id,name)
3) room_details(id,name,room_categories_id,room_capacities_id)
This is my controller :
class RoomDetailsController extends AppController {
var $name = "RoomDetails";
function index(){
$this->loadModel('RoomCategory');
$this->loadModel('RoomCapacity');
$roomcategories = $this->RoomCategory->find('list');
$roomcapacities = $this->RoomCapacity->find('list');
$this->set(compact('roomcategories','roomcapacities'));
}
}
In my View File:
echo $this->Form->input('roomcategory');
echo $this->Form->input('roomcapacity');
Drop down is perfect but when i click on button its also give the message to me that save
but when i see the database in room_details the entery of room_categories_id has Zero value as well as room_capacities_id also same value that is Zero
so, plz give me solution for this
room_details table should be:
id
name
room_category_id
room_capacity_id
and in the view file
echo $this->Form->input('room_category_id');
echo $this->Form->input('room_capacity_id');
and in the controller
$roomCategories = $this->RoomCategory->find('list');
$roomCapacities = $this->RoomCapacity->find('list');
$this->set(compact('roomCategories','roomCapacities'));
Sorry for the question title but I can't really find an suitible title.
I use Laravel 3 with Eloquent models (first project in Laravel).
I have an user, list and item model. The user can't fetch any lists, the list can fetch items. But the user can order the items, so the order is saved per user/item.
Will be more clear with following data (simplified for clarity):
Database table:
USER
--------
id
name
LIST
-------
id
name
ITEM
-------
id
list_id
name
USER_ITEM_ORDER
---------------
user_id
item_id
order
List model:
class List extends Eloquent {
public function items() {
return $this->has_many('Item');
}
}
Now I want to use the list model to get all the items based on an user, $list->items($user_id) --> array with items with the user's order.
Can someone show me the way to achieve this?
Please try using this code :
public static function NAMEUserId() {
$query = DB::table('username')
->select(array('users.username', DB::raw('NAME(user's.id) as UserID')))
->join('users', 'items.user_id', '=', 'users.id')
->group_by('users.id')
->order_by('usersid', 'desc')
->get();
return $query;
}
Yeah! I fixed it. :D I'll answer my own question because there is an up vote..
It was pretty easy, just use Fluent on the returned object like this:
public function items($user_id = 0) {
$items = $this->has_many('Item');
// do we need to get the order?
if($user_id != 0) {
$items = $items->left_join('user_item_order', 'items.id', '=', 'user_item_order.item_id')
->where('user_item_order.user_id', '=', $user_id)
->order_by('user_item_order.order', 'asc');
}
return $items->get();
}
I'm a CakePHP newbie. I have been looking for an answer to this for a while.
I followed directions from RichardAtHome in answer regarding autocomplete in CakePHP (autoComplete CakePHP 2.0).
I set up the function in my AppController.
This works very well with real fields but bugged when using Virtual Fields:
class Person extends AppModel {
public $virtualFields = array(
'name' => "CONCAT(Person.firstname, ' ', Person.lastname)"
);
}
I get this error: Column not found: 1054 Unknown column 'Person.name' in 'where clause'
When checking the SQL query I see this:
(CONCAT(`Person`.`firstname`, ' ', `Person`.`lastname`)) AS `Person__name`
This problem only occurs when I use $model = $this->{$this->modelClass}->alias;. Hardcording the model class in a specific controller (not AppController) works fine.
What do I need to do to make it work?
UPDATE:
After fiddling with this I discovered that it doesn't relate to $model = $this->{$this->modelClass}->alias; at all.
Instead I changed the 'conditions' value in the find() method and it all worked out fine. I am still puzzled as to why, but now it works just fine.
Incorrect code:
$result = $this->$model->find('all', array(
'conditions' => array(
$model . '.' . $field . " LIKE '%" . $term . "%'"
)
));
Correct code:
$result = $this->$model->find('all', array(
'conditions' => array(
$model . '.' . $field . " LIKE " => "%" . $term . "%"
)
));
That is an issue of the CakePHP core. You can't use a variable or another property within the declaration of a property. So you have to override the constructor and set your virtual fields there using $this->alias. The core has no automatic way to handle this internally so you have to take care of it.
The issue applies to all model properties by the way. We had the same issue with the $order property of the model. I'll paste the code here but you will have to modify the aliasPrefixing() method to not just go by the start of a string. Replace it by a regex and you should be fine to apply the prefix replacing method to all properties.
/**
* Constructor
*
* #param integer|string|array $id Set this ID for this model on startup, can also be an array of options, see above.
* #param string $table Name of database table to use.
* #param string $ds DataSource connection name.
*/
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->prefixOrderProperty();
}
/**
* Prefixes the order property with the actual alias if its a string or array
*
* The core fails on using the proper prefix when building the query with two
* different tables. Already reported this to the core team and might work on a
* core patch to fix this in the DboSource. The core fix should be done in DboSource,
* when reading the order property from the model.
*
* #return void
*/
public function prefixOrderProperty() {
if (is_string($this->order)) {
$this->order = $this->aliasPrefixing($this->order);
}
if (is_array($this->order)) {
foreach ($this->order as $key => $value) {
$this->order[$key] = $this->aliasPrefixing($value);
}
}
}
/**
* Checks if a string of a field name contains a dot if not it will add it and add the alias prefix
*
* #param string
* #return string
*/
public function aliasPrefixing($string) {
if (stripos($string, '.') === false) {
return $this->alias . '.' . $string;
}
return $string;
}