author id | name
1 Mike
2 Dive
3 Stiv
book id | title
1 ABC
2 War
book_author id_book | id_author
1 1
1 2
2 3
app/models/Book.php
public function getAuthors()
{
return $this->hasMany(Authors::className(), ['id' => 'id_author'])->viaTable('book_author',['id_book' => 'id']);
}
In view:
foreach (Books::findAll([1, 2]) as $book)
{
echo sprintf('%s | %s',
$book->title,implode(', ',
$book->getAuthors()));
}
Always returned implode(): Invalid arguments passed in $book->getAuthors()));
getAuthors() - doesn't choose author, why?
Need:
ABC | Mike, Dive
War | Stiv
$book->getAuthors() get object arrays. You should get simple array. Try this code:
foreach (Books::findAll([1, 2]) as $book)
{
$authors = ArrayHelper::toArray($book->getAuthors()->all(), [
'app\models\Authors' => [
'name', 'id'
]
]);
echo sprintf('%s | %s',
$book->title,implode(', ',
ArrayHelper::map($authors, 'id', 'name')));
}
Related
I have done up a query builder using join. I would like to show table 2, 3, 4, 5, 6 and so on based on the user id on table 1. I tried to query the result, it is showing like this :
My Tables
Table users
user_id | username | email
1 | userA | userA#email.com
2 | userB | userB#gmail.com
Table add_game
game_id | user_id | ign | acc_id
1 | 1 | ignA | accA
2 | 1 | ignB | accB
1 | 2 | ignB | accB
3 | 2 | ignD | accD
I will be using foreach loop and I believe it will display out multiple times based on the records in the database. What should I do if I only want to display the information highlighted in the red box (which is from users table) just 1 time and all the records associated with user id in add_game table?
This is my current code :
Controller
public function login()
{
$data = [];
helper(['form']);
$validation = \Config\Services::validation();
$db = db_connect();
$model = new LoginModel($db);
$user = $model->login($this->request->getVar('userlogin'));
$this->setUserSession($user[0]);
echo view('templates/header', $data, $user);
echo view('account/login', $data, $user);
echo view('templates/footer', $data, $user);
}
private function setUserSession($user){
$data = [
'user_id' => $user['user_id'],
'username' => $user['username'],
'email' => $user['email'],
'firstname' => $user['firstname'],
'lastname' => $user['lastname'],
'dob' => $user['dob'],
'country' => $user['country'],
'country_code' => $user['c_code'],
'contact' => $user['contact'],
'game_id' => $user['game_id'],
'ign' => $user['ign'],
'acc_id' => $user['acc_id'],
'isLoggedIn' => true
];
session()->set($data);
return true;
}
Model:
return $this->db->table('users')
->groupStart()
->where('username', $str)
->orWhere('email', $str)
->groupEnd()
->join('add_game', 'add_game.user_id = users.user_id')
->get()
->getResultArray();
I have a few more tables but not yet created for now so I have only joined 1 table for the time being. What am I missing? Or do I have to loop twice? Is there a way that I just need to loop 1 time? Hope someone can help me out here. Thanks in advance guys!
the easiest way to achieve this (display 2 records from add_game table and 1 record from users table) you need to create a foreach loop in your view, and exclude duplicated data from users table to be shown.
controller:
$data['my_data']=$this->Your_model->your_method(); // your query example
$this->load->view('your_view',$data)
view:
<?php $my_id=0;foreach($my_data as $row):?>
<?php if($my_id!=$row->user_id):?>
<div><?=$row->username?></div> <!--data from table user-->
<div><?=$row->created_at?></div> <!--data from table add_game-->
<?php else:?>
<div><?=$row->created_at?></div> <!--only data from table add_game-->
<?php endif;?>
<?php $my_id=$row->user_id;endforeach;?>
trying to get id from each person
$person = $request->input('person');
//values for person: Murdock,Wayne
$values = explode(',' , $person);
if(count($values) > 1) {
//count($values) = 2
foreach($values as $val) {
$get_id = Tag::where('name', $val)->get();
foreach($get_id as $get) {
echo "id=".$get->id;
$result= FileTags::with('file')->where('tag_id', $get->id)->get();
}
}
}
when i do echo $get->id just getting id=1, when is supossed to be id=1 and id=2
Murdock -- id:1
Wayne -- id:2
|table filetags|
| id | tag_id | file_id |
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 2 | 4 |
| 4 | 3 | 1 |
$result = FileTags::with('file')->where('tag_id', $id->id)->get();
I should get files with id 2,3 and 4
Model TAG
public function fileTag() {
return $this->hasMany('App\FileTags');
}
Model Archive
protected $table = 'files';
public function fileTag() {
return $this->hasMany('App\FileTags');
}
Model FileTags
public function tag() {
return $this->belongsTo('App\Tag' , 'tag_id');
}
public function file() {
return $this->belongsTo('App\Archive', 'file_id');
}
Thanks for the help.
EDIT:
|table tag|
| id | name |
| 1 | Murdock |
| 2 | Wayne |
Result from echo $obt_id;
[{"id":1,"name":"Murdock","description":"Description","type":"0","status":"1","created_at":"2016-07-20 18:01:14","updated_at":"2016-07-20 18:01:14"}][]
from var_dump($obt_id)
array (size=1)
0 =>
object(App\Tag)[267]
protected 'table' => string 'tags' (length=4)
protected 'fillable' =>
array (size=4)
...
protected 'connection' => null
protected 'primaryKey' => string 'id' (length=2)
protected 'keyType' => string 'int' (length=3)
protected 'perPage' => int 15
public 'incrementing' => boolean true
public 'timestamps' => boolean true
protected 'attributes' =>
array (size=7)
...
...
...
C:\wamp64\www\Petro\app\Http\Controllers\CatalogedController.php:53:
object(Illuminate\Database\Eloquent\Collection)[272]
protected 'items' =>
array (size=0)
You could create a Variable, $result; initialize it as an Empty Arrayand then simply push all the Results of evaluating the code: FileTags::with('file')->where('tag_id', $get->id)->get() into that the $result Array. And, in the end, Check if the $result Array is not empty. If it's not, you may simply implode it using comma (Assuming it is a String) and echo your Results...
<?php
$person = $request->input('person');
//values for person: Murdock,Wayne
$values = explode(',' , $person);
$result = array(); // <== INITIALIZE TO AN EMPTY ARRAY...
if(count($values) > 1) { //<== $values NOT values...
//count(values) = 2
foreach($values as trim($val)) { //<== TRY TRIMMING OFF WHITE SPACES.
$get_id = Tag::where('name', $val)->get();
foreach($get_id as $get) {
echo "id=".$get->id;
// PUSH THE DATA INTO THE ARRAY...
$result[] = FileTags::with('file')->where('tag_id', $get->id)->get();
}
}
}
// CHECK IF $result IS NOT EMPTY
if(!empty($result)){
// CONVERT THE ARRAY TO A STRING (ASSUMING ITS CONTENT ARE NOT OBJECTS OR ARRAYS)
$result = implode(", ", $result);
// ECHO OUR YOUR RESULT...
echo $result;
}
I want to have a result like this, to expand all nodes and make a defined treeview.
var defaultData = [
{
text: 'Parent 1',
href: '#parent1',
tags: ['4'],
nodes: [
{
text: 'Child 1',
href: '#child1',
tags: ['2'],
nodes: [
{
text: 'Grandchild 1',
href: '#grandchild1',
tags: ['0']
},
{
text: 'Grandchild 2',
href: '#grandchild2',
tags: ['0']
}
]
},
{
text: 'Child 2',
href: '#child2',
tags: ['0']
}
]
},
{
text: 'Parent 2',
href: '#parent2',
tags: ['0']
},
{
text: 'Parent 3',
href: '#parent3',
tags: ['0']
},
{
text: 'Parent 4',
href: '#parent4',
tags: ['0']
},
{
text: 'Parent 5',
href: '#parent5' ,
tags: ['0']
}
];
I've create a table like this, is it correct?
and how to query them in order to have result as above by json_encode the result?
First of all, you need to fix your table. It is highly irregular and text values will not work well with matching in any language. Try a table like this:
------------------------------
| id | parent | desc |
------------------------------
| 1 | 0 | parent 1 |
------------------------------
| 2 | 0 | parent 2 |
------------------------------
| 3 | 0 | parent 1 |
------------------------------
| 4 | 0 | parent 2 |
------------------------------
| 5 | 0 | parent 1 |
------------------------------
| 6 | 1 | child 1 |
------------------------------
| 7 | 1 | child 2 |
------------------------------
| 8 | 6 | Grandchild 1 |
------------------------------
| 9 | 6 | Grandchild 2 |
------------------------------
id and parent should be integer fields and desc can be text/varchar. Root or top level items should have a parent value of zero (0).
Then you can use a script similar to:
$db = new mysqli('127.0.0.1', 'your_db_user', 'your_secure_password', 'your_db_schema');
if( $mysqli->connect_error ) {
echo 'Something went wrong: ' . $mysqli->connect_error;
}
$json = [];
function sanitize_id($id) {
return preg_replace( '/[^a-z0-9]/', '', strtolower($id) );
}
function recursive( $parentId, &$json ) {
global $mysqli;
if ($stmt = $mysqli->prepare("SELECT * FROM your-table WHERE parent = ?")) {
// Bind parent id to query
$stmt->bind_param('i', $parentId);
$results = $stmt->execute();
// Loop over results
while ( $result = $results->fetch_assoc() ) {
// Add result to JSON structure at referenced location
$json[] = [
'text' => $result['desc'],
'href' => '#' . sanitize_id($result['desc']),
'tags' => ['0'], // Are the tags another field?
'nodes' => []
];
// Rerun recusive function to check for and add any children
recursive( $result['id'], $json['nodes'] );
}
$stmt->close();
}
};
recursive(0, $json);
echo json_encode( $json );
$db->close();
I have a Coupon model in a Many to Many relation with a Product model (with pivot table and so on...). I created some local scope to get only available coupons, and to get only coupons of determined category:
public function scopeAvailable($query)
{
return $query->where('available', '>', 0);
}
public function scopeOfCategory($query, $category)
{
return $query->join('categories', 'categories.id', '=', 'coupons.category_id')
->where('categories.slug', $category);
}
I want to eager load all available coupons of some category with their respective products. So I'm doing:
$coupons = Coupon::with('products')->available()->ofCategory($category)->paginate(20);
If I call $coupons->first(), I can see the information about the coupon. But if I call $coupons->first()->products I get an empty array.
If I comment the ->ofCategory($category) part, it works as expected.
Here is my Models:
class Coupon extends Model
{
public function products()
{
return $this->belongsToMany('App\Product');
}
...
}
class Product extends Model
{
public function coupons()
{
return $this->belongsToMany('App\Coupon');
}
...
}
I'm using Laravel 5.2. What am I doing wrong?
Edit:
It looks like a problem with my Category. If I try to get coupons on "other" category, I got my coupon as expected. If I try to get coupons on "electronics" category, I got a coupon with no products. I'm pretty sure I have coupons with products both on "electronics" and "other" categories.
If I dump Category::where('slug', '=', 'electronics')->first():
...
protected 'attributes' =>
array (size=3)
'id' => int 1
'name' => string 'Electronics' (length=11)
'slug' => string 'electronics' (length=11)
...
If I dump Category::where('slug', '=', 'other')->first():
...
protected 'attributes' =>
array (size=3)
'id' => int 2
'name' => string 'Other' (length=5)
'slug' => string 'other' (length=5)
...
Edit 2:
I created another coupons with "other" category, so I have two coupons with this category. When I print the coupons, it shows the first coupon twice.
Table coupons:
| id | name | available | category_id |
|----|------------|-----------|-------------|
| 1 | Coupon #1 | 1 | 1 |
| 2 | Coupon #2 | 1 | 1 |
| 3 | Coupon #3 | 1 | 1 |
Table products:
| id | name |
|----|-------------|
| 1 | Product #1 |
| 2 | Product #2 |
| 3 | Product #3 |
Table coupon_product:
| id |product_id| coupon_id |
|----|----------|-----------|
| 1 | 1 | 1 |
| 2 | 2 | 1 |
Table categories:
| id | slug |
|----|-------------|
| 1 | category-1 |
| 2 | category-2 |
| 3 | category-3 |
Product.php:
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public function coupons()
{
return $this->belongsToMany('App\Coupon');
}
}
Coupon.php:
class Coupon extends Model
{
public function products()
{
return $this->belongsToMany('App\Product');
}
public function scopeAvailable($query)
{
return $query->where('available', '>', 0);
}
public function scopeOfCategory($query, $category)
{
return $query->join('categories', 'categories.id', '=', 'coupons.category_id')
->where('categories.slug', $category);
}
}
And finally when I run:
$coupons = App\Coupon::with('products')->available()->ofCategory('funny')->first();
dd($coupons->products);
I get this:
Which is correct. Can you post more detailed info about your current state of the project?
I'm new in Yii2. I am using the DepDrop widget provide by Kartik. Now, I can pick data from column1, however, the related data in column2 doesn't show up. I can't even click on it.
Here is partial of the content of mysql table.
ID | name | sub_ID | category
1 | up | 11 | T-shirt
1 | up | 12 | jet
2 | shoe | 21 | nike
2 | shoe | 22 | adidda
Here is my _form.php code
<?= $form->field($model, 'category')->dropDownlist(
ArrayHelper::map(itemcategory::find()->all(), 'ID', 'name'), ['id' => 'cat_id', 'prompt' => 'Select…']
);?>
<?= $form->field($model, 'subcategory')->widget(
DepDrop::classname(), [
'options' => ['id' => 'subcategory', 'placeholder' => 'Select…'],
'pluginOptions' => [
'depends' => ['cat_id'],
'url'=>\yii\helpers\Url::to(['/positemcategory/Subcat'])
]
]
)?>
Here is my model ItemCategory.php code
public function getSubCatList($cat_id)
{
$data = self::find()->where(['ID' => $cat_id])->select(['sub_ID AS id', 'subcategory AS name'])->asArray()->all();
return $data;
}
And here is the controller Itemcategory.php code
public function actionSubcat()
{
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$cat_id = $parents[0];
// $out = \app\models\ItemCategory::getSubCategoryList($cat_id);
$out = self::getSubCatList($cat_id);
echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
I want to let user pick the item by its name, and save only the ID in another table in mysql instead of the full name.
Use ArrayHelper of Yii2.
$out = self::getSubCatList($cat_id);
echo Json::encode(['output'=>ArrayHelper::map($out,'id','name'),'selected'=>'']);
As a result you will get array with id as key and name as value.