There must be some misunderstanding with my implementation of the function $get_ship_class -> check_array($category,$cat_in_class = array()); because it's throwing the error:
Fatal error: Uncaught ArgumentCountError: Too few arguments to
function get_ship_class::check_array(), 0 passed in
C:\xampp\htdocs\php_sandbox\assign_ship_class.php on line 60 and at
least 1 expected in
C:\xampp\htdocs\php_sandbox\assign_ship_class.php:45 Stack trace: #0
C:\xampp\htdocs\php_sandbox\assign_ship_class.php(60):
get_ship_class->check_array() #1 {main} thrown in
C:\xampp\htdocs\php_sandbox\assign_ship_class.php on line 45
in response, I tried $get_ship_class->check_array($category, $cat_in_class = array()) and it didn't work.
Essentially the first function get_class_categories() retrieves the product categories under a specific shipping class as an array.
function get_product_category($category) retrieves the category of the current product at hand - we will pretend; set $category = "Monitors" in this case.
Lastly check_array(); just checks if $category = Monitors matches any elements in the list of categories for this shipping class, which was generated by the get_class_categories() function.
<?php
class get_ship_class
{
public function get_class_categories()
{
$csv = array_map("str_getcsv", file("Shipping Classes.csv"));
/*
print_r($csv);
echo "<br />";
*/
$header = array_shift($csv);
// Separate the header from data
/*
print_r($header);
echo "<br />";
*/
$col = array_search("Com1_34-95", $header);
/*
print_r($col);
*/
foreach ($csv as $row) {
$array[] = $row[$col];
}
$cat_in_class = array_filter($array);
print_r($cat_in_class);
//https://stackoverflow.com/a/30909191/9095603
$this->check_array($cat_in_class); // pass array onto function below
}
public function get_product_category()
{
$this->category = 'Monitor';
//echo $this->category;
}
public function check_array($category, $cat_in_class = array())
{
// https://stackoverflow.com/a/6431836/9095603
//$this->category='Monitor';
$this->category;
if (in_array($this->category, $cat_in_class)) {
echo "Match detected!";
}
}
}
$get_ship_class = new get_ship_class();
$get_ship_class->get_product_category('Monitors');
//echo '<br />';
$get_ship_class->get_class_categories();
//echo '<br />';
$get_ship_class->check_array();
I agree with #u_mulder. Regardless, I'm trying to give you an answer.
Your code calls the check_array function twice:
At the end of the get_class_categories function, handing over exactly one argument: $cat_in_class - not TWO
At the end of your php file, handing over null arguments.
I suggest you to perform a code review. Once you have identified the control flow, you should be able to fix it. (Please let getXX functions return a value, if they don't name they setXX and let they write their results to object variables...)
Related
I have this code:
public function taxesData(Product $product)
{
$taxes = \Auth::user()->taxes;
foreach ($taxes as $tax) {
echo "$product->getTax($tax)";
}
}
which on testing gives this error:
Type error: Too few arguments to function App\Product::getTax(), 0 passed in E:\projects\ims\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Concerns\HasAttributes.php on line 411 and exactly 1 expected
However, just a small change makes it works, but I am not able to understand. Why?
public function taxesData(Product $product)
{
$taxes = \Auth::user()->taxes;
foreach ($taxes as $tax) {
echo $product->getTax($tax);
}
}
Please help.
I tried to simplify it for the purpose of posting here... actually i am creating json with html component for a datatable ->
public function taxesData(Product $product)
{
$taxes = \Auth::user()->taxes;
return datatables()
->of($taxes)
->addColumn('check',function($tax) use($product){
if($product->hasTax($tax)){
return "<input type='checkbox' class='input-sm row-checkbox' name='tax[$tax->id]' value='$tax->id' checked>";
}else{
return "<input type='checkbox' class='input-sm row-checkbox' name='tax[$tax->id]' value='$tax->id'>";
}
})
->editColumn('tax', function($tax) use($product){
return "<span class='currencyinput form-control'>
<input id='rate' type='text' name='rate' value='$product->getTax($tax)' required autofocus>
</span>"
})
->toJson();
}
Adding getTax method
public function getTax(Tax $t)
{
if($this->hasTax($t)){
return $this->taxes->find($t->id)->pivot->tax;
}
else{
return $t->pivot->tax;
}
}
public function hasTax(Tax $tax)
{
foreach ($this->taxes as $t) {
if($t->id == $tax->id){
return true;
}
}
return false;
}
It fails because you are not following the correct syntax of echo strings.
This would work:
echo "{$product->getTax($tax)}";
or actually, because you dont' need the quotes for such a simple expression:
echo $product->getTax($tax);
Here's what I've done so far.
Just for simplicity, I've created a sample Model.
// SampleModel.php
public function relatedModels()
{
return $this->hasMany(RelatedModel::class);
}
// this is like an accessor, but since our model doesn't have
// a property called `relatedModels`, Laravel will ignore it
// until later...
public function getRelatedModels()
{
return "Sample";
}
Given the following code, here are the outputs.
$a = SampleModel::find($id);
$a->relatedModels;
// this returns a collection of related models to this model.
$a->getRelatedModels();
// this returns "Sample";
// HOWEVER, when we try to interpolate that member function call.
"$a->getRelatedModels()"
// this throws error that the method `getRelatedModels` must return a relationship.
// I've also tried to add an argument to my existing function to be in-line with your situation.
public function getRelatedModels($a) ...
// this works well
$a->getRelatedModels(1);
// but this, yes, it throws the error as same as what you've got.
"$a->getRelatedModels(1)";
The error pointed out this line in the framework's codebase.
// HasAttributes.php
protected function getRelationshipFromMethod($method)
{
$relation = $this->$method(); // <-- this line
For some reason, doing "$a->getRelatedModels(1)" triggers the __get magic method of the model.
Which branches down to this stack call.
// Model.php
public function __get($key)
{
return $this->getAttribute($key);
}
// |
// V
// HasAttributes.php
public function getAttribute($key)
{
...
return $this->getRelationValue($key);
}
// |
// V
// HasAttributes.php
public function getRelationValue($key)
{
...
if (method_exists($this, $key)) {
return $this->getRelationshipFromMethod($key);
}
}
// |
// V
// HasAttributes.php
protected function getRelationshipFromMethod($method)
{
$relation = $this->$method(); // <-- lastly to this
// $method = "getRelatedModels"
// since our method `getRelatedModels` needs an argument
// this call will fail since it wasn't able to provide an argument.
...
}
That's why you're getting the too few arguments passed exception. I want to investigate further but I have to go home!
I don't know if this is a legit bug for Laravel, but if you do think so, issue it on Laravel's github repository.
UPDATE
I've posted an issue in github and this is one of the comments which truly made sense for me.
This is neither a issue with Laravel, nor with PHP. You are just using the wrong syntax, see it here: https://github.com/laravel/framework/issues/23639
Github user #staudenmeir commented:
"$sampleModel->getRelatedModels()" is equivalent to "$sampleModel->getRelatedModels"."()".
The usage of variables in strings is limited to "$foo" and "$foo->bar". Function calls like "$foo->bar()"
don't work. You can (but shouldn't) use curly braces for that: "{$foo->bar()}"
The better solution is just simple string concatenation:
"text..." . $sampleModel->getRelatedModels() . "more text..."
So that is why the magic method __get is being called.
I'm coding a small piece for a larger project that will read a CSV file and store the information in a class. I'm storing each instance of the class in an array.
So far, all I'm trying to do is read each line of the CSV, create a new class instance with that info, and then display the info using a class function I created.
I have two questions:
first, when building the constructor, I originally tried using $this->$property but I got undefined variable errors for each property when I did that. I took out $this and it seemed to work alright. I'm wondering why $this didn't work there?
And now the error that I'm having is an undefined variable error for each time I try to access a variable to print it out in the displayInfo() function of my class. I don't understand how the variable is undefined, they are properties of the class and they were initialized using the constructor.
Here's my code:
<?php
class Course {
public $crn;
public $title;
public $instructor;
public $section;
public $location;
public $time;
public $days;
function __construct($arg_crn, $arg_title, $arg_instructor, $arg_section, $arg_location, $arg_time, $arg_days) {
$crn = $arg_crn;
$title = $arg_title;
$instructor = $arg_instructor;
$section = $arg_section;
$location = $arg_location;
$time = $arg_time;
$days = $arg_days;
}
public function displayInfo() {
echo ("\n");
echo $crn;
echo (", ");
echo $title;
echo (", ");
echo $instructor;
echo (", ");
echo $section;
echo (", ");
echo $location;
echo (", ");
echo $time;
echo (", ");
echo $days;
echo ("<br/>");
}
}
?>
<?php
$fileName = "testCSV.txt";
$fp = fopen($fileName, "r");
$index = 0;
// get the next line of the CSV: this contains the headers
$fields = fgetcsv($fp);
// get the next line of the CSV, which contains the first course information
// $fields is an array holding each field of the line (where a field is separated by commas)
$fields = fgetcsv($fp);
while($fields) {
// if at the end of the file, fgetcsv returns false and the while loop will not execute
// the fields in the file are saved into the following indices in fields:
// 0: CRN
// 1: Title
// 2: Instructor
// 3: Section
// 4: Location
// 5: Time
// 6: Days
// add a new course to the array of courses using the information from fields
$Courses[$index] = new Course($fields[0], $fields[1], $fields[2], $fields[3], $fields[4], $fields[5], $fields[6]);
$Courses[$index]->displayInfo();
// get the next line and increment index
$fields = fgetcsv($fp);
$index++;
}
?>
As Mark Baker mentioned that instance variable can be accesses using $this->crn, follow the same & read some tutorials on OOPS in PHP as you are too new to this to ask anything here.
You tried accessing properties using $this->$property, which should be $this->property.
Some tutorials:
http://php.net/manual/en/language.oop5.php
http://www.tutorialspoint.com/php/php_object_oriented.htm
I am trying to move over to OOP and have a User class with the following:
<?php
class User {
public function __construct($sdb)
{
$this->sdb = $sdb;
}
// and some other methods
}
?>
I call the class using:
$Users = new User($sdb);
I can then use
echo $Users->GetAdminName($AdminId);
And it shows me the results just fine.
But then further down the page, I call another method named ShowUsers that returns all users from the table.
$results = $Users->ShowUsers();
foreach($results as $result)
{
echo my results ....
}
The issue I am having is that the ShowUsers() method is only showing 1 record instead of all the records.
BUT, if I comment out the top method call
//echo $Users->GetAdminName($AdminId);
It shows all the records and not just one.
I am not sure what I am doing wrong here. Any help is greatly appreciated.
function GetAdminName($AdminId)
{
$this->sdb->limit_val="0,1";
$results = $this->sdb->dbSelect("administrators",array("AdminId","FirstName","LastName"),array("AdminId"=>$AdminId));
foreach($results as $result)
{
$AdminName = $result["FirstName"]." ".$result["LastName"];
}
return $AdminName;
}
function ShowUsers($Status = '')
{
$this->sdb->order_by_column="LastName";
$tables=array("administrators", "roles");
$joins=array("administrators.RoleId=roles.RoleId");
$join_condition=array("INNER JOIN");
$columns=array("AdminId", "AdminEmail", "FirstName", "LastName", "Status", "RoleName");
if($Status)
{
$whereCondition=array("Status"=>"$Status");
}
return $this->sdb->dbSelectJoin($tables,$joins,$join_condition,$columns,$whereCondition);
}
Hi I've recently started yet another project and my boss is insisting that we use the MVC model, the problem being that due to many articles showing different ways to do this we havent managed to agree on what a proper MVC model should look like.
So here's my problem for this project (whether this is the correct way to do it or not) I am using the following baseline rules
Controller classes manage both getting the data from the model classes and passing the data to the view classes and retrieving the view and displaying it
Model classes managhe all database actions and return the data using mysql_fetch_assoc
View classes create the views using the data etc.
So my issue is with processing the information from mysql_fetch_assoc normally you would do something like this (assuming we have already run a query)
while ($row = mysql_fetch_assoc($result)) {
echo $row["username"];
}
but as I'm processing the results in the view class rather than the model how do I cycle through all of the results when I have already passed the assoc array to the view, currently I'm getting a problem where it keeps looping through the results until it hits a memory size error so for some reason it isn't able to figure out how many results it needs to cycle through
My current code snippets are below sorry for the bad explainations.
Controller
require_once 'admin_model.php';
require_once 'admin_view.php';
class admin_controller {
public $model;
public $view;
public function __construct() {
$this->model = new admin_model;
$this->view = new admin_view;
}
public function get_group_view() {
$in_model = $this->model->get_group_view();
$in_view = $this->view->get_group_view ($in_model);
echo $in_view;
}
Model
class admin_model {
public function get_group_view() {
$query = mysql_query("
SELECT
group_id,
group_name
FROM
user_groups
");
return mysql_fetch_assoc($query);
}
}
View
class admin_view {
public function get_group_view($group_data) {
while($group_data) {
$output .= $group_data['group_id'] . '###' . $group_data['group_name'] . '<hr />';
}
return $output;
}
}
Which currently returns the error:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 133693393 bytes)
So can someone please advise me on the best way to go through the results without moving 'mysql_fetch_assoc' function from the model class?
PS I know I'm probably doing MVC completely wrong but it works for us and we don't want to have to research and change our code yet again thanks.
You should not return the MySQL Result - you should do:
$return = array();
$query = mysql_query("SELECT group_id, group_name FROM user_groups");
while($row = mysql_fetch_assoc($query)) {
$return[] = $row;
}
mysql_free_result($row);
return $return;
And you should fix the $group_data bug per #Roman_S . The correct use, along with the above code is
public function get_group_view($group_data) {
$output = '';
foreach($group_data as $group) {
$output .= $group['group_id'] . '###' . $group['group_name'] . '<hr />';
}
return $output;
}
Finally you should migrate to MySQLi or PDO if possible.
You have en error here
while($group_data) {
$output .= $group_data['group_id'] . '###' . $group_data['group_name'] . '<hr />';
}
If $group_data is not empty - your loop will never end.
To give a suggestion on how to handle database control.
When using PDO for instance
$pdoInst = new PDO( .. );
and we have a method somewhere that validates every statement the $pdoInst produces
abstract class .. {
public static function validateStmt($stmt) {
if($stmt !== false) { .. }
// everything else you like, even error handling, log files, etc.
}
}
}
a prepared statement like the get_group_view method will look like the following
public function get_group_view {
$stmt = $pdoInst->prepare(" .. QUERY .. ");
// the return can be wrapped in a method to handle errors, etc, which can be done
// here or else where.
$stmt->execute() // returns true or false
return $stmt;
}
now for iteration
public function get_group_view($group_data) {
$output = "";
// validate the statement, can be done here or else where as said before
if($pdoInst::validateStmt($group_data)) {
// many ways how to iterate, foreach is just one.
foreach($group_data as $index => $group) {
$output .= $group['group_id'] . '###' . $group['group_name'] . '<hr />';
}
}
return $output;
}
The nicest thing about PDO is that you can extend the classes with custom ones. You can add functionality that adds more value to your Model.
I searched forever trying to find an answer, but was ultimately stumped. I've been writing code to allow multiple bots to connect to a chat box. I wrote all the main code and checked it over to make sure it was all okay. Then when I got to calling the function needed to make it work, it gave me an error saying:
Notice: Undefined variable: ip in C:\wamp\www\BotRaid.php on line 40
And also an error saying:
Fatal Error: Cannot access empty property in C:\wamp\www\BotRaid.php
on line 40
( Also a screenshot here: http://prntscr.com/ckz55 )
<?php
date_default_timezone_set("UCT");
declare(ticks=1);
set_time_limit(0);
class BotRaid
{
public $ip="174.36.242.26";
public $port=10038;
public $soc = null;
public $packet = array();
##############################
# You can edit below this #
##############################
public $roomid="155470742";
public $userid = "606657406";
public $k = "2485599605";
public $name="";
public $avatar=;
public $homepage="";
##############################
# Stop editing #
##############################
public function retry()
{
$this->connect($this->$ip,$this->$port); //Line 40, where I'm getting the error now.
$this->join($this->$roomid);
while($this->read()!="DIED");
}
public function connect($ip, $port)
{
if($this->$soc!=null) socket_close($this->$soc);
$soc = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
if(!$this->$soc)$this->port();
if(!socket_connect($this->$soc,$this->$ip,$this->$port))$this->port();
}
public function port()
{
$this->$port++;
if($this->$port>10038) $this->$port=10038;
$this->retry();
}
public function join($roomid)
{
$this->send('<y m="1" />');
$this->read();
$this->send('<j2 q="1" y="'.$this->$packet['y']['i'].'" k="'.$this->$k.'" k3="0" z="12" p="0" c"'.$roomid.'" f="0" u="'.$this->$userid.'" d0="0" n="'.$this->$name.'" a="'.$this->$avatar.'" h="'.$this->$homepage.'" v="0" />');
$this->port();
$this->$roomid;
}
public function send($msg)
{
echo "\n Successfully connected.";
socket_write($this->$soc, $this->$msg."\0", strlen($this->$msg)+1);
}
public function read($parse=true)
{
$res = rtrim(socket_read($this->$soc, 4096));
echo "\nSuccessfully connected.";
if(strpos(strtolower($res), "Failed"))$this->port();
if(!$res) return "DIED";
$this->lastPacket = $res;
if($res{strlen($res)-1}!='>') {$res.=$this->read(false);}
if($parse)$this->parse($res);
return $res;
}
public function parse($packer)
{
$packet=str_replace('+','#più#',str_replace(' ="',' #=#"',$packet));
if(substr_count($packet,'>')>1) $packet = explode('/>',$packet);
foreach((Array)$packet as $p) {
$p = trim($p);
if(strlen($p)<5) return;
$type = trim(strtolower(substr($p,1,strpos($p.' ',' '))));
$p = trim(str_replace("<$type",'',str_replace('/>','',$p)));
parse_str(str_replace('"','',str_replace('" ','&',str_replace('="','=',str_replace('&','__38',$p)))),$this->packet[$type]);
foreach($this->packet[$type] as $k=>$v) {
$this->packet[$type][$k] = str_replace('#più#','+',str_replace('#=#','=',str_replace('__38','&',$v)));
}
}
}
}
$bot = new BotRaid; //This is where I had the error originally
$bot->retry();
?>
Line 40 is below the "Stop Editing" line. Anyone have any suggestions? Or perhaps need me to clear some things up?
You are accessing the properties of the class incorrectly.
The line:
$this->connect($this->$ip,$this->$port);
Should be:
$this->connect($this->ip, $this->port);
Since there was no local variable called $ip, your expression was evaluating to $this-> when trying to access the property since PHP lets you access properties and functions using variables.
For example, this would work:
$ip = 'ip';
$theIp = $this->$ip; // evaluates to $this->ip
// or a function call
$method = 'someFunction';
$value = $this->$method(); // evaluates to $this->someFunction();
You will have to change all the occurrences of $this->$foo with $this->foo since you used that notation throughout the class.
As noted in the comment by #Aatch, see the docs on variable variables for further explanation. But that is what you were running into accidentally.